Changes in / [838ef08:bf70aa9]
- Location:
- doc/working/exception
- Files:
-
- 4 edited
-
impl/exception.c (modified) (3 diffs)
-
impl/exception.h (modified) (1 diff)
-
impl/test-main.c (modified) (4 diffs)
-
translate.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
doc/working/exception/impl/exception.c
r838ef08 rbf70aa9 22 22 23 23 void __throw_resume(exception except) { 24 25 // DEBUG 26 printf("Throwing resumption exception %d\n", except); 24 void noop() { printf("do nothing\n");} 25 struct __cleanup_hook __blarg __attribute__((cleanup(noop))); 27 26 28 27 struct __try_resume_node * original_head = shared_stack.current_resume; … … 46 45 } 47 46 47 /* __try_resume_node functions: 48 * Currently I was planning to generate this code inline, and even if I don't 49 * putting it in the header so it can be inlined might be worth while. 50 * And if we put them in Cforall code we can use the operators. 51 */ 52 void __try_resume_node_new(struct __try_resume_node * node, 53 _Bool (*handler)(exception except)) { 54 node->next = shared_stack.top_resume; 55 shared_stack.top_resume = node; 56 node->try_to_handle = handler; 57 } 58 59 void __try_resume_node_delete(struct __try_resume_node * node) { 60 shared_stack.top_resume = node->next; 61 } 62 48 63 49 64 // TERMINATION =============================================================== 50 65 51 66 // Requires -fexceptions to work. 52 53 // Global which defines the current exception54 // Currently an int just to make matching easier55 //int this_exception; (became shared_stack.current_exception)56 57 // We need a piece of storage to raise the exception58 struct _Unwind_Exception this_exception_storage;59 60 // Function needed by force unwind61 // It basically says to unwind the whole stack and then exit when we reach the end of the stack62 static _Unwind_Reason_Code _Stop_Fn(63 int version,64 _Unwind_Action actions,65 _Unwind_Exception_Class exceptionClass,66 struct _Unwind_Exception * unwind_exception,67 struct _Unwind_Context * context,68 void * some_param) {69 if( actions & _UA_END_OF_STACK ) exit(1);70 if( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON;71 72 return _URC_FATAL_PHASE2_ERROR;73 }74 75 // Example throw routine76 void __throw_terminate( int val ) {77 // Store the current exception78 shared_stack.current_exception = val;79 80 // DEBUG81 printf("Throwing termination exception %d\n", val);82 83 // Call stdlibc to raise the exception84 _Unwind_Reason_Code ret = _Unwind_RaiseException( &this_exception_storage );85 86 // If we reach here it means something happened87 // For resumption to work we need to find a way to return back to here88 // Most of them will probably boil down to setting a global flag and making the phase 1 either stop or fail.89 // Causing an error on purpose may help avoiding unnecessary work but it might have some weird side effects.90 // If we just pretend no handler was found that would work but may be expensive for no reason since we will always91 // search the whole stack92 93 if( ret == _URC_END_OF_STACK ) {94 // No proper handler was found95 // This can be handled in several way96 // C++ calls std::terminate97 // Here we force unwind the stack, basically raising a cancellation98 printf("Uncaught exception %p\n", &this_exception_storage);99 100 ret = _Unwind_ForcedUnwind( &this_exception_storage, _Stop_Fn, (void*)0x22 );101 printf("UNWIND ERROR %d after force unwind\n", ret);102 abort();103 }104 105 // We did not simply reach the end of the stack without finding a handler,106 // Something wen't wrong107 printf("UNWIND ERROR %d after raise exception\n", ret);108 abort();109 }110 111 // This is our personality routine112 // For every stack frame anotated with ".cfi_personality 0x3,__gcfa_personality_v0"113 // This function will be called twice when unwinding114 // Once in the search phased and once in the cleanup phase115 _Unwind_Reason_Code __gcfa_personality_v0 (116 int version, _Unwind_Action actions, unsigned long long exceptionClass,117 struct _Unwind_Exception* unwind_exception,118 struct _Unwind_Context* context)119 {120 121 // DEBUG122 //printf("CFA: 0x%lx\n", _Unwind_GetCFA(context));123 printf("Personality function (%d, %x, %llu, %p, %p):", version, actions, exceptionClass, unwind_exception, context);124 125 // If we've reached the end of the stack then there is nothing much we can do...126 if( actions & _UA_END_OF_STACK ) return _URC_END_OF_STACK;127 128 // DEBUG129 if (actions & _UA_SEARCH_PHASE) {130 printf(" lookup phase");131 }132 // DEBUG133 else if (actions & _UA_CLEANUP_PHASE) {134 printf(" cleanup phase");135 }136 // Just in case, probably can't actually happen137 else {138 printf(" error\n");139 return _URC_FATAL_PHASE1_ERROR;140 }141 142 // Get a pointer to the language specific data from which we will read what we need143 const unsigned char * lsd = (const unsigned char*) _Unwind_GetLanguageSpecificData( context );144 145 if( !lsd ) { //Nothing to do, keep unwinding146 printf(" no LSD");147 goto UNWIND;148 }149 150 // Get the instuction pointer and a reading pointer into the exception table151 lsda_header_info lsd_info;152 const unsigned char * cur_ptr = parse_lsda_header( context, lsd, &lsd_info);153 _Unwind_Ptr instruction_ptr = _Unwind_GetIP( context );154 155 // Linearly search the table for stuff to do156 while( cur_ptr < lsd_info.action_table ) {157 _Unwind_Ptr callsite_start;158 _Unwind_Ptr callsite_len;159 _Unwind_Ptr callsite_landing_pad;160 _uleb128_t callsite_action;161 162 // Decode the common stuff we have in here163 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_start);164 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_len);165 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_landing_pad);166 cur_ptr = read_uleb128 (cur_ptr, &callsite_action);167 168 // Have we reach the correct frame info yet?169 if( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) {170 //DEBUG BEGIN171 void * ls = (void*)lsd_info.Start;172 void * cs = (void*)callsite_start;173 void * cl = (void*)callsite_len;174 void * bp = (void*)lsd_info.Start + callsite_start;175 void * ep = (void*)lsd_info.Start + callsite_start + callsite_len;176 void * ip = (void*)instruction_ptr;177 printf("\nfound %p - %p (%p, %p, %p), looking for %p\n", bp, ep, ls, cs, cl, ip);178 //DEBUG END179 continue;180 }181 182 // Have we gone too far183 if( lsd_info.Start + callsite_start > instruction_ptr ) {184 printf(" gone too far");185 break;186 }187 188 // Something to do?189 if( callsite_landing_pad ) {190 // Which phase are we in191 if (actions & _UA_SEARCH_PHASE) {192 // Search phase, this means we probably found a potential handler and must check if it is a match193 194 // If we have arbitrarily decided that 0 means nothing to do and 1 means there is a potential handler195 // This doesn't seem to conflict the gcc default behavior196 if (callsite_action != 0) {197 // Now we want to run some code to see if the handler matches198 // This is the tricky part where we want to the power to run arbitrary code199 // However, generating a new exception table entry and try routine every time200 // is way more expansive than we might like201 // The information we have is :202 // - The GR (Series of registers)203 // GR1=GP Global Pointer of frame ref by context204 // - The instruction pointer205 // - The instruction pointer info (???)206 // - The CFA (Canonical Frame Address)207 // - The BSP (Probably the base stack pointer)208 209 210 // The current apprach uses one exception table entry per try block211 _uleb128_t imatcher;212 // Get the relative offset to the213 cur_ptr = read_uleb128 (cur_ptr, &imatcher);214 215 // Get a function pointer from the relative offset and call it216 // _Unwind_Reason_Code (*matcher)() = (_Unwind_Reason_Code (*)())lsd_info.LPStart + imatcher;217 218 _Unwind_Reason_Code (*matcher)() =219 MATCHER_FROM_CONTEXT(context);220 int index = matcher(shared_stack.current_exception);221 _Unwind_Reason_Code ret = (0 == index)222 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;223 shared_stack.current_handler_index = index;224 225 // Based on the return value, check if we matched the exception226 if( ret == _URC_HANDLER_FOUND) printf(" handler found\n");227 else printf(" no handler\n");228 return ret;229 }230 231 // This is only a cleanup handler, ignore it232 printf(" no action");233 }234 else if (actions & _UA_CLEANUP_PHASE) {235 236 if( (callsite_action != 0) && !(actions & _UA_HANDLER_FRAME) ){237 // If this is a potential exception handler238 // but not the one that matched the exception in the seach phase,239 // just ignore it240 goto UNWIND;241 }242 243 // We need to run some clean-up or a handler244 // These statment do the right thing but I don't know any specifics at all245 _Unwind_SetGR( context, __builtin_eh_return_data_regno(0), (_Unwind_Ptr) unwind_exception );246 _Unwind_SetGR( context, __builtin_eh_return_data_regno(1), 0 );247 248 // I assume this sets the instruction pointer to the adress of the landing pad249 // It doesn't actually set it, it only state the value that needs to be set once we return _URC_INSTALL_CONTEXT250 _Unwind_SetIP( context, lsd_info.LPStart + callsite_landing_pad );251 252 // DEBUG253 printf(" action\n");254 255 // Return have some action to run256 return _URC_INSTALL_CONTEXT;257 }258 }259 260 // Nothing to do, move along261 printf(" no landing pad");262 }263 // No handling found264 printf(" table end reached\n");265 266 // DEBUG267 UNWIND:268 printf(" unwind\n");269 270 // Keep unwinding the stack271 return _URC_CONTINUE_UNWIND;272 }273 67 274 68 // Try statements are hoisted out see comments for details … … 347 141 " .size __try_terminate, .-__try_terminate\n" 348 142 " .ident \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n" 349 //" .section .note.GNU-stack,\"x\",@progbits\n"143 " .section .note.GNU-stack,\"x\",@progbits\n" 350 144 ); 145 146 // Global which defines the current exception 147 // Currently an int just to make matching easier 148 int this_exception; 149 150 // We need a piece of storage to raise the exception 151 struct _Unwind_Exception this_exception_storage; 152 153 // Function needed by force unwind 154 // It basically says to unwind the whole stack and then exit when we reach the end of the stack 155 static _Unwind_Reason_Code _Stop_Fn( 156 int version, 157 _Unwind_Action actions, 158 _Unwind_Exception_Class exceptionClass, 159 struct _Unwind_Exception * unwind_exception, 160 struct _Unwind_Context * context, 161 void * some_param) { 162 if( actions & _UA_END_OF_STACK ) exit(1); 163 if( actions & _UA_CLEANUP_PHASE ) return _URC_NO_REASON; 164 165 return _URC_FATAL_PHASE2_ERROR; 166 } 167 168 // Example throw routine 169 void __throw_terminate( int val ) { 170 // Store the current exception 171 this_exception = val; 172 173 // DEBUG 174 printf("Throwing exception %d\n", this_exception); 175 176 // Call stdlibc to raise the exception 177 _Unwind_Reason_Code ret = _Unwind_RaiseException( &this_exception_storage ); 178 179 // If we reach here it means something happened 180 // For resumption to work we need to find a way to return back to here 181 // Most of them will probably boil down to setting a global flag and making the phase 1 either stop or fail. 182 // Causing an error on purpose may help avoiding unnecessary work but it might have some weird side effects. 183 // If we just pretend no handler was found that would work but may be expensive for no reason since we will always 184 // search the whole stack 185 186 if( ret == _URC_END_OF_STACK ) { 187 // No proper handler was found 188 // This can be handled in several way 189 // C++ calls std::terminate 190 // Here we force unwind the stack, basically raising a cancellation 191 printf("Uncaught exception %p\n", &this_exception_storage); 192 193 ret = _Unwind_ForcedUnwind( &this_exception_storage, _Stop_Fn, (void*)0x22 ); 194 printf("UNWIND ERROR %d after force unwind\n", ret); 195 abort(); 196 } 197 198 // We did not simply reach the end of the stack without finding a handler, 199 // Something wen't wrong 200 printf("UNWIND ERROR %d after raise exception\n", ret); 201 abort(); 202 } 203 204 // This is our personality routine 205 // For every stack frame anotated with ".cfi_personality 0x3,__gcfa_personality_v0" 206 // This function will be called twice when unwinding 207 // Once in the search phased and once in the cleanup phase 208 _Unwind_Reason_Code __gcfa_personality_v0 ( 209 int version, _Unwind_Action actions, unsigned long long exceptionClass, 210 struct _Unwind_Exception* unwind_exception, 211 struct _Unwind_Context* context) 212 { 213 printf("CFA: 0x%lx\n", _Unwind_GetCFA(context)); 214 215 // DEBUG 216 printf("Personality function (%d, %x, %llu, %p, %p):", version, actions, exceptionClass, unwind_exception, context); 217 218 // If we've reached the end of the stack then there is nothing much we can do... 219 if( actions & _UA_END_OF_STACK ) return _URC_END_OF_STACK; 220 221 // DEBUG 222 if (actions & _UA_SEARCH_PHASE) { 223 printf(" lookup phase"); 224 } 225 // DEBUG 226 else if (actions & _UA_CLEANUP_PHASE) { 227 printf(" cleanup phase"); 228 } 229 // Just in case, probably can't actually happen 230 else { 231 printf(" error\n"); 232 return _URC_FATAL_PHASE1_ERROR; 233 } 234 235 // Get a pointer to the language specific data from which we will read what we need 236 const unsigned char * lsd = (const unsigned char*) _Unwind_GetLanguageSpecificData( context ); 237 238 if( !lsd ) { //Nothing to do, keep unwinding 239 printf(" no LSD"); 240 goto UNWIND; 241 } 242 243 // Get the instuction pointer and a reading pointer into the exception table 244 lsda_header_info lsd_info; 245 const unsigned char * cur_ptr = parse_lsda_header( context, lsd, &lsd_info); 246 _Unwind_Ptr instruction_ptr = _Unwind_GetIP( context ); 247 248 // Linearly search the table for stuff to do 249 while( cur_ptr < lsd_info.action_table ) { 250 _Unwind_Ptr callsite_start; 251 _Unwind_Ptr callsite_len; 252 _Unwind_Ptr callsite_landing_pad; 253 _uleb128_t callsite_action; 254 255 // Decode the common stuff we have in here 256 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_start); 257 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_len); 258 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_landing_pad); 259 cur_ptr = read_uleb128 (cur_ptr, &callsite_action); 260 261 // Have we reach the correct frame info yet? 262 if( lsd_info.Start + callsite_start + callsite_len < instruction_ptr ) { 263 //DEBUG BEGIN 264 void * ls = (void*)lsd_info.Start; 265 void * cs = (void*)callsite_start; 266 void * cl = (void*)callsite_len; 267 void * bp = (void*)lsd_info.Start + callsite_start; 268 void * ep = (void*)lsd_info.Start + callsite_start + callsite_len; 269 void * ip = (void*)instruction_ptr; 270 printf("\nfound %p - %p (%p, %p, %p), looking for %p\n", bp, ep, ls, cs, cl, ip); 271 //DEBUG END 272 continue; 273 } 274 275 // Have we gone too far 276 if( lsd_info.Start + callsite_start > instruction_ptr ) { 277 printf(" gone too far"); 278 break; 279 } 280 281 // Something to do? 282 if( callsite_landing_pad ) { 283 // Which phase are we in 284 if (actions & _UA_SEARCH_PHASE) { 285 // Search phase, this means we probably found a potential handler and must check if it is a match 286 287 // If we have arbitrarily decided that 0 means nothing to do and 1 means there is a potential handler 288 // This doesn't seem to conflict the gcc default behavior 289 if (callsite_action != 0) { 290 // Now we want to run some code to see if the handler matches 291 // This is the tricky part where we want to the power to run arbitrary code 292 // However, generating a new exception table entry and try routine every time 293 // is way more expansive than we might like 294 // The information we have is : 295 // - The GR (Series of registers) 296 // GR1=GP Global Pointer of frame ref by context 297 // - The instruction pointer 298 // - The instruction pointer info (???) 299 // - The CFA (Canonical Frame Address) 300 // - The BSP (Probably the base stack pointer) 301 302 303 // The current apprach uses one exception table entry per try block 304 _uleb128_t imatcher; 305 // Get the relative offset to the 306 cur_ptr = read_uleb128 (cur_ptr, &imatcher); 307 308 // Get a function pointer from the relative offset and call it 309 // _Unwind_Reason_Code (*matcher)() = (_Unwind_Reason_Code (*)())lsd_info.LPStart + imatcher; 310 311 _Unwind_Reason_Code (*matcher)() = 312 MATCHER_FROM_CONTEXT(context); 313 int index = matcher(shared_stack.current_exception); 314 _Unwind_Reason_Code ret = (0 == index) 315 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; 316 shared_stack.current_handler_index = index; 317 318 319 // Based on the return value, check if we matched the exception 320 if( ret == _URC_HANDLER_FOUND) printf(" handler found\n"); 321 else printf(" no handler\n"); 322 return ret; 323 } 324 325 // This is only a cleanup handler, ignore it 326 printf(" no action"); 327 } 328 else if (actions & _UA_CLEANUP_PHASE) { 329 330 if( (callsite_action != 0) && !(actions & _UA_HANDLER_FRAME) ){ 331 // If this is a potential exception handler 332 // but not the one that matched the exception in the seach phase, 333 // just ignore it 334 goto UNWIND; 335 } 336 337 // We need to run some clean-up or a handler 338 // These statment do the right thing but I don't know any specifics at all 339 _Unwind_SetGR( context, __builtin_eh_return_data_regno(0), (_Unwind_Ptr) unwind_exception ); 340 _Unwind_SetGR( context, __builtin_eh_return_data_regno(1), 0 ); 341 342 // I assume this sets the instruction pointer to the adress of the landing pad 343 // It doesn't actually set it, it only state the value that needs to be set once we return _URC_INSTALL_CONTEXT 344 _Unwind_SetIP( context, lsd_info.LPStart + callsite_landing_pad ); 345 346 // DEBUG 347 printf(" action\n"); 348 349 // Return have some action to run 350 return _URC_INSTALL_CONTEXT; 351 } 352 } 353 354 // Nothing to do, move along 355 printf(" no landing pad"); 356 } 357 // No handling found 358 printf(" table end reached\n"); 359 360 // DEBUG 361 UNWIND: 362 printf(" unwind\n"); 363 364 // Keep unwinding the stack 365 return _URC_CONTINUE_UNWIND; 366 } -
doc/working/exception/impl/exception.h
r838ef08 rbf70aa9 32 32 }; 33 33 34 extern struct shared_stack_t s hared_stack;34 extern struct shared_stack_t stared_stack; -
doc/working/exception/impl/test-main.c
r838ef08 rbf70aa9 1 1 #include "exception.h" 2 2 3 // Use: gcc -fexceptions -Wall -Werror -g exception.c test-main.c4 5 3 #include <stdio.h> 6 #include <stdbool.h>7 4 8 5 // Translation Helpers: … … 10 7 struct __cleanup_hook __hidden_hook __attribute__((cleanup(function))) 11 8 12 #define SET_UP_RESUME_NODE(handler_function) \13 struct __try_resume_node node \14 __attribute__((cleanup(__try_resume_node_delete))); \15 __try_resume_node_new(&node, handler_function)16 17 void __try_resume_node_new(struct __try_resume_node * node,18 _Bool (*handler)(exception except)) {19 node->next = shared_stack.top_resume;20 shared_stack.top_resume = node;21 node->try_to_handle = handler;22 }23 24 void __try_resume_node_delete(struct __try_resume_node * node) {25 shared_stack.top_resume = node->next;26 }27 9 28 10 // Local Print On Exit: … … 37 19 #define raii_t __attribute__((cleanup(raii_dtor))) struct raii_base_type 38 20 39 // ===========================================================================40 21 // Runtime code (post-translation). 41 22 void terminate(int except_value) { … … 53 34 // Termination Test: Two handlers: no catch, catch 54 35 void bar() { 55 raii_t a = {"bar function"}; 56 { 57 void bar_try1() { 58 terminate(4); 36 void bar_try1() { 37 terminate(4); 38 } 39 void bar_catch1(int index, exception except) { 40 switch(except) { 41 case 1: 42 printf("bar caught exception.\n"); 43 break; 44 default: 45 printf("INVALID INDEX in bar: %d\n", except); 59 46 } 60 void bar_catch1(int index, exception except) { 61 switch(except) { 62 case 1: 63 printf("bar caught exception 3.\n"); 64 break; 65 default: 66 printf("INVALID INDEX in bar: %d (%d)\n", index, except); 67 } 47 } 48 int bar_match1(exception except) { 49 if (3 == except) { 50 return 1; 51 } else { 52 return 0; 68 53 } 69 int bar_match1(exception except) {70 if (3 == except) {71 return 1;72 } else {73 return 0;74 }75 }76 __try_terminate(bar_try1, bar_catch1, bar_match1);77 54 } 55 __try_terminate(bar_try1, bar_catch1, bar_match1); 78 56 } 79 57 80 58 void foo() { 81 raii_t a = {"foo function"}; 82 { 83 void foo_try1() { 84 bar(); 59 void foo_try1() { 60 bar(); 61 } 62 void foo_catch1(int index, exception except) { 63 switch(except) { 64 case 1: 65 printf("foo caught exception 4.\n"); 66 break; 67 case 2: 68 printf("foo caught exception 2.\n"); 69 break; 70 default: 71 printf("INVALID INDEX in foo: %d\n", except); 85 72 } 86 void foo_catch1(int index, exception except) { 87 switch(index) { 88 case 1: 89 printf("foo caught exception 4.\n"); 90 break; 91 case 2: 92 printf("foo caught exception 2.\n"); 93 break; 94 default: 95 printf("INVALID INDEX in foo: %d (%d)\n", index, except); 96 } 73 } 74 int foo_match1(exception except) { 75 if (4 == except) { 76 return 1; 77 } else if (2 == except) { 78 return 2; 79 } else { 80 return 0; 97 81 } 98 int foo_match1(exception except) {99 if (4 == except) {100 return 1;101 } else if (2 == except) {102 return 2;103 } else {104 return 0;105 }106 }107 __try_terminate(foo_try1, foo_catch1, foo_match1);108 82 } 83 __try_terminate(foo_try1, foo_catch1, foo_match1); 109 84 } 110 85 111 // Resumption Two Handler Test: no catch, catch.112 void beta() {113 raii_t a = {"beta function"};114 {115 bool beta_handle1(exception except) {116 if (3 == except) {117 printf("beta caught exception 3\n");118 return true;119 } else {120 return false;121 }122 }123 struct __try_resume_node node124 __attribute__((cleanup(__try_resume_node_delete)));125 __try_resume_node_new(&node, beta_handle1);126 {127 resume(4);128 }129 }130 }131 void alpha() {132 raii_t a = {"alpha function"};133 {134 bool alpha_handle1(exception except) {135 if (2 == except) {136 printf("alpha caught exception 2\n");137 return true;138 } else if (4 == except) {139 printf("alpha caught exception 4\n");140 return true;141 } else {142 return false;143 }144 }145 struct __try_resume_node node146 __attribute__((cleanup(__try_resume_node_delete)));147 __try_resume_node_new(&node, alpha_handle1);148 {149 beta();150 }151 }152 }153 154 // Finally Test:155 void farewell() {156 {157 void farewell_finally1() {158 printf("See you next time\n");159 }160 struct __cleanup_hook __hidden_hook161 __attribute__((cleanup(farewell_finally1)));162 {163 printf("walk out of farewell\n");164 }165 }166 }167 168 // Resume-to-Terminate Test:169 void fallback() {170 {171 void fallback_try1() {172 resume(1);173 }174 void fallback_catch1(int index, exception except) {175 switch (index) {176 case 1:177 printf("fallback caught termination 1\n");178 break;179 default:180 printf("INVALID INDEX in fallback: %d (%d)\n", index, except);181 }182 }183 int fallback_match1(exception except) {184 if (1 == except) {185 return 1;186 } else {187 return 0;188 }189 }190 __try_terminate(fallback_try1, fallback_catch1, fallback_match1);191 }192 }193 194 // Terminate Throw New Exception:195 void terminate_swap() {196 raii_t a = {"terminate_swap"};197 {198 void fn_try1() {199 terminate(2);200 }201 void fn_catch1(int index, exception except) {202 switch (index) {203 case 1:204 terminate(1);205 break;206 default:207 printf("INVALID INDEX in terminate_swap: %d (%d)\n",208 index, except);209 }210 }211 int fn_match1(exception except) {212 if (2 == except) {213 return 1;214 } else {215 return 0;216 }217 }218 __try_terminate(fn_try1, fn_catch1, fn_match1);219 }220 }221 222 void terminate_swapped() {223 raii_t a = {"terminate_swapped"};224 {225 void fn_try1() {226 terminate_swap();227 }228 void fn_catch1(int index, exception except) {229 switch (index) {230 case 1:231 printf("terminate_swapped caught exception 1\n");232 break;233 default:234 printf("INVALID INDEX in terminate_swapped: %d (%d)\n",235 index, except);236 }237 }238 int fn_match1(exception except) {239 if (1 == except) {240 return 1;241 } else {242 return 0;243 }244 }245 __try_terminate(fn_try1, fn_catch1, fn_match1);246 }247 }248 249 // Resume Throw New Exception:250 void resume_swap() {251 raii_t a = {"terminate_swap"};252 {253 bool fn_handle1(exception except) {254 if (2 == except) {255 resume(1);256 return true;257 } else {258 return false;259 }260 }261 struct __try_resume_node node262 __attribute__((cleanup(__try_resume_node_delete)));263 __try_resume_node_new(&node, fn_handle1);264 {265 resume(2);266 }267 }268 }269 270 void resume_swapped() {271 {272 bool fn_handle1(exception except) {273 if (1 == except) {274 printf("resume_swapped caught exception 1\n");275 return true;276 } else {277 return false;278 }279 }280 struct __try_resume_node node281 __attribute__((cleanup(__try_resume_node_delete)));282 __try_resume_node_new(&node, fn_handle1);283 {284 resume_swap();285 }286 }287 }288 289 // Terminate Rethrow:290 // I don't have an implementation for this.291 292 // Resume Rethrow:293 void reresume() {294 {295 bool reresume_handle1(exception except) {296 if (1 == except) {297 printf("reresume 1 caught exception 1\n");298 return true;299 } else {300 return false;301 }302 }303 struct __try_resume_node node304 __attribute__((cleanup(__try_resume_node_delete)));305 __try_resume_node_new(&node, reresume_handle1);306 {307 bool reresume_handle2(exception except) {308 if (1 == except) {309 printf("reresume 2 caught and rethrows exception 1\n");310 return false;311 } else {312 return false;313 }314 }315 struct __try_resume_node node316 __attribute__((cleanup(__try_resume_node_delete)));317 __try_resume_node_new(&node, reresume_handle2);318 {319 resume(1);320 }321 }322 }323 }324 325 // Terminate-Resume interaction:326 void fum() {327 // terminate block, call resume328 {329 void fum_try1() {330 resume(3);331 }332 void fum_catch1(int index, exception except) {333 switch (index) {334 case 1:335 printf("fum caught exception 3\n");336 break;337 default:338 printf("INVALID INDEX in fum: %d (%d)\n", index, except);339 }340 }341 int fum_match1(exception except) {342 if (3 == except) {343 return 1;344 } else {345 return 0;346 }347 }348 __try_terminate(fum_try1, fum_catch1, fum_match1);349 }350 }351 352 void foe() {353 // resume block, call terminate354 {355 bool foe_handle1(exception except) {356 if (3 == except) {357 printf("foe caught exception 3\n");358 return true;359 } else {360 return false;361 }362 }363 struct __try_resume_node node364 __attribute__((cleanup(__try_resume_node_delete)));365 __try_resume_node_new(&node, foe_handle1);366 {367 terminate(3);368 }369 }370 }371 372 void fy() {373 // terminate block calls fum, call foe374 {375 void fy_try1() {376 foe();377 }378 void fy_catch1(int index, exception except) {379 switch (index) {380 case 1:381 printf("fy caught exception 3\n");382 fum();383 break;384 default:385 printf("INVALID INDEX in fy: %d (%d)\n", index, except);386 }387 }388 int fy_match1(exception except) {389 if (3 == except) {390 return 1;391 } else {392 return 0;393 }394 }395 __try_terminate(fy_try1, fy_catch1, fy_match1);396 }397 }398 399 void fee() {400 // resume block, call fy401 {402 bool fee_handle1(exception except) {403 if (3 == except) {404 printf("fee caught exception 3\n");405 return true;406 } else {407 return false;408 }409 }410 struct __try_resume_node node411 __attribute__((cleanup(__try_resume_node_delete)));412 __try_resume_node_new(&node, fee_handle1);413 {414 fy();415 }416 }417 }418 419 420 // main: choose which tests to run421 86 int main(int argc, char * argv[]) { 422 87 raii_t a = {"main function"}; 423 88 424 foo(); printf("\n"); 425 alpha(); printf("\n"); 426 farewell(); printf("\n"); 427 fallback(); printf("\n"); 428 terminate_swapped(); printf("\n"); 429 resume_swapped(); printf("\n"); 430 reresume(); printf("\n"); 431 fee(); printf("\n"); 432 // Uncaught termination test. 433 terminate(7); 89 foo(); 434 90 } -
doc/working/exception/translate.c
r838ef08 rbf70aa9 237 237 } 238 238 void finally1() { 239 // Finally, because of timing, also works for resume. 240 // However this might not actually be better in any way. 239 // (Finally, because of timing, also work for resume.) 241 240 __try_resume_cleanup(); 242 241
Note:
See TracChangeset
for help on using the changeset viewer.