- File:
-
- 1 edited
-
src/ControlStruct/ExceptTranslate.cc (modified) (29 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cc
r1abc5ab5 rba912706 10 10 // Created On : Wed Jun 14 16:49:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Jun 2 9 15:18:00 201713 // Update Count : 112 // Last Modified On : Thr Jun 22 15:57:00 2017 13 // Update Count : 0 14 14 // 15 15 16 16 #include "ExceptTranslate.h" 17 17 #include "Common/PassVisitor.h" 18 #include "SynTree/Statement.h"19 #include "SynTree/Declaration.h"20 #include "SynTree/Expression.h"21 #include "SynTree/Type.h"22 #include "SynTree/Attribute.h"23 18 24 19 namespace ControlFlow { … … 39 34 40 35 static void init_func_types() { 41 static boolinit_complete = false;36 static init_complete = false; 42 37 if (init_complete) { 43 38 return; 44 39 } 45 40 ObjectDecl index_obj( 46 " __handler_index",41 "index_t", 47 42 Type::StorageClasses(), 48 43 LinkageSpec::Cforall, … … 52 47 ); 53 48 ObjectDecl exception_obj( 54 " __exception_inst",49 "exception_t", 55 50 Type::StorageClasses(), 56 51 LinkageSpec::Cforall, … … 60 55 ); 61 56 ObjectDecl bool_obj( 62 " __ret_bool",57 "bool_t", 63 58 Type::StorageClasses(), 64 59 LinkageSpec::Cforall, … … 83 78 84 79 void split( CatchList& allHandlers, CatchList& terHandlers, 85 CatchList& resHandlers ) {80 CatchList& resHandlers ) { 86 81 while ( !allHandlers.empty() ) { 87 CatchStmt * stmt = allHandlers.front();82 Statement * stmt = allHandlers.front(); 88 83 allHandlers.pop_front(); 89 if (Ca tchStmt::Terminate == stmt->get_kind()) {84 if (CaseStmt::Terminate == stmt->get_kind()) { 90 85 terHandlers.push_back(stmt); 91 86 } else { … … 97 92 template<typename T> 98 93 void free_all( std::list<T *> &list ) { 99 typenamestd::list<T *>::iterator it;94 std::list<T *>::iterator it; 100 95 for ( it = list.begin() ; it != list.end() ; ++it ) { 101 96 delete *it; … … 105 100 106 101 void appendDeclStmt( CompoundStmt * block, Declaration * item ) { 107 block->push_back(new DeclStmt(no Labels, item));108 } 109 110 Expression * nameOf( DeclarationWithType * decl) {111 return new VariableExpr( decl);102 block->push_back(new DeclStmt(no_labels, item)); 103 } 104 105 Expression * nameOf( FunctionDecl * function ) { 106 return new VariableExpr( function ); 112 107 } 113 108 … … 116 111 Statement * create_terminate_throw( ThrowStmt *throwStmt ) { 117 112 // __throw_terminate( EXPR ); 118 UntypedExpr * call = new UntypedExpr( new NameExpr( 119 "__cfaehm__throw_termination" ) ); 120 call->get_args().push_back( throwStmt->get_expr() ); 113 ApplicationExpr * call = new ApplicationExpr( /* ... */ ); 114 call->get_args.push_back( throwStmt->get_expr() ); 121 115 Statement * result = new ExprStmt( throwStmt->get_labels(), call ); 122 116 throwStmt->set_expr( nullptr ); … … 126 120 Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) { 127 121 // __rethrow_terminate(); 128 assert( nullptr == throwStmt->get_expr() );129 122 Statement * result = new ExprStmt( 130 123 throwStmt->get_labels(), 131 new UntypedExpr( new NameExpr( "__cfaehm__rethrow_termination" ) )124 new ApplicationExpr( /* ... */ ); 132 125 ); 133 126 delete throwStmt; … … 136 129 Statement * create_resume_throw( ThrowStmt *throwStmt ) { 137 130 // __throw_resume( EXPR ); 138 UntypedExpr * call = new UntypedExpr( new NameExpr( 139 "__cfaehm__throw_resumption" ) ); 140 call->get_args().push_back( throwStmt->get_expr() ); 131 ApplicationExpr * call = new ApplicationExpr( /* ... */ ); 132 call->get_args.push_back( throwStmt->get_expr() ); 141 133 Statement * result = new ExprStmt( throwStmt->get_labels(), call ); 142 134 throwStmt->set_expr( nullptr ); … … 148 140 Statement * result = new ReturnStmt( 149 141 throwStmt->get_labels(), 150 new ConstantExpr( Constant::from_bool( false ) ) 142 new ConstantExpr( 143 Constant( 144 new BasicType( 145 Type::Qualifiers(), 146 BasicType::Bool 147 ), 148 "0") 149 ) 151 150 ); 152 151 delete throwStmt; … … 161 160 return block; 162 161 } 163 FunctionDecl * create_try_wrapper( CompoundStmt *body ) { 164 165 return new FunctionDecl( "try", Type::StorageClasses(), 166 LinkageSpec::Cforall, void_func_t.clone(), body ); 162 FunctionDecl * create_try_wrapper( TryStmt *tryStmt ) { 163 CompoundStmt * body = base_try->get_block(); 164 base_try->set_block(nullptr); 165 166 return new FunctionDecl("try", Type::StorageClasses(), 167 LinkageSpec::Cforall, void_func_t, body); 167 168 } 168 169 169 170 FunctionDecl * create_terminate_catch( CatchList &handlers ) { 170 171 std::list<CaseStmt *> handler_wrappers; 171 172 FunctionType *func_type = catch_func_t.clone();173 DeclarationWithType * index_obj = func_type->get_parameters().front();174 // DeclarationWithType * except_obj = func_type->get_parameters().back();175 172 176 173 // Index 1..{number of handlers} … … 181 178 CatchStmt * handler = *it; 182 179 183 // INTEGERconstant Version 184 // case `index`: 185 // { 186 // `handler.body` 187 // } 188 // return; 189 std::list<Statement *> caseBody; 190 caseBody.push_back( handler->get_body() ); 191 handler->set_body( nullptr ); 192 caseBody.push_back( new ReturnStmt( noLabels, nullptr ) ); 193 194 handler_wrappers.push_back( new CaseStmt( 180 std::list<Statement *> core; 181 if ( /*the exception is named*/ ) { 182 ObjectDecl * local_except = /* Dynamic case, same */; 183 core->push_back( new DeclStmt( noLabel, local_except ) ); 184 } 185 // Append the provided statement to the handler. 186 core->push_back( cur_handler->get_body() ); 187 // Append return onto the inner block? case stmt list? 188 CaseStmt * wrapper = new CaseStmt( 195 189 noLabels, 196 190 new ConstantExpr( Constant::from_int( index ) ), 197 caseBody 198 ) ); 191 core 192 ); 193 handler_wrappers.push_back(wrapper); 199 194 } 200 195 // TODO: Some sort of meaningful error on default perhaps? 201 202 std::list<Statement*> stmt_handlers;203 while ( !handler_wrappers.empty() ) {204 stmt_handlers.push_back( handler_wrappers.front() );205 handler_wrappers.pop_front();206 }207 196 208 197 SwitchStmt * handler_lookup = new SwitchStmt( 209 198 noLabels, 210 nameOf( index_obj ), 211 stmt_handlers 199 /*parameter 0: index*/, 200 handler_wrappers, 201 false 212 202 ); 213 203 CompoundStmt * body = new CompoundStmt( noLabels ); … … 215 205 216 206 return new FunctionDecl("catch", Type::StorageClasses(), 217 LinkageSpec::Cforall, func_type, body);207 LinkageSpec::Cforall, catch_func_t, body); 218 208 } 219 209 220 210 // Create a single check from a moddified handler. 221 // except_obj is referenced, modded_handler will be freed. 222 CompoundStmt *create_single_matcher( 223 DeclarationWithType * except_obj, CatchStmt * modded_handler ) { 224 CompoundStmt * block = new CompoundStmt( noLabels ); 225 226 // INTEGERconstant Version 227 assert( nullptr == modded_handler->get_decl() ); 228 ConstantExpr * number = 229 dynamic_cast<ConstantExpr*>( modded_handler->get_cond() ); 230 assert( number ); 231 modded_handler->set_cond( nullptr ); 232 233 Expression * cond; 234 { 235 std::list<Expression *> args; 236 args.push_back( number ); 237 args.push_back( nameOf( except_obj ) ); 238 cond = new UntypedExpr( new NameExpr( "?==?" /*???*/), args ); 239 } 211 CompoundStmt *create_single_matcher( CatchStmt * modded_handler ) { 212 CompoundStmt * block = new CompoundStmt( noLables ); 213 214 appendDeclStmt( block, modded_handler->get_decl() ); 215 216 // TODO: This is not the actual check. 217 LogicalExpr * cond = new ConstantExpr( Constant::from_bool( false ) ); 240 218 241 219 if ( modded_handler->get_cond() ) { 242 cond = new LogicalExpr( cond, modded_handler->get_cond() ) ;220 cond = new LogicalExpr( cond, modded_handler->get_cond() )q 243 221 } 244 222 block->push_back( new IfStmt( noLabels, 245 cond, modded_handler->get_body() , nullptr ));223 cond, modded_handler->get_body() ); 246 224 247 225 modded_handler->set_decl( nullptr ); … … 254 232 FunctionDecl * create_terminate_match( CatchList &handlers ) { 255 233 CompoundStmt * body = new CompoundStmt( noLabels ); 256 257 FunctionType * func_type = match_func_t.clone();258 DeclarationWithType * except_obj = func_type->get_parameters().back();259 234 260 235 // Index 1..{number of handlers} … … 265 240 CatchStmt * handler = *it; 266 241 267 // Body should have been taken by create_terminate_catch. 268 assert( nullptr == handler->get_body() ); 269 270 // Create new body. 242 // body should have been taken by create_terminate_catch. 243 // assert( nullptr == handler->get_body() ); 271 244 handler->set_body( new ReturnStmt( noLabels, 272 245 new ConstantExpr( Constant::from_int( index ) ) ) ); 273 246 274 // Create the handler. 275 body->push_back( create_single_matcher( except_obj, handler ) ); 276 *it = nullptr; 247 body->push_back( create_single_matcher( handler ) ); 277 248 } 278 249 279 250 return new FunctionDecl("match", Type::StorageClasses(), 280 LinkageSpec::Cforall, func_type, body);281 } 282 283 CompoundStmt * create_terminate_caller(251 LinkageSpec::Cforall, match_func_t, body); 252 } 253 254 Statement * create_terminate_caller( 284 255 FunctionDecl * try_wrapper, 285 256 FunctionDecl * terminate_catch, 286 257 FunctionDecl * terminate_match) { 287 258 288 UntypedExpr * caller = new UntypedExpr( new NameExpr( 289 "__cfaehm__try_terminate" ) ); 290 std::list<Expression *>& args = caller->get_args(); 259 ApplicationExpr * caller = new ApplicationExpr( /* ... */ ); 260 std::list<Expression *>& args = caller.get_args(); 291 261 args.push_back( nameOf( try_wrapper ) ); 292 262 args.push_back( nameOf( terminate_catch ) ); 293 263 args.push_back( nameOf( terminate_match ) ); 294 264 295 CompoundStmt * callStmt = new CompoundStmt( noLabels ); 296 callStmt->push_back( new ExprStmt( noLabels, caller ) ); 297 return callStmt; 265 return new ExprStmt( noLabels, caller ); 298 266 } 299 267 300 268 FunctionDecl * create_resume_handler( CatchList &handlers ) { 301 CompoundStmt * body = new CompoundStmt( noLabels ); 302 303 FunctionType * func_type = match_func_t.clone(); 304 DeclarationWithType * except_obj = func_type->get_parameters().back(); 269 CompoundStmt * body = new CompountStmt( noLabels ); 305 270 306 271 CatchList::iterator it; … … 315 280 handling_code->push_back( handler->get_body() ); 316 281 } 317 handling_code->push_back( new ReturnStmt( noLabel s,282 handling_code->push_back( new ReturnStmt( noLabel, 318 283 new ConstantExpr( Constant::from_bool( false ) ) ) ); 319 284 handler->set_body( handling_code ); 320 285 321 286 // Create the handler. 322 body->push_back( create_single_matcher( except_obj, handler ) ); 323 *it = nullptr; 287 body->push_back( create_single_matcher( handler ) ); 324 288 } 325 289 326 290 return new FunctionDecl("handle", Type::StorageClasses(), 327 LinkageSpec::Cforall, func_type, body); 328 } 329 330 CompoundStmt * create_resume_wrapper( 331 StructDecl * node_decl, 291 LinkageSpec::Cforall, handle_func_t, body); 292 } 293 294 Statement * create_resume_wrapper( 332 295 Statement * wraps, 333 296 FunctionDecl * resume_handler ) { 334 297 CompoundStmt * body = new CompoundStmt( noLabels ); 335 298 336 // struct __try_resume_node __resume_node 337 // __attribute__((cleanup( __cfaehm__try_resume_cleanup ))); 338 // ** unwinding of the stack here could cause problems ** 339 // ** however I don't think that can happen currently ** 340 // __cfaehm__try_resume_setup( &__resume_node, resume_handler ); 299 // struct node = {current top resume handler, call to resume_handler}; 300 // __attribute__((cleanup( ... ))); 301 // set top resume handler to node. 302 // The wrapped statement. 303 304 ListInit * node_init; 305 { 306 std::list<Initializer*> field_inits; 307 field_inits.push_back( new SingleInit( /* ... */ ) ); 308 field_inits.push_back( new SingleInit( nameOf( resume_handler ) ) ); 309 node_init = new ListInit( field_inits ); 310 } 341 311 342 312 std::list< Attribute * > attributes; 343 313 { 344 314 std::list< Expression * > attr_params; 345 attr_params.push_back( n ew NameExpr(346 "__cfaehm__try_resume_cleanup") );347 attributes.push_back( new Attribute( "cleanup", attr_params ) );348 } 349 350 ObjectDecl * obj = newObjectDecl(351 " __resume_node",315 attr_params.push_back( nameOf( /* ... deconstructor ... */ ) ); 316 attrributes.push_back( new Attribute( "cleanup", attr_params ) ); 317 } 318 319 appendDeclStmt( body, 320 /**/ ObjectDecl( 321 "resume_node", 352 322 Type::StorageClasses(), 353 323 LinkageSpec::Cforall, 354 324 nullptr, 355 new StructInstType( 356 Type::Qualifiers(), 357 node_decl 358 ), 359 nullptr, 325 /* Type* = resume_node */, 326 node_init, 360 327 attributes 361 ); 362 appendDeclStmt( body, obj ); 363 364 UntypedExpr *setup = new UntypedExpr( new NameExpr( 365 "__cfaehm__try_resume_setup" ) ); 366 setup->get_args().push_back( nameOf( obj ) ); 367 setup->get_args().push_back( nameOf( resume_handler ) ); 368 369 body->push_back( new ExprStmt( noLabels, setup ) ); 370 328 ) 329 ); 371 330 body->push_back( wraps ); 372 331 return body; … … 374 333 375 334 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) { 376 FinallyStmt * finally = tryStmt->get_finally(); 377 CompoundStmt * body = finally->get_block(); 378 finally->set_block( nullptr ); 379 delete finally; 335 CompoundStmt * body = tryStmt->get_finally(); 380 336 tryStmt->set_finally( nullptr ); 381 337 382 338 return new FunctionDecl("finally", Type::StorageClasses(), 383 LinkageSpec::Cforall, void_func_t.clone(), body); 384 } 385 386 ObjectDecl * create_finally_hook( 387 StructDecl * hook_decl, FunctionDecl * finally_wrapper ) { 388 // struct __cfaehm__cleanup_hook __finally_hook 389 // __attribute__((cleanup( finally_wrapper ))); 339 LinkageSpec::Cforall, void_func_t, body); 340 } 341 342 ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper ) { 343 // struct _cleanup_hook NAME __attribute__((cleanup( ... ))); 390 344 391 345 // Make Cleanup Attribute. … … 394 348 std::list< Expression * > attr_params; 395 349 attr_params.push_back( nameOf( finally_wrapper ) ); 396 attr ibutes.push_back( new Attribute( "cleanup", attr_params ) );397 } 398 399 return new ObjectDecl(400 "__finally_hook",350 attrributes.push_back( new Attribute( "cleanup", attr_params ) ); 351 } 352 353 return ObjectDecl( /* ... */ 354 const std::string &name "finally_hook", 401 355 Type::StorageClasses(), 402 356 LinkageSpec::Cforall, 403 357 nullptr, 404 new StructInstType( 405 emptyQualifiers, 406 hook_decl 407 ), 358 /* ... Type * ... */, 408 359 nullptr, 409 360 attributes … … 412 363 413 364 414 class ExceptionMutatorCore : public With Guards{365 class ExceptionMutatorCore : public WithScoping { 415 366 enum Context { NoHandler, TerHandler, ResHandler }; 416 367 … … 419 370 // loop, switch or the goto stays within the function. 420 371 421 Context cur _context;372 Context curContext; 422 373 423 374 // We might not need this, but a unique base for each try block's … … 426 377 //unsigned int try_count = 0; 427 378 428 StructDecl *node_decl;429 StructDecl *hook_decl;430 379 431 380 public: 432 381 ExceptionMutatorCore() : 433 cur_context(NoHandler), 434 node_decl(nullptr), hook_decl(nullptr) 382 curContext(NoHandler) 435 383 {} 436 384 437 void premutate( CatchStmt *catchStmt ); 438 void premutate( StructDecl *structDecl ); 385 void premutate( CatchStmt *tryStmt ); 439 386 Statement * postmutate( ThrowStmt *throwStmt ); 440 387 Statement * postmutate( TryStmt *tryStmt ); … … 446 393 if ( throwStmt->get_expr() ) { 447 394 return create_terminate_throw( throwStmt ); 448 } else if ( TerHandler == cur _context ) {395 } else if ( TerHandler == curContext ) { 449 396 return create_terminate_rethrow( throwStmt ); 450 397 } else { 451 398 assertf(false, "Invalid throw in %s at %i\n", 452 throwStmt->location.filename .c_str(),399 throwStmt->location.filename, 453 400 throwStmt->location.linenumber); 454 401 return nullptr; … … 457 404 if ( throwStmt->get_expr() ) { 458 405 return create_resume_throw( throwStmt ); 459 } else if ( ResHandler == cur _context ) {406 } else if ( ResHandler == curContext ) { 460 407 return create_resume_rethrow( throwStmt ); 461 408 } else { 462 409 assertf(false, "Invalid throwResume in %s at %i\n", 463 throwStmt->location.filename .c_str(),410 throwStmt->location.filename, 464 411 throwStmt->location.linenumber); 465 412 return nullptr; … … 469 416 470 417 Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) { 471 assert( node_decl );472 assert( hook_decl );473 474 418 // Generate a prefix for the function names? 475 419 476 CompoundStmt * block = new CompoundStmt( noLabels);477 CompoundStmt * inner = take_try_block( tryStmt );420 CompoundStmt * block = new CompoundStmt(); 421 Statement * inner = take_try_block( tryStmt ); 478 422 479 423 if ( tryStmt->get_finally() ) { … … 483 427 appendDeclStmt( block, finally_block ); 484 428 // Create and add the finally cleanup hook. 485 appendDeclStmt( block, 486 create_finally_hook( hook_decl, finally_block ) ); 487 } 488 489 CatchList termination_handlers; 490 CatchList resumption_handlers; 491 split( tryStmt->get_catchers(), 492 termination_handlers, resumption_handlers ); 493 494 if ( resumption_handlers.size() ) { 429 appendDeclStmt( block, create_finally_hook( finally_block ) ); 430 } 431 432 StatementList termination_handlers; 433 StatementList resumption_handlers; 434 split( tryStmt->get_handlers(), 435 termination_handlers, resumption_handlers ); 436 437 if ( resumeption_handlers.size() ) { 495 438 // Define the helper function. 496 439 FunctionDecl * resume_handler = … … 498 441 appendDeclStmt( block, resume_handler ); 499 442 // Prepare hooks 500 inner = create_resume_wrapper( node_decl,inner, resume_handler );443 inner = create_resume_wrapper( inner, resume_handler ); 501 444 } 502 445 … … 519 462 block->push_back( inner ); 520 463 521 //free_all( termination_handlers );522 //free_all( resumption_handlers );464 free_all( termination_handlers ); 465 free_all( resumption_handlers ); 523 466 524 467 return block; … … 526 469 527 470 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) { 528 GuardValue( cur _context );529 if ( CatchStmt::Terminat e== catchStmt->get_kind() ) {530 cur _context = TerHandler;471 GuardValue( curContext ); 472 if ( CatchStmt::Termination == catchStmt->get_kind() ) { 473 curContext = TerHandler; 531 474 } else { 532 cur_context = ResHandler; 533 } 534 } 535 536 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) { 537 if ( !structDecl->has_body() ) { 538 // Skip children? 539 return; 540 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) { 541 assert( nullptr == node_decl ); 542 node_decl = structDecl; 543 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) { 544 assert( nullptr == hook_decl ); 545 hook_decl = structDecl; 546 } 547 // Later we might get the exception type as well. 548 } 549 550 void translateEHM( std::list< Declaration *> & translationUnit ) { 551 init_func_types(); 552 475 curContext = ResHandler; 476 } 477 } 478 479 void translateEHM( std::list< Declaration *> & translationUnit ) { 553 480 PassVisitor<ExceptionMutatorCore> translator; 554 481 for ( Declaration * decl : translationUnit ) { 555 decl-> acceptMutator( translator );482 decl->mutate( translator ); 556 483 } 557 484 }
Note:
See TracChangeset
for help on using the changeset viewer.