Changeset 79dbb79
- Timestamp:
- Jul 28, 2017, 2:26:29 PM (7 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 926341c, ea5023c
- Parents:
- 59310bf (diff), 86d5ba7c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cc
r59310bf r79dbb79 10 10 // Created On : Wed Jun 14 16:49:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tus Jul 18 10:09:00 201713 // Update Count : 412 // Last Modified On : Fri Jul 28 14:03:00 2017 13 // Update Count : 5 14 14 // 15 15 … … 21 21 #include "SynTree/Type.h" 22 22 #include "SynTree/Attribute.h" 23 #include "SynTree/VarExprReplacer.h" 23 24 24 25 namespace ControlStruct { 25 26 26 // This (large) section could probably be moved out of the class27 // and be static helpers instead.28 29 // Type(Qualifiers &, false, std::list<Attribute *> &)30 31 27 // void (*function)(); 32 static FunctionType try_func_t( Type::Qualifiers(), false);28 static FunctionType try_func_t(noQualifiers, false); 33 29 // void (*function)(int, exception); 34 static FunctionType catch_func_t( Type::Qualifiers(), false);30 static FunctionType catch_func_t(noQualifiers, false); 35 31 // int (*function)(exception); 36 static FunctionType match_func_t( Type::Qualifiers(), false);32 static FunctionType match_func_t(noQualifiers, false); 37 33 // bool (*function)(exception); 38 static FunctionType handle_func_t( Type::Qualifiers(), false);34 static FunctionType handle_func_t(noQualifiers, false); 39 35 // void (*function)(__attribute__((unused)) void *); 40 static FunctionType finally_func_t( Type::Qualifiers(), false);36 static FunctionType finally_func_t(noQualifiers, false); 41 37 42 38 static void init_func_types() { … … 115 111 } 116 112 117 template<typename T>118 void free_all( std::list<T *> &list ) {119 typename std::list<T *>::iterator it;120 for ( it = list.begin() ; it != list.end() ; ++it ) {121 delete *it;122 }123 list.clear();124 }125 126 113 void appendDeclStmt( CompoundStmt * block, Declaration * item ) { 127 114 block->push_back(new DeclStmt(noLabels, item)); … … 136 123 Statement * create_given_throw( 137 124 const char * throwFunc, ThrowStmt * throwStmt ) { 125 // There is an extra copy here we might be able to remove with 126 // references. 138 127 // { int NAME = EXPR; throwFunc( &NAME ); } 139 128 CompoundStmt * result = new CompoundStmt( noLabels ); … … 159 148 return create_given_throw( "__cfaehm__throw_terminate", throwStmt ); 160 149 } 161 Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) { 162 // __rethrow_terminate(); 150 151 Statement * create_terminate_rethrow( ThrowStmt *throwStmt, 152 ObjectDecl *handler_except_decl ) { 153 // { `handler_except_decl` = NULL; __rethrow_terminate(); } 163 154 assert( nullptr == throwStmt->get_expr() ); 164 Statement * result = new ExprStmt( 165 throwStmt->get_labels(), 155 assert( handler_except_decl ); 156 157 CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() ); 158 result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign( 159 nameOf( handler_except_decl ), 160 new ConstantExpr( Constant::null( 161 new PointerType( 162 noQualifiers, 163 handler_except_decl->get_type()->clone() 164 ) 165 ) ) 166 ) ) ); 167 result->push_back( new ExprStmt( 168 noLabels, 166 169 new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) ) 167 ) ;170 ) ); 168 171 delete throwStmt; 169 172 return result; 170 173 } 174 171 175 Statement * create_resume_throw( ThrowStmt *throwStmt ) { 172 176 // __throw_resume( EXPR ); 173 177 return create_given_throw( "__cfaehm__throw_resume", throwStmt ); 174 178 } 179 175 180 Statement * create_resume_rethrow( ThrowStmt *throwStmt ) { 176 181 // return false; … … 201 206 FunctionType *func_type = catch_func_t.clone(); 202 207 DeclarationWithType * index_obj = func_type->get_parameters().front(); 203 //DeclarationWithType * except_obj = func_type->get_parameters().back();208 DeclarationWithType * except_obj = func_type->get_parameters().back(); 204 209 205 210 // Index 1..{number of handlers} … … 213 218 // case `index`: 214 219 // { 220 // `handler.decl` {inserted} = { except_obj }; 215 221 // `handler.body` 216 222 // } 217 223 // return; 218 std::list<Statement *> caseBody; 219 caseBody.push_back( handler->get_body() ); 224 CompoundStmt * block = new CompoundStmt( noLabels ); 225 226 // Just copy the exception value. 227 // TODO: Or just store an ObjectDecl? 228 ObjectDecl * handler_decl = 229 dynamic_cast<ObjectDecl*>( handler->get_decl() ); 230 assert( handler_decl ); 231 ObjectDecl * local_except = handler_decl->clone(); 232 local_except->set_init( 233 new ListInit({ new SingleInit( nameOf( except_obj ) ) }) ); 234 #if 0 235 // Virtual Exception Vision 236 // case `index`: 237 // { 238 // `handler.decl` = { (virtual `decl.type`)`except` }; 239 // `handler.body`; 240 // } 241 // return; 242 243 // Save a cast copy of the exception (should always succeed). 244 ObjectDecl * local_except = handler->get_decl()->clone(); 245 local_except.set_init( 246 new ListInit({ new SingleInit( 247 new VirtualCastExpr( nameOf( except_obj ), 248 local_except->get_type() 249 ) 250 ) }) ); 251 #endif 252 block->push_back( new DeclStmt( noLabels, local_except ) ); 253 254 // Add the cleanup attribute. 255 local_except->get_attributes().push_back( new Attribute( 256 "cleanup", 257 { new NameExpr( "__cfaehm__cleanup_terminate" ) } 258 ) ); 259 260 // Update variables in the body to point to this local copy. 261 { 262 VarExprReplacer::DeclMap mapping; 263 mapping[ handler_decl ] = local_except; 264 VarExprReplacer mapper( mapping ); 265 handler->get_body()->accept( mapper ); 266 } 267 268 block->push_back( handler->get_body() ); 220 269 handler->set_body( nullptr ); 221 caseBody.push_back( new ReturnStmt( noLabels, nullptr ) ); 222 270 271 std::list<Statement *> caseBody 272 { block, new ReturnStmt( noLabels, nullptr ) }; 223 273 handler_wrappers.push_back( new CaseStmt( 224 274 noLabels, … … 253 303 CompoundStmt * block = new CompoundStmt( noLabels ); 254 304 305 ObjectDecl * local_except = 306 dynamic_cast<ObjectDecl *>( modded_handler->get_decl() ); 307 assert( local_except ); 308 block->push_back( new DeclStmt( noLabels, local_except ) ); 309 #if 0 310 // Virtual Exception Version 311 // { 312 // `modded_handler.decl` 313 // if ( `decl.name = (virtual)`except` 314 // [&& `modded_handler.cond`] ) { 315 // `modded_handler.body` 316 // } 317 // } 318 319 // Check for type match. 320 Expression * cond = UntypedExpr::createAssign( nameOf( local_except ), 321 new VirtualCastExpr( nameOf( except_obj ), 322 local_except->get_type()->clone() ) ); 323 #endif 324 255 325 // INTEGERconstant Version 256 assert( nullptr == modded_handler->get_decl() ); 326 // { 327 // `modded_handler.decl` = *`except` 328 // if ( `decl.name` == `modded_handler.cond` ) { 329 // `modded_handler.body` 330 // } 331 // } 257 332 ConstantExpr * number = 258 333 dynamic_cast<ConstantExpr*>( modded_handler->get_cond() ); … … 274 349 } 275 350 351 // Add the check on the conditional if it is provided. 276 352 if ( modded_handler->get_cond() ) { 277 353 cond = new LogicalExpr( cond, modded_handler->get_cond() ); 278 354 } 355 // Construct the match condition. 279 356 block->push_back( new IfStmt( noLabels, 280 357 cond, modded_handler->get_body(), nullptr ) ); … … 288 365 289 366 FunctionDecl * create_terminate_match( CatchList &handlers ) { 367 // int match(exception * except) { 368 // HANDLER WRAPPERS { return `index`; } 369 // } 370 290 371 CompoundStmt * body = new CompoundStmt( noLabels ); 291 372 … … 323 404 FunctionDecl * terminate_catch, 324 405 FunctionDecl * terminate_match) { 406 // { __cfaehm__try_terminate(`try`, `catch`, `match`); } 325 407 326 408 UntypedExpr * caller = new UntypedExpr( new NameExpr( … … 337 419 338 420 FunctionDecl * create_resume_handler( CatchList &handlers ) { 421 // bool handle(exception * except) { 422 // HANDLER WRAPPERS { `hander->body`; return true; } 423 // } 339 424 CompoundStmt * body = new CompoundStmt( noLabels ); 340 425 … … 415 500 416 501 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) { 502 // void finally() { <finally code> } 417 503 FinallyStmt * finally = tryStmt->get_finally(); 418 504 CompoundStmt * body = finally->get_block(); … … 462 548 Context cur_context; 463 549 550 // The current (innermost) termination handler exception declaration. 551 ObjectDecl * handler_except_decl; 552 464 553 // We might not need this, but a unique base for each try block's 465 554 // generated functions might be nice. … … 473 562 ExceptionMutatorCore() : 474 563 cur_context(NoHandler), 475 node_decl(nullptr), hook_decl(nullptr) 564 handler_except_decl( nullptr ), 565 node_decl( nullptr ), hook_decl( nullptr ) 476 566 {} 477 567 … … 481 571 Statement * postmutate( TryStmt *tryStmt ); 482 572 }; 573 574 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) { 575 // Currently, we make up the declaration, as there isn't one for 576 // integers. 577 ObjectDecl * tmp = new ObjectDecl( 578 "_hidden_local", 579 Type::StorageClasses(), 580 LinkageSpec::Cforall, 581 nullptr, 582 new PointerType( 583 noQualifiers, 584 new BasicType( noQualifiers, BasicType::SignedInt ) 585 ), 586 nullptr 587 ); 588 catchStmt->set_decl( tmp ); 589 590 GuardValue( cur_context ); 591 if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 592 cur_context = TerHandler; 593 594 GuardValue( handler_except_decl ); 595 handler_except_decl = tmp; 596 //handler_except_decl = catchStmt->get_decl(); 597 } else { 598 cur_context = ResHandler; 599 } 600 } 601 602 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) { 603 if ( !structDecl->has_body() ) { 604 // Skip children? 605 return; 606 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) { 607 assert( nullptr == node_decl ); 608 node_decl = structDecl; 609 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) { 610 assert( nullptr == hook_decl ); 611 hook_decl = structDecl; 612 } 613 // Later we might get the exception type as well. 614 } 483 615 484 616 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) { … … 488 620 return create_terminate_throw( throwStmt ); 489 621 } else if ( TerHandler == cur_context ) { 490 return create_terminate_rethrow( throwStmt ); 622 return create_terminate_rethrow( 623 throwStmt, handler_except_decl ); 491 624 } else { 492 625 assertf(false, "Invalid throw in %s at %i\n", … … 560 693 block->push_back( inner ); 561 694 562 //free_all( termination_handlers );563 //free_all( resumption_handlers );564 565 695 return block; 566 }567 568 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {569 GuardValue( cur_context );570 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {571 cur_context = TerHandler;572 } else {573 cur_context = ResHandler;574 }575 }576 577 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {578 if ( !structDecl->has_body() ) {579 // Skip children?580 return;581 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {582 assert( nullptr == node_decl );583 node_decl = structDecl;584 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {585 assert( nullptr == hook_decl );586 hook_decl = structDecl;587 }588 // Later we might get the exception type as well.589 696 } 590 697 -
src/libcfa/exception.c
r59310bf r79dbb79 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Jul 26 10:37:51201713 // Update Count : 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jul 28 12:41:00 2017 13 // Update Count : 3 14 14 // 15 15 … … 33 33 34 34 // Temperary global exception context. Does not work with concurency. 35 struct shared_stack_t {35 struct exception_context_t { 36 36 struct __cfaehm__try_resume_node * top_resume; 37 37 struct __cfaehm__try_resume_node * current_resume; 38 38 39 exception current_exception;39 exception * current_exception; 40 40 int current_handler_index; 41 } shared_stack = {NULL, NULL, 0, 0}; 42 41 42 // Storage to avoid using the heap for exceptions. 43 exception built_in_storage; 44 } shared_stack = {NULL, NULL, 0, 0, 0}; 45 46 // Get the current exception context. 47 // There can be a single global until multithreading occurs, then each stack 48 // needs its own. It will have to be updated to handle that. 49 struct exception_context_t * this_exception_context() { 50 return &shared_stack; 51 } 52 //#define SAVE_EXCEPTION_CONTEXT(to_name) 53 //struct exception_context_t * to_name = this_exception_context(); 54 //exception * this_exception() { 55 // return this_exception_context()->current_exception; 56 //} 43 57 44 58 … … 94 108 // TERMINATION =============================================================== 95 109 96 // Requires -fexceptions to work. 97 98 // Global which defines the current exception. Currently an int just to make matching easier. 99 //int this_exception; (became shared_stack.current_exception) 110 // MEMORY MANAGEMENT (still for integers) 111 // May have to move to cfa for constructors and destructors. 112 113 // Creates a copy of the indicated exception and sets current_exception to it. 114 static void __cfaehm__allocate_exception( exception * except ) { 115 struct exception_context_t * context = this_exception_context(); 116 117 // Try to use the context's store, otherwise use the heap. 118 if ( 0 == context->built_in_storage ) { 119 context->current_exception = &context->built_in_storage; 120 } else { 121 exception * new_copy = malloc( sizeof( exception/*int*/ ) ); 122 if ( ! new_copy ) { 123 // Failure: cannot allocate exception. Terminate thread. 124 exit(1); // <- thread or program? 125 } 126 context->current_exception = new_copy; 127 } 128 129 // Copy the exception to storage. 130 *context->current_exception = *except; 131 } 132 133 // Delete the provided exception, unsetting current_exception if relivant. 134 static void __cfaehm__delete_exception( exception * except ) { 135 struct exception_context_t * context = this_exception_context(); 136 137 // DEBUG 138 printf( "Deleting Exception %d (%s)\n", *except, 139 (&context->built_in_storage == except) ? "builtin" : "dynamic" ); 140 141 if ( context->current_exception == except ) { 142 // TODO: This should restore it to the last exception. 143 context->current_exception = NULL; 144 } 145 if ( &context->built_in_storage == except ) { 146 // You can't throw the exception '0'. 147 context->built_in_storage = 0; 148 } else { 149 // Only secondary or too large exceptions are thrown. 150 free( except ); 151 } 152 } 153 154 // If this isn't a rethrow (*except==0), delete the provided exception. 155 void __cfaehm__cleanup_terminate( exception ** except ) { 156 if ( *except ) __cfaehm__delete_exception( *except ); 157 } 158 100 159 101 160 // We need a piece of storage to raise the exception … … 117 176 } 118 177 119 void __cfaehm__throw_terminate( exception * val ) { 120 // Store the current exception 121 shared_stack.current_exception = *val; 122 123 // DEBUG 124 printf("Throwing termination exception %d\n", *val); 178 // The exception that is being thrown must already be stored. 179 __attribute__((noreturn)) void __cfaehm__begin_unwind(void) { 180 if ( ! this_exception_context()->current_exception ) { 181 printf("UNWIND ERROR missing exception in begin unwind\n"); 182 abort(); 183 } 184 125 185 126 186 // Call stdlibc to raise the exception … … 148 208 } 149 209 150 // Nesting this the other way would probably be faster. 210 void __cfaehm__throw_terminate( exception * val ) { 211 // DEBUG 212 printf("Throwing termination exception\n"); 213 214 __cfaehm__allocate_exception( val ); 215 __cfaehm__begin_unwind(); 216 } 217 151 218 void __cfaehm__rethrow_terminate(void) { 152 219 // DEBUG 153 220 printf("Rethrowing termination exception\n"); 154 221 155 __cfaehm__ throw_terminate(&shared_stack.current_exception);222 __cfaehm__begin_unwind(); 156 223 } 157 224 … … 263 330 _Unwind_Reason_Code (*matcher)(exception *) = 264 331 MATCHER_FROM_CONTEXT(context); 265 int index = matcher( &shared_stack.current_exception);332 int index = matcher(shared_stack.current_exception); 266 333 _Unwind_Reason_Code ret = (0 == index) 267 334 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; … … 359 426 // Exception handler 360 427 catch_block( shared_stack.current_handler_index, 361 &shared_stack.current_exception );428 shared_stack.current_exception ); 362 429 } 363 430 -
src/libcfa/exception.h
r59310bf r79dbb79 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:11:00 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:57:02201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jul 27 12:42:00 2017 13 // Update Count : 4 14 14 // 15 15 16 16 #pragma once 17 17 18 // Later to be a special structure type.19 typedef int exception;20 18 21 19 #ifdef __CFORALL__ 22 20 extern "C" { 23 21 #endif 22 23 #if 1 24 typedef int exception; 25 #else 26 struct exception_t; 27 struct exception_t_vtable { 28 struct exception_t_vtable const * parent; 29 size_t size; 30 void (*copy)(struct exception_t *this, struct exception_t * other); 31 void (*free)(struct exception_t *this); 32 const char (*msg)(struct exception_t *this); 33 }; 34 struct exception_t { 35 struct exception_vtable const * virtual_table; 36 }; 37 typedef struct exception_t exception; 38 #endif 39 24 40 25 41 // Used in throw statement translation. … … 34 50 int (*match_block)(exception * except)); 35 51 52 // Clean-up the exception in catch blocks. 53 void __cfaehm__cleanup_terminate(exception ** except); 54 36 55 // Data structure creates a list of resume handlers. 37 56 struct __cfaehm__try_resume_node { … … 40 59 }; 41 60 61 // These act as constructor and destructor for the resume node. 42 62 void __cfaehm__try_resume_setup( 43 63 struct __cfaehm__try_resume_node * node, … … 47 67 48 68 // Check for a standard way to call fake deconstructors. 49 struct __cfaehm__cleanup_hook { 50 }; 69 struct __cfaehm__cleanup_hook {}; 51 70 52 71 #ifdef __CFORALL__
Note: See TracChangeset
for help on using the changeset viewer.