- File:
-
- 1 edited
-
src/ControlStruct/ExceptTranslate.cc (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cc
r66ba544 r3090127 10 10 // Created On : Wed Jun 14 16:49:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr May 21 13:18:00 202013 // Update Count : 1 512 // 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 Statement * create_resume_rethrow( ThrowStmt * throwStmt ); 75 76 public: 77 ThrowMutatorCore() : 78 terminate_handler_except( nullptr ), 79 cur_context( NoHandler ) 80 {} 81 82 void premutate( CatchStmt *catchStmt ); 83 Statement * postmutate( ThrowStmt *throwStmt ); 84 }; 85 86 // ThrowStmt Mutation Helpers 87 88 Statement * ThrowMutatorCore::create_either_throw( 89 ThrowStmt * throwStmt, const char * throwFunc ) { 90 // `throwFunc`( `throwStmt->get_name()` ); 91 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) ); 92 call->get_args().push_back( throwStmt->get_expr() ); 93 throwStmt->set_expr( nullptr ); 94 delete throwStmt; 95 return new ExprStmt( call ); 96 } 97 98 Statement * ThrowMutatorCore::create_terminate_rethrow( 99 ThrowStmt *throwStmt ) { 100 // { `terminate_handler_except` = 0p; __rethrow_terminate(); } 101 assert( nullptr == throwStmt->get_expr() ); 102 assert( terminate_handler_except ); 103 104 CompoundStmt * result = new CompoundStmt(); 105 result->labels = throwStmt->labels; 106 result->push_back( new ExprStmt( UntypedExpr::createAssign( 107 nameOf( terminate_handler_except ), 108 new ConstantExpr( Constant::null( 109 //new PointerType( 110 // noQualifiers, 111 terminate_handler_except->get_type()->clone() 112 // ) 113 ) ) 114 ) ) ); 115 result->push_back( new ExprStmt( 116 new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) ) 117 ) ); 118 delete throwStmt; 119 return result; 120 } 121 122 Statement * ThrowMutatorCore::create_resume_rethrow( 123 ThrowStmt *throwStmt ) { 124 // return false; 125 Statement * result = new ReturnStmt( 126 new ConstantExpr( Constant::from_bool( false ) ) 127 ); 128 result->labels = throwStmt->labels; 129 delete throwStmt; 130 return result; 131 } 132 133 // Visiting/Mutating Functions 134 135 void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) { 136 // Validate the statement's form. 137 ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() ); 138 // Also checking the type would be nice. 139 if ( decl ) { 140 // Pass. 141 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 142 SemanticError(catchStmt->location, "catch must have exception type"); 143 } else { 144 SemanticError(catchStmt->location, "catchResume must have exception type"); 145 } 146 147 // Track the handler context. 148 GuardValue( cur_context ); 149 if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 150 cur_context = TerHandler; 151 152 GuardValue( terminate_handler_except ); 153 terminate_handler_except = decl; 154 } else { 155 cur_context = ResHandler; 156 } 157 } 158 159 Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) { 160 // Ignoring throwStmt->get_target() for now. 161 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) { 162 if ( throwStmt->get_expr() ) { 163 return create_either_throw( throwStmt, "$throw" ); 164 } else if ( TerHandler == cur_context ) { 165 return create_terminate_rethrow( throwStmt ); 166 } else { 167 abort("Invalid throw in %s at %i\n", 168 throwStmt->location.filename.c_str(), 169 throwStmt->location.first_line); 170 } 171 } else { 172 if ( throwStmt->get_expr() ) { 173 return create_either_throw( throwStmt, "$throwResume" ); 174 } else if ( ResHandler == cur_context ) { 175 return create_resume_rethrow( throwStmt ); 176 } else { 177 abort("Invalid throwResume in %s at %i\n", 178 throwStmt->location.filename.c_str(), 179 throwStmt->location.first_line); 180 } 181 } 182 } 183 184 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 185 78 // The built in types used in translation. 186 79 StructDecl * except_decl; … … 189 82 190 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 ); 191 90 CompoundStmt * take_try_block( TryStmt * tryStmt ); 192 91 FunctionDecl * create_try_wrapper( CompoundStmt * body ); … … 222 121 223 122 public: 224 TryMutatorCore() : 123 ExceptionMutatorCore() : 124 cur_context( NoHandler ), 125 handler_except_decl( nullptr ), 225 126 except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ), 226 127 try_func_t( noQualifiers, false ), … … 231 132 {} 232 133 134 void premutate( CatchStmt *catchStmt ); 233 135 void premutate( StructDecl *structDecl ); 234 136 Statement * postmutate( ThrowStmt *throwStmt ); … … 236 138 }; 237 139 238 void TryMutatorCore::init_func_types() {140 void ExceptionMutatorCore::init_func_types() { 239 141 assert( except_decl ); 240 142 … … 294 196 } 295 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 296 257 // TryStmt Mutation Helpers 297 258 298 CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {259 CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) { 299 260 CompoundStmt * block = tryStmt->get_block(); 300 261 tryStmt->set_block( nullptr ); … … 302 263 } 303 264 304 FunctionDecl * TryMutatorCore::create_try_wrapper(265 FunctionDecl * ExceptionMutatorCore::create_try_wrapper( 305 266 CompoundStmt *body ) { 306 267 … … 309 270 } 310 271 311 FunctionDecl * TryMutatorCore::create_terminate_catch(272 FunctionDecl * ExceptionMutatorCore::create_terminate_catch( 312 273 CatchList &handlers ) { 313 274 std::list<CaseStmt *> handler_wrappers; … … 389 350 // Create a single check from a moddified handler. 390 351 // except_obj is referenced, modded_handler will be freed. 391 CompoundStmt * TryMutatorCore::create_single_matcher(352 CompoundStmt * ExceptionMutatorCore::create_single_matcher( 392 353 DeclarationWithType * except_obj, CatchStmt * modded_handler ) { 393 354 // { … … 427 388 } 428 389 429 FunctionDecl * TryMutatorCore::create_terminate_match(390 FunctionDecl * ExceptionMutatorCore::create_terminate_match( 430 391 CatchList &handlers ) { 431 392 // int match(exception * except) { … … 464 425 } 465 426 466 CompoundStmt * TryMutatorCore::create_terminate_caller(427 CompoundStmt * ExceptionMutatorCore::create_terminate_caller( 467 428 FunctionDecl * try_wrapper, 468 429 FunctionDecl * terminate_catch, … … 482 443 } 483 444 484 FunctionDecl * TryMutatorCore::create_resume_handler(445 FunctionDecl * ExceptionMutatorCore::create_resume_handler( 485 446 CatchList &handlers ) { 486 447 // bool handle(exception * except) { … … 519 480 } 520 481 521 CompoundStmt * TryMutatorCore::create_resume_wrapper(482 CompoundStmt * ExceptionMutatorCore::create_resume_wrapper( 522 483 Statement * wraps, 523 484 FunctionDecl * resume_handler ) { … … 563 524 } 564 525 565 FunctionDecl * TryMutatorCore::create_finally_wrapper(526 FunctionDecl * ExceptionMutatorCore::create_finally_wrapper( 566 527 TryStmt * tryStmt ) { 567 // void finally() { `finally->block`}528 // void finally() { <finally code> } 568 529 FinallyStmt * finally = tryStmt->get_finally(); 569 530 CompoundStmt * body = finally->get_block(); … … 576 537 } 577 538 578 ObjectDecl * TryMutatorCore::create_finally_hook(539 ObjectDecl * ExceptionMutatorCore::create_finally_hook( 579 540 FunctionDecl * finally_wrapper ) { 580 541 // struct __cfaehm_cleanup_hook __finally_hook 581 // __attribute__((cleanup( `finally_wrapper`)));542 // __attribute__((cleanup( finally_wrapper ))); 582 543 583 544 // Make Cleanup Attribute. … … 604 565 605 566 // Visiting/Mutating Functions 606 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 ) { 607 592 if ( !structDecl->has_body() ) { 608 593 // Skip children? … … 619 604 hook_decl = structDecl; 620 605 } 621 } 622 623 Statement * TryMutatorCore::postmutate( ThrowStmt * ) { 624 // All throws should be removed by this point. 625 assert( false ); 626 } 627 628 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 ) { 629 637 assert( except_decl ); 630 638 assert( node_decl ); … … 680 688 } 681 689 682 void translate Throws( std::list< Declaration *> & translationUnit ) {683 PassVisitor< ThrowMutatorCore> translator;690 void translateEHM( std::list< Declaration *> & translationUnit ) { 691 PassVisitor<ExceptionMutatorCore> translator; 684 692 mutateAll( translationUnit, translator ); 685 693 } 686 687 void translateTries( std::list< Declaration *> & translationUnit ) {688 PassVisitor<TryMutatorCore> translator;689 mutateAll( translationUnit, translator );690 }691 694 }
Note:
See TracChangeset
for help on using the changeset viewer.