Changeset 22f94a4 for src/ControlStruct/ExceptTranslate.cc
- Timestamp:
- Aug 11, 2020, 4:40:15 PM (4 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 0d070ca
- Parents:
- 07d867b (diff), 129674b (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cc
r07d867b r22f94a4 10 10 // Created On : Wed Jun 14 16:49:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 27 11:58:00 202013 // Update Count : 1 312 // Last Modified On : Wed Jun 24 11:18:00 2020 13 // Update Count : 17 14 14 // 15 15 … … 64 64 } 65 65 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 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 { 78 168 // The built in types used in translation. 79 169 StructDecl * except_decl; … … 82 172 83 173 // 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 );90 174 CompoundStmt * take_try_block( TryStmt * tryStmt ); 91 175 FunctionDecl * create_try_wrapper( CompoundStmt * body ); … … 101 185 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ); 102 186 ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper ); 187 Statement * create_resume_rethrow( ThrowStmt * throwStmt ); 103 188 104 189 // Types used in translation, make sure to use clone. … … 121 206 122 207 public: 123 ExceptionMutatorCore() : 124 cur_context( NoHandler ), 125 handler_except_decl( nullptr ), 208 TryMutatorCore() : 126 209 except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ), 127 210 try_func_t( noQualifiers, false ), … … 132 215 {} 133 216 134 void premutate( CatchStmt *catchStmt );135 217 void premutate( StructDecl *structDecl ); 218 Statement * postmutate( TryStmt *tryStmt ); 136 219 Statement * postmutate( ThrowStmt *throwStmt ); 137 Statement * postmutate( TryStmt *tryStmt );138 220 }; 139 221 140 void ExceptionMutatorCore::init_func_types() {222 void TryMutatorCore::init_func_types() { 141 223 assert( except_decl ); 142 224 … … 196 278 } 197 279 198 // ThrowStmt Mutation Helpers199 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 257 280 // TryStmt Mutation Helpers 258 281 259 CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {282 CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) { 260 283 CompoundStmt * block = tryStmt->get_block(); 261 284 tryStmt->set_block( nullptr ); … … 263 286 } 264 287 265 FunctionDecl * ExceptionMutatorCore::create_try_wrapper(288 FunctionDecl * TryMutatorCore::create_try_wrapper( 266 289 CompoundStmt *body ) { 267 290 … … 270 293 } 271 294 272 FunctionDecl * ExceptionMutatorCore::create_terminate_catch(295 FunctionDecl * TryMutatorCore::create_terminate_catch( 273 296 CatchList &handlers ) { 274 297 std::list<CaseStmt *> handler_wrappers; … … 350 373 // Create a single check from a moddified handler. 351 374 // except_obj is referenced, modded_handler will be freed. 352 CompoundStmt * ExceptionMutatorCore::create_single_matcher(375 CompoundStmt * TryMutatorCore::create_single_matcher( 353 376 DeclarationWithType * except_obj, CatchStmt * modded_handler ) { 354 377 // { … … 388 411 } 389 412 390 FunctionDecl * ExceptionMutatorCore::create_terminate_match(413 FunctionDecl * TryMutatorCore::create_terminate_match( 391 414 CatchList &handlers ) { 392 415 // int match(exception * except) { … … 425 448 } 426 449 427 CompoundStmt * ExceptionMutatorCore::create_terminate_caller(450 CompoundStmt * TryMutatorCore::create_terminate_caller( 428 451 FunctionDecl * try_wrapper, 429 452 FunctionDecl * terminate_catch, … … 443 466 } 444 467 445 FunctionDecl * ExceptionMutatorCore::create_resume_handler(468 FunctionDecl * TryMutatorCore::create_resume_handler( 446 469 CatchList &handlers ) { 447 470 // bool handle(exception * except) { … … 480 503 } 481 504 482 CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(505 CompoundStmt * TryMutatorCore::create_resume_wrapper( 483 506 Statement * wraps, 484 507 FunctionDecl * resume_handler ) { … … 524 547 } 525 548 526 FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(549 FunctionDecl * TryMutatorCore::create_finally_wrapper( 527 550 TryStmt * tryStmt ) { 528 // void finally() { <finally code>}551 // void finally() { `finally->block` } 529 552 FinallyStmt * finally = tryStmt->get_finally(); 530 553 CompoundStmt * body = finally->get_block(); … … 537 560 } 538 561 539 ObjectDecl * ExceptionMutatorCore::create_finally_hook(562 ObjectDecl * TryMutatorCore::create_finally_hook( 540 563 FunctionDecl * finally_wrapper ) { 541 564 // struct __cfaehm_cleanup_hook __finally_hook 542 // __attribute__((cleanup( finally_wrapper)));565 // __attribute__((cleanup( `finally_wrapper` ))); 543 566 544 567 // Make Cleanup Attribute. … … 564 587 } 565 588 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 566 599 // Visiting/Mutating Functions 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 ) { 600 void TryMutatorCore::premutate( StructDecl *structDecl ) { 592 601 if ( !structDecl->has_body() ) { 593 602 // Skip children? … … 604 613 hook_decl = structDecl; 605 614 } 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 ) { 615 } 616 617 Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) { 637 618 assert( except_decl ); 638 619 assert( node_decl ); … … 688 669 } 689 670 690 void translateEHM( std::list< Declaration *> & translationUnit ) { 691 PassVisitor<ExceptionMutatorCore> translator; 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; 692 679 mutateAll( translationUnit, translator ); 693 680 } 681 682 void translateTries( std::list< Declaration *> & translationUnit ) { 683 PassVisitor<TryMutatorCore> translator; 684 mutateAll( translationUnit, translator ); 685 } 694 686 }
Note: See TracChangeset
for help on using the changeset viewer.