Changes in / [79dbb79:59310bf]
- Location:
- src
- Files:
-
- 1 deleted
- 3 edited
-
ControlStruct/ExceptTranslate.cc (modified) (18 diffs)
-
libcfa/exception.c (modified) (7 diffs)
-
libcfa/exception.h (modified) (4 diffs)
-
tests/except-1.c (deleted)
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cc
r79dbb79 r59310bf 10 10 // Created On : Wed Jun 14 16:49:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jul 28 14:03:00 201713 // Update Count : 512 // Last Modified On : Tus Jul 18 10:09:00 2017 13 // Update Count : 4 14 14 // 15 15 … … 21 21 #include "SynTree/Type.h" 22 22 #include "SynTree/Attribute.h" 23 #include "SynTree/VarExprReplacer.h"24 23 25 24 namespace ControlStruct { 26 25 26 // This (large) section could probably be moved out of the class 27 // and be static helpers instead. 28 29 // Type(Qualifiers &, false, std::list<Attribute *> &) 30 27 31 // void (*function)(); 28 static FunctionType try_func_t( noQualifiers, false);32 static FunctionType try_func_t(Type::Qualifiers(), false); 29 33 // void (*function)(int, exception); 30 static FunctionType catch_func_t( noQualifiers, false);34 static FunctionType catch_func_t(Type::Qualifiers(), false); 31 35 // int (*function)(exception); 32 static FunctionType match_func_t( noQualifiers, false);36 static FunctionType match_func_t(Type::Qualifiers(), false); 33 37 // bool (*function)(exception); 34 static FunctionType handle_func_t( noQualifiers, false);38 static FunctionType handle_func_t(Type::Qualifiers(), false); 35 39 // void (*function)(__attribute__((unused)) void *); 36 static FunctionType finally_func_t( noQualifiers, false);40 static FunctionType finally_func_t(Type::Qualifiers(), false); 37 41 38 42 static void init_func_types() { … … 111 115 } 112 116 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 113 126 void appendDeclStmt( CompoundStmt * block, Declaration * item ) { 114 127 block->push_back(new DeclStmt(noLabels, item)); … … 123 136 Statement * create_given_throw( 124 137 const char * throwFunc, ThrowStmt * throwStmt ) { 125 // There is an extra copy here we might be able to remove with126 // references.127 138 // { int NAME = EXPR; throwFunc( &NAME ); } 128 139 CompoundStmt * result = new CompoundStmt( noLabels ); … … 148 159 return create_given_throw( "__cfaehm__throw_terminate", throwStmt ); 149 160 } 150 151 Statement * create_terminate_rethrow( ThrowStmt *throwStmt, 152 ObjectDecl *handler_except_decl ) { 153 // { `handler_except_decl` = NULL; __rethrow_terminate(); } 161 Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) { 162 // __rethrow_terminate(); 154 163 assert( nullptr == throwStmt->get_expr() ); 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, 164 Statement * result = new ExprStmt( 165 throwStmt->get_labels(), 169 166 new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) ) 170 ) );167 ); 171 168 delete throwStmt; 172 169 return result; 173 170 } 174 175 171 Statement * create_resume_throw( ThrowStmt *throwStmt ) { 176 172 // __throw_resume( EXPR ); 177 173 return create_given_throw( "__cfaehm__throw_resume", throwStmt ); 178 174 } 179 180 175 Statement * create_resume_rethrow( ThrowStmt *throwStmt ) { 181 176 // return false; … … 206 201 FunctionType *func_type = catch_func_t.clone(); 207 202 DeclarationWithType * index_obj = func_type->get_parameters().front(); 208 DeclarationWithType * except_obj = func_type->get_parameters().back();203 // DeclarationWithType * except_obj = func_type->get_parameters().back(); 209 204 210 205 // Index 1..{number of handlers} … … 218 213 // case `index`: 219 214 // { 220 // `handler.decl` {inserted} = { except_obj };221 215 // `handler.body` 222 216 // } 223 217 // return; 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() ); 218 std::list<Statement *> caseBody; 219 caseBody.push_back( handler->get_body() ); 269 220 handler->set_body( nullptr ); 270 271 std::list<Statement *> caseBody 272 { block, new ReturnStmt( noLabels, nullptr ) }; 221 caseBody.push_back( new ReturnStmt( noLabels, nullptr ) ); 222 273 223 handler_wrappers.push_back( new CaseStmt( 274 224 noLabels, … … 303 253 CompoundStmt * block = new CompoundStmt( noLabels ); 304 254 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 0310 // Virtual Exception Version311 // {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 #endif324 325 255 // INTEGERconstant Version 326 // { 327 // `modded_handler.decl` = *`except` 328 // if ( `decl.name` == `modded_handler.cond` ) { 329 // `modded_handler.body` 330 // } 331 // } 256 assert( nullptr == modded_handler->get_decl() ); 332 257 ConstantExpr * number = 333 258 dynamic_cast<ConstantExpr*>( modded_handler->get_cond() ); … … 349 274 } 350 275 351 // Add the check on the conditional if it is provided.352 276 if ( modded_handler->get_cond() ) { 353 277 cond = new LogicalExpr( cond, modded_handler->get_cond() ); 354 278 } 355 // Construct the match condition.356 279 block->push_back( new IfStmt( noLabels, 357 280 cond, modded_handler->get_body(), nullptr ) ); … … 365 288 366 289 FunctionDecl * create_terminate_match( CatchList &handlers ) { 367 // int match(exception * except) {368 // HANDLER WRAPPERS { return `index`; }369 // }370 371 290 CompoundStmt * body = new CompoundStmt( noLabels ); 372 291 … … 404 323 FunctionDecl * terminate_catch, 405 324 FunctionDecl * terminate_match) { 406 // { __cfaehm__try_terminate(`try`, `catch`, `match`); }407 325 408 326 UntypedExpr * caller = new UntypedExpr( new NameExpr( … … 419 337 420 338 FunctionDecl * create_resume_handler( CatchList &handlers ) { 421 // bool handle(exception * except) {422 // HANDLER WRAPPERS { `hander->body`; return true; }423 // }424 339 CompoundStmt * body = new CompoundStmt( noLabels ); 425 340 … … 500 415 501 416 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) { 502 // void finally() { <finally code> }503 417 FinallyStmt * finally = tryStmt->get_finally(); 504 418 CompoundStmt * body = finally->get_block(); … … 548 462 Context cur_context; 549 463 550 // The current (innermost) termination handler exception declaration.551 ObjectDecl * handler_except_decl;552 553 464 // We might not need this, but a unique base for each try block's 554 465 // generated functions might be nice. … … 562 473 ExceptionMutatorCore() : 563 474 cur_context(NoHandler), 564 handler_except_decl( nullptr ), 565 node_decl( nullptr ), hook_decl( nullptr ) 475 node_decl(nullptr), hook_decl(nullptr) 566 476 {} 567 477 … … 571 481 Statement * postmutate( TryStmt *tryStmt ); 572 482 }; 573 574 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {575 // Currently, we make up the declaration, as there isn't one for576 // 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 nullptr587 );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 }615 483 616 484 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) { … … 620 488 return create_terminate_throw( throwStmt ); 621 489 } else if ( TerHandler == cur_context ) { 622 return create_terminate_rethrow( 623 throwStmt, handler_except_decl ); 490 return create_terminate_rethrow( throwStmt ); 624 491 } else { 625 492 assertf(false, "Invalid throw in %s at %i\n", … … 693 560 block->push_back( inner ); 694 561 562 //free_all( termination_handlers ); 563 //free_all( resumption_handlers ); 564 695 565 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. 696 589 } 697 590 -
src/libcfa/exception.c
r79dbb79 r59310bf 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Fri Jul 28 12:41:00201713 // Update Count : 311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 26 10:37:51 2017 13 // Update Count : 2 14 14 // 15 15 … … 33 33 34 34 // Temperary global exception context. Does not work with concurency. 35 struct exception_context_t {35 struct shared_stack_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 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 //} 41 } shared_stack = {NULL, NULL, 0, 0}; 42 57 43 58 44 … … 108 94 // TERMINATION =============================================================== 109 95 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 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) 159 100 160 101 // We need a piece of storage to raise the exception … … 176 117 } 177 118 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 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); 185 125 186 126 // Call stdlibc to raise the exception … … 208 148 } 209 149 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 150 // Nesting this the other way would probably be faster. 218 151 void __cfaehm__rethrow_terminate(void) { 219 152 // DEBUG 220 153 printf("Rethrowing termination exception\n"); 221 154 222 __cfaehm__ begin_unwind();155 __cfaehm__throw_terminate(&shared_stack.current_exception); 223 156 } 224 157 … … 330 263 _Unwind_Reason_Code (*matcher)(exception *) = 331 264 MATCHER_FROM_CONTEXT(context); 332 int index = matcher( shared_stack.current_exception);265 int index = matcher(&shared_stack.current_exception); 333 266 _Unwind_Reason_Code ret = (0 == index) 334 267 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; … … 426 359 // Exception handler 427 360 catch_block( shared_stack.current_handler_index, 428 shared_stack.current_exception );361 &shared_stack.current_exception ); 429 362 } 430 363 -
src/libcfa/exception.h
r79dbb79 r59310bf 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Jun 26 15:11:00 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Fri Jul 27 12:42:00201713 // Update Count : 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:57:02 2017 13 // Update Count : 3 14 14 // 15 15 16 16 #pragma once 17 17 18 // Later to be a special structure type. 19 typedef int exception; 18 20 19 21 #ifdef __CFORALL__ 20 22 extern "C" { 21 23 #endif 22 23 #if 124 typedef int exception;25 #else26 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 #endif39 40 24 41 25 // Used in throw statement translation. … … 50 34 int (*match_block)(exception * except)); 51 35 52 // Clean-up the exception in catch blocks.53 void __cfaehm__cleanup_terminate(exception ** except);54 55 36 // Data structure creates a list of resume handlers. 56 37 struct __cfaehm__try_resume_node { … … 59 40 }; 60 41 61 // These act as constructor and destructor for the resume node.62 42 void __cfaehm__try_resume_setup( 63 43 struct __cfaehm__try_resume_node * node, … … 67 47 68 48 // Check for a standard way to call fake deconstructors. 69 struct __cfaehm__cleanup_hook {}; 49 struct __cfaehm__cleanup_hook { 50 }; 70 51 71 52 #ifdef __CFORALL__
Note:
See TracChangeset
for help on using the changeset viewer.