- File:
-
- 1 edited
-
src/ControlStruct/ExceptTranslate.cc (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cc
r7f9968ad r3090127 10 10 // Created On : Wed Jun 14 16:49:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jun 24 11:18:00 202013 // Update Count : 1 712 // Last Modified On : Fri Mar 27 11:58:00 2020 13 // Update Count : 13 14 14 // 15 15 … … 64 64 } 65 65 66 class ThrowMutatorCore : public WithGuards { 67 ObjectDecl * terminate_handler_except; 68 enum Context { NoHandler, TerHandler, ResHandler } cur_context; 69 70 // The helper functions for code/syntree generation. 71 Statement * create_either_throw( 72 ThrowStmt * throwStmt, const char * throwFunc ); 73 Statement * create_terminate_rethrow( ThrowStmt * throwStmt ); 74 75 public: 76 ThrowMutatorCore() : 77 terminate_handler_except( nullptr ), 78 cur_context( NoHandler ) 79 {} 80 81 void premutate( CatchStmt *catchStmt ); 82 Statement * postmutate( ThrowStmt *throwStmt ); 83 }; 84 85 // ThrowStmt Mutation Helpers 86 87 Statement * ThrowMutatorCore::create_either_throw( 88 ThrowStmt * throwStmt, const char * throwFunc ) { 89 // `throwFunc`( `throwStmt->get_name()` ); 90 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) ); 91 call->get_args().push_back( throwStmt->get_expr() ); 92 throwStmt->set_expr( nullptr ); 93 delete throwStmt; 94 return new ExprStmt( call ); 95 } 96 97 Statement * ThrowMutatorCore::create_terminate_rethrow( 98 ThrowStmt *throwStmt ) { 99 // { `terminate_handler_except` = 0p; __rethrow_terminate(); } 100 assert( nullptr == throwStmt->get_expr() ); 101 assert( terminate_handler_except ); 102 103 CompoundStmt * result = new CompoundStmt(); 104 result->labels = throwStmt->labels; 105 result->push_back( new ExprStmt( UntypedExpr::createAssign( 106 nameOf( terminate_handler_except ), 107 new ConstantExpr( Constant::null( 108 terminate_handler_except->get_type()->clone() 109 ) ) 110 ) ) ); 111 result->push_back( new ExprStmt( 112 new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) ) 113 ) ); 114 delete throwStmt; 115 return result; 116 } 117 118 // Visiting/Mutating Functions 119 120 void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) { 121 // Validate the statement's form. 122 ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() ); 123 // Also checking the type would be nice. 124 if ( !decl || !dynamic_cast<PointerType *>( decl->type ) ) { 125 std::string kind = (CatchStmt::Terminate == catchStmt->kind) ? "catch" : "catchResume"; 126 SemanticError( catchStmt->location, kind + " must have pointer to an exception type" ); 127 } 128 129 // Track the handler context. 130 GuardValue( cur_context ); 131 if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 132 cur_context = TerHandler; 133 134 GuardValue( terminate_handler_except ); 135 terminate_handler_except = decl; 136 } else { 137 cur_context = ResHandler; 138 } 139 } 140 141 Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) { 142 // Ignoring throwStmt->get_target() for now. 143 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) { 144 if ( throwStmt->get_expr() ) { 145 return create_either_throw( throwStmt, "$throw" ); 146 } else if ( TerHandler == cur_context ) { 147 return create_terminate_rethrow( throwStmt ); 148 } else { 149 abort("Invalid throw in %s at %i\n", 150 throwStmt->location.filename.c_str(), 151 throwStmt->location.first_line); 152 } 153 } else { 154 if ( throwStmt->get_expr() ) { 155 return create_either_throw( throwStmt, "$throwResume" ); 156 } else if ( ResHandler == cur_context ) { 157 // This has to be handled later. 158 return throwStmt; 159 } else { 160 abort("Invalid throwResume in %s at %i\n", 161 throwStmt->location.filename.c_str(), 162 throwStmt->location.first_line); 163 } 164 } 165 } 166 167 class TryMutatorCore { 66 class ExceptionMutatorCore : public WithGuards { 67 enum Context { NoHandler, TerHandler, ResHandler }; 68 69 // Also need to handle goto, break & continue. 70 // They need to be cut off in a ResHandler, until we enter another 71 // loop, switch or the goto stays within the function. 72 73 Context cur_context; 74 75 // The current (innermost) termination handler exception declaration. 76 ObjectDecl * handler_except_decl; 77 168 78 // The built in types used in translation. 169 79 StructDecl * except_decl; … … 172 82 173 83 // The many helper functions for code/syntree generation. 84 Statement * create_given_throw( 85 const char * throwFunc, ThrowStmt * throwStmt ); 86 Statement * create_terminate_throw( ThrowStmt * throwStmt ); 87 Statement * create_terminate_rethrow( ThrowStmt * throwStmt ); 88 Statement * create_resume_throw( ThrowStmt * throwStmt ); 89 Statement * create_resume_rethrow( ThrowStmt * throwStmt ); 174 90 CompoundStmt * take_try_block( TryStmt * tryStmt ); 175 91 FunctionDecl * create_try_wrapper( CompoundStmt * body ); … … 185 101 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ); 186 102 ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper ); 187 Statement * create_resume_rethrow( ThrowStmt * throwStmt );188 103 189 104 // Types used in translation, make sure to use clone. … … 206 121 207 122 public: 208 TryMutatorCore() : 123 ExceptionMutatorCore() : 124 cur_context( NoHandler ), 125 handler_except_decl( nullptr ), 209 126 except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ), 210 127 try_func_t( noQualifiers, false ), … … 215 132 {} 216 133 134 void premutate( CatchStmt *catchStmt ); 217 135 void premutate( StructDecl *structDecl ); 136 Statement * postmutate( ThrowStmt *throwStmt ); 218 137 Statement * postmutate( TryStmt *tryStmt ); 219 Statement * postmutate( ThrowStmt *throwStmt );220 138 }; 221 139 222 void TryMutatorCore::init_func_types() {140 void ExceptionMutatorCore::init_func_types() { 223 141 assert( except_decl ); 224 142 … … 278 196 } 279 197 198 // ThrowStmt Mutation Helpers 199 200 Statement * ExceptionMutatorCore::create_given_throw( 201 const char * throwFunc, ThrowStmt * throwStmt ) { 202 // `throwFunc`( `throwStmt->get_name` ); 203 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) ); 204 call->get_args().push_back( throwStmt->get_expr() ); 205 throwStmt->set_expr( nullptr ); 206 delete throwStmt; 207 return new ExprStmt( call ); 208 } 209 210 Statement * ExceptionMutatorCore::create_terminate_throw( 211 ThrowStmt *throwStmt ) { 212 // __throw_terminate( `throwStmt->get_name()` ); } 213 return create_given_throw( "__cfaehm_throw_terminate", throwStmt ); 214 } 215 216 Statement * ExceptionMutatorCore::create_terminate_rethrow( 217 ThrowStmt *throwStmt ) { 218 // { `handler_except_decl` = NULL; __rethrow_terminate(); } 219 assert( nullptr == throwStmt->get_expr() ); 220 assert( handler_except_decl ); 221 222 CompoundStmt * result = new CompoundStmt(); 223 result->labels = throwStmt->labels; 224 result->push_back( new ExprStmt( UntypedExpr::createAssign( 225 nameOf( handler_except_decl ), 226 new ConstantExpr( Constant::null( 227 new PointerType( 228 noQualifiers, 229 handler_except_decl->get_type()->clone() 230 ) 231 ) ) 232 ) ) ); 233 result->push_back( new ExprStmt( 234 new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) ) 235 ) ); 236 delete throwStmt; 237 return result; 238 } 239 240 Statement * ExceptionMutatorCore::create_resume_throw( 241 ThrowStmt *throwStmt ) { 242 // __throw_resume( `throwStmt->get_name` ); 243 return create_given_throw( "__cfaehm_throw_resume", throwStmt ); 244 } 245 246 Statement * ExceptionMutatorCore::create_resume_rethrow( 247 ThrowStmt *throwStmt ) { 248 // return false; 249 Statement * result = new ReturnStmt( 250 new ConstantExpr( Constant::from_bool( false ) ) 251 ); 252 result->labels = throwStmt->labels; 253 delete throwStmt; 254 return result; 255 } 256 280 257 // TryStmt Mutation Helpers 281 258 282 CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {259 CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) { 283 260 CompoundStmt * block = tryStmt->get_block(); 284 261 tryStmt->set_block( nullptr ); … … 286 263 } 287 264 288 FunctionDecl * TryMutatorCore::create_try_wrapper(265 FunctionDecl * ExceptionMutatorCore::create_try_wrapper( 289 266 CompoundStmt *body ) { 290 267 … … 293 270 } 294 271 295 FunctionDecl * TryMutatorCore::create_terminate_catch(272 FunctionDecl * ExceptionMutatorCore::create_terminate_catch( 296 273 CatchList &handlers ) { 297 274 std::list<CaseStmt *> handler_wrappers; … … 373 350 // Create a single check from a moddified handler. 374 351 // except_obj is referenced, modded_handler will be freed. 375 CompoundStmt * TryMutatorCore::create_single_matcher(352 CompoundStmt * ExceptionMutatorCore::create_single_matcher( 376 353 DeclarationWithType * except_obj, CatchStmt * modded_handler ) { 377 354 // { … … 411 388 } 412 389 413 FunctionDecl * TryMutatorCore::create_terminate_match(390 FunctionDecl * ExceptionMutatorCore::create_terminate_match( 414 391 CatchList &handlers ) { 415 392 // int match(exception * except) { … … 448 425 } 449 426 450 CompoundStmt * TryMutatorCore::create_terminate_caller(427 CompoundStmt * ExceptionMutatorCore::create_terminate_caller( 451 428 FunctionDecl * try_wrapper, 452 429 FunctionDecl * terminate_catch, … … 466 443 } 467 444 468 FunctionDecl * TryMutatorCore::create_resume_handler(445 FunctionDecl * ExceptionMutatorCore::create_resume_handler( 469 446 CatchList &handlers ) { 470 447 // bool handle(exception * except) { … … 503 480 } 504 481 505 CompoundStmt * TryMutatorCore::create_resume_wrapper(482 CompoundStmt * ExceptionMutatorCore::create_resume_wrapper( 506 483 Statement * wraps, 507 484 FunctionDecl * resume_handler ) { … … 547 524 } 548 525 549 FunctionDecl * TryMutatorCore::create_finally_wrapper(526 FunctionDecl * ExceptionMutatorCore::create_finally_wrapper( 550 527 TryStmt * tryStmt ) { 551 // void finally() { `finally->block`}528 // void finally() { <finally code> } 552 529 FinallyStmt * finally = tryStmt->get_finally(); 553 530 CompoundStmt * body = finally->get_block(); … … 560 537 } 561 538 562 ObjectDecl * TryMutatorCore::create_finally_hook(539 ObjectDecl * ExceptionMutatorCore::create_finally_hook( 563 540 FunctionDecl * finally_wrapper ) { 564 541 // struct __cfaehm_cleanup_hook __finally_hook 565 // __attribute__((cleanup( `finally_wrapper`)));542 // __attribute__((cleanup( finally_wrapper ))); 566 543 567 544 // Make Cleanup Attribute. … … 587 564 } 588 565 589 Statement * TryMutatorCore::create_resume_rethrow( ThrowStmt *throwStmt ) {590 // return false;591 Statement * result = new ReturnStmt(592 new ConstantExpr( Constant::from_bool( false ) )593 );594 result->labels = throwStmt->labels;595 delete throwStmt;596 return result;597 }598 599 566 // Visiting/Mutating Functions 600 void TryMutatorCore::premutate( StructDecl *structDecl ) { 567 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) { 568 // Validate the Statement's form. 569 ObjectDecl * decl = 570 dynamic_cast<ObjectDecl *>( catchStmt->get_decl() ); 571 if ( decl && true /* check decl->get_type() */ ) { 572 // Pass. 573 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 574 SemanticError(catchStmt->location, "catch must have exception type"); 575 } else { 576 SemanticError(catchStmt->location, "catchResume must have exception type"); 577 } 578 579 // Track the handler context. 580 GuardValue( cur_context ); 581 if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 582 cur_context = TerHandler; 583 584 GuardValue( handler_except_decl ); 585 handler_except_decl = decl; 586 } else { 587 cur_context = ResHandler; 588 } 589 } 590 591 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) { 601 592 if ( !structDecl->has_body() ) { 602 593 // Skip children? … … 613 604 hook_decl = structDecl; 614 605 } 615 } 616 617 Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) { 606 // Later we might get the exception type as well. 607 } 608 609 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) { 610 assert( except_decl ); 611 612 // Ignoring throwStmt->get_target() for now. 613 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) { 614 if ( throwStmt->get_expr() ) { 615 return create_terminate_throw( throwStmt ); 616 } else if ( TerHandler == cur_context ) { 617 return create_terminate_rethrow( throwStmt ); 618 } else { 619 abort("Invalid throw in %s at %i\n", 620 throwStmt->location.filename.c_str(), 621 throwStmt->location.first_line); 622 } 623 } else { 624 if ( throwStmt->get_expr() ) { 625 return create_resume_throw( throwStmt ); 626 } else if ( ResHandler == cur_context ) { 627 return create_resume_rethrow( throwStmt ); 628 } else { 629 abort("Invalid throwResume in %s at %i\n", 630 throwStmt->location.filename.c_str(), 631 throwStmt->location.first_line); 632 } 633 } 634 } 635 636 Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) { 618 637 assert( except_decl ); 619 638 assert( node_decl ); … … 669 688 } 670 689 671 Statement * TryMutatorCore::postmutate( ThrowStmt *throwStmt ) { 672 // Only valid `throwResume;` statements should remain. (2/3 checks) 673 assert( ThrowStmt::Resume == throwStmt->kind && ! throwStmt->expr ); 674 return create_resume_rethrow( throwStmt ); 675 } 676 677 void translateThrows( std::list< Declaration *> & translationUnit ) { 678 PassVisitor<ThrowMutatorCore> translator; 690 void translateEHM( std::list< Declaration *> & translationUnit ) { 691 PassVisitor<ExceptionMutatorCore> translator; 679 692 mutateAll( translationUnit, translator ); 680 693 } 681 682 void translateTries( std::list< Declaration *> & translationUnit ) {683 PassVisitor<TryMutatorCore> translator;684 mutateAll( translationUnit, translator );685 }686 694 }
Note:
See TracChangeset
for help on using the changeset viewer.