source: src/ControlStruct/ExceptTranslate.cc@ af4903b

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since af4903b was 948b0c8, checked in by Andrew Beach <ajbeach@…>, 8 years ago

Reorginization of ExceptTranslate to make the next steps easier.

  • Property mode set to 100644
File size: 22.3 KB
RevLine 
[ba912706]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ExceptVisitor.cc --
8//
9// Author : Andrew Beach
10// Created On : Wed Jun 14 16:49:00 2017
11// Last Modified By : Andrew Beach
[948b0c8]12// Last Modified On : Wed Aug 02 12:09:00 2017
13// Update Count : 7
[ba912706]14//
15
16#include "ExceptTranslate.h"
17#include "Common/PassVisitor.h"
[288eede]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"
[86d5ba7c]23#include "SynTree/VarExprReplacer.h"
[ba912706]24
[307a732]25namespace ControlStruct {
[ba912706]26
[948b0c8]27 // Buricratic Helpers (Not having to do with the paritular operation.)
28
29 typedef std::list<CatchStmt*> CatchList;
30
31 void split( CatchList& allHandlers, CatchList& terHandlers,
32 CatchList& resHandlers ) {
33 while ( !allHandlers.empty() ) {
34 CatchStmt * stmt = allHandlers.front();
35 allHandlers.pop_front();
36 if (CatchStmt::Terminate == stmt->get_kind()) {
37 terHandlers.push_back(stmt);
38 } else {
39 resHandlers.push_back(stmt);
40 }
41 }
42 }
43
44 void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
45 block->push_back(new DeclStmt(noLabels, item));
46 }
47
48 Expression * nameOf( DeclarationWithType * decl ) {
49 return new VariableExpr( decl );
50 }
51
52 class ExceptionMutatorCore : public WithGuards {
53 enum Context { NoHandler, TerHandler, ResHandler };
54
55 // Also need to handle goto, break & continue.
56 // They need to be cut off in a ResHandler, until we enter another
57 // loop, switch or the goto stays within the function.
58
59 Context cur_context;
60
61 // The current (innermost) termination handler exception declaration.
62 ObjectDecl * handler_except_decl;
63
64 // The built in types used in translation.
65 StructDecl * except_decl;
66 StructDecl * node_decl;
67 StructDecl * hook_decl;
68
69 // The many helper functions for code/syntree generation.
70 Statement * create_given_throw(
71 const char * throwFunc, ThrowStmt * throwStmt );
72 Statement * create_terminate_throw( ThrowStmt * throwStmt );
73 Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
74 Statement * create_resume_throw( ThrowStmt * throwStmt );
75 Statement * create_resume_rethrow( ThrowStmt * throwStmt );
76 CompoundStmt * take_try_block( TryStmt * tryStmt );
77 FunctionDecl * create_try_wrapper( CompoundStmt * body );
78 FunctionDecl * create_terminate_catch( CatchList &handlers );
79 CompoundStmt * create_single_matcher(
80 DeclarationWithType * except_obj, CatchStmt * modded_handler );
81 FunctionDecl * create_terminate_match( CatchList &handlers );
82 CompoundStmt * create_terminate_caller( FunctionDecl * try_wrapper,
83 FunctionDecl * terminate_catch, FunctionDecl * terminate_match );
84 FunctionDecl * create_resume_handler( CatchList &handlers );
85 CompoundStmt * create_resume_wrapper(
86 Statement * wraps, FunctionDecl * resume_handler );
87 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt );
88 ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper );
89
90 // Types used in translation, make sure to use clone.
91 // void (*function)();
92 FunctionType try_func_t;
93 // void (*function)(int, exception);
94 FunctionType catch_func_t;
95 // int (*function)(exception);
96 FunctionType match_func_t;
97 // bool (*function)(exception);
98 FunctionType handle_func_t;
99 // void (*function)(__attribute__((unused)) void *);
100 FunctionType finally_func_t;
101
102 StructInstType * create_except_type() {
103 assert( except_decl );
104 return new StructInstType( noQualifiers, except_decl );
105 }
106 void init_func_types();
107
108 public:
109 ExceptionMutatorCore() :
110 cur_context( NoHandler ),
111 handler_except_decl( nullptr ),
112 except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
113 try_func_t( noQualifiers, false ),
114 catch_func_t( noQualifiers, false ),
115 match_func_t( noQualifiers, false ),
116 handle_func_t( noQualifiers, false ),
117 finally_func_t( noQualifiers, false )
118 {
119 init_func_types();
[ba912706]120 }
[948b0c8]121
122 void premutate( CatchStmt *catchStmt );
123 void premutate( StructDecl *structDecl );
124 Statement * postmutate( ThrowStmt *throwStmt );
125 Statement * postmutate( TryStmt *tryStmt );
126 };
127
128 void ExceptionMutatorCore::init_func_types() {
[ba912706]129 ObjectDecl index_obj(
[288eede]130 "__handler_index",
[ba912706]131 Type::StorageClasses(),
132 LinkageSpec::Cforall,
133 /*bitfieldWidth*/ NULL,
[ac10576]134 new BasicType( noQualifiers, BasicType::SignedInt ),
[ba912706]135 /*init*/ NULL
[307a732]136 );
[ba912706]137 ObjectDecl exception_obj(
[288eede]138 "__exception_inst",
[ba912706]139 Type::StorageClasses(),
140 LinkageSpec::Cforall,
141 /*bitfieldWidth*/ NULL,
[307a732]142 new PointerType(
[ac10576]143 noQualifiers,
[948b0c8]144 //new StructInstType( noQualifiers, except_decl )
[ac10576]145 new BasicType( noQualifiers, BasicType::SignedInt )
[307a732]146 ),
[ba912706]147 /*init*/ NULL
[307a732]148 );
[ba912706]149 ObjectDecl bool_obj(
[288eede]150 "__ret_bool",
[ba912706]151 Type::StorageClasses(),
152 LinkageSpec::Cforall,
153 /*bitfieldWidth*/ NULL,
[948b0c8]154 new BasicType( noQualifiers, BasicType::Bool ),
[ba912706]155 /*init*/ NULL
[307a732]156 );
157 ObjectDecl voidptr_obj(
158 "__hook",
159 Type::StorageClasses(),
160 LinkageSpec::Cforall,
161 NULL,
162 new PointerType(
[ac10576]163 noQualifiers,
[307a732]164 new VoidType(
[ac10576]165 noQualifiers
[307a732]166 ),
[948b0c8]167 std::list<Attribute *>{ new Attribute( "unused" ) }
[307a732]168 ),
169 NULL
170 );
[ba912706]171
[307a732]172 catch_func_t.get_parameters().push_back( index_obj.clone() );
173 catch_func_t.get_parameters().push_back( exception_obj.clone() );
174 match_func_t.get_returnVals().push_back( index_obj.clone() );
175 match_func_t.get_parameters().push_back( exception_obj.clone() );
176 handle_func_t.get_returnVals().push_back( bool_obj.clone() );
177 handle_func_t.get_parameters().push_back( exception_obj.clone() );
178 finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
[ba912706]179 }
180
181 // ThrowStmt Mutation Helpers
182
[948b0c8]183 Statement * ExceptionMutatorCore::create_given_throw(
[307a732]184 const char * throwFunc, ThrowStmt * throwStmt ) {
[86d5ba7c]185 // There is an extra copy here we might be able to remove with
186 // references.
[307a732]187 // { int NAME = EXPR; throwFunc( &NAME ); }
188 CompoundStmt * result = new CompoundStmt( noLabels );
189 ObjectDecl * local = new ObjectDecl(
190 "__local_exception_copy",
191 Type::StorageClasses(),
192 LinkageSpec::Cforall,
193 NULL,
[ac10576]194 new BasicType( noQualifiers, BasicType::SignedInt ),
[307a732]195 new SingleInit( throwStmt->get_expr() )
196 );
197 appendDeclStmt( result, local );
198 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
199 call->get_args().push_back( new AddressExpr( nameOf( local ) ) );
200 result->push_back( new ExprStmt( throwStmt->get_labels(), call ) );
[ba912706]201 throwStmt->set_expr( nullptr );
202 delete throwStmt;
203 return result;
204 }
[307a732]205
[948b0c8]206 Statement * ExceptionMutatorCore::create_terminate_throw(
207 ThrowStmt *throwStmt ) {
[307a732]208 // { int NAME = EXPR; __throw_terminate( &NAME ); }
[38ac6ec]209 return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
[307a732]210 }
[86d5ba7c]211
[948b0c8]212 Statement * ExceptionMutatorCore::create_terminate_rethrow(
213 ThrowStmt *throwStmt ) {
[86d5ba7c]214 // { `handler_except_decl` = NULL; __rethrow_terminate(); }
[288eede]215 assert( nullptr == throwStmt->get_expr() );
[86d5ba7c]216 assert( handler_except_decl );
217
218 CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
219 result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
220 nameOf( handler_except_decl ),
221 new ConstantExpr( Constant::null(
222 new PointerType(
223 noQualifiers,
224 handler_except_decl->get_type()->clone()
225 )
226 ) )
227 ) ) );
228 result->push_back( new ExprStmt(
229 noLabels,
[38ac6ec]230 new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
[86d5ba7c]231 ) );
[ba912706]232 delete throwStmt;
233 return result;
234 }
[86d5ba7c]235
[948b0c8]236 Statement * ExceptionMutatorCore::create_resume_throw(
237 ThrowStmt *throwStmt ) {
[ba912706]238 // __throw_resume( EXPR );
[38ac6ec]239 return create_given_throw( "__cfaehm__throw_resume", throwStmt );
[ba912706]240 }
[86d5ba7c]241
[948b0c8]242 Statement * ExceptionMutatorCore::create_resume_rethrow(
243 ThrowStmt *throwStmt ) {
[ba912706]244 // return false;
245 Statement * result = new ReturnStmt(
246 throwStmt->get_labels(),
[288eede]247 new ConstantExpr( Constant::from_bool( false ) )
[ba912706]248 );
249 delete throwStmt;
250 return result;
251 }
252
253 // TryStmt Mutation Helpers
254
[948b0c8]255 // XXX: Leave out?
256 CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
[ba912706]257 CompoundStmt * block = tryStmt->get_block();
258 tryStmt->set_block( nullptr );
259 return block;
260 }
[948b0c8]261
262 FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
263 CompoundStmt *body ) {
[ba912706]264
[288eede]265 return new FunctionDecl( "try", Type::StorageClasses(),
[307a732]266 LinkageSpec::Cforall, try_func_t.clone(), body );
[ba912706]267 }
268
[948b0c8]269 FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
270 CatchList &handlers ) {
[ba912706]271 std::list<CaseStmt *> handler_wrappers;
272
[288eede]273 FunctionType *func_type = catch_func_t.clone();
274 DeclarationWithType * index_obj = func_type->get_parameters().front();
[86d5ba7c]275 DeclarationWithType * except_obj = func_type->get_parameters().back();
[288eede]276
[ba912706]277 // Index 1..{number of handlers}
278 int index = 0;
279 CatchList::iterator it = handlers.begin();
280 for ( ; it != handlers.end() ; ++it ) {
281 ++index;
282 CatchStmt * handler = *it;
283
[288eede]284 // INTEGERconstant Version
285 // case `index`:
286 // {
[86d5ba7c]287 // `handler.decl` {inserted} = { except_obj };
[288eede]288 // `handler.body`
289 // }
290 // return;
[86d5ba7c]291 CompoundStmt * block = new CompoundStmt( noLabels );
292
[03eedd5]293 // Just copy the exception value. (Post Validation)
[86d5ba7c]294 ObjectDecl * handler_decl =
[03eedd5]295 static_cast<ObjectDecl *>( handler->get_decl() );
[86d5ba7c]296 ObjectDecl * local_except = handler_decl->clone();
297 local_except->set_init(
298 new ListInit({ new SingleInit( nameOf( except_obj ) ) }) );
299#if 0
300 // Virtual Exception Vision
301 // case `index`:
302 // {
303 // `handler.decl` = { (virtual `decl.type`)`except` };
304 // `handler.body`;
305 // }
306 // return;
307
308 // Save a cast copy of the exception (should always succeed).
[03eedd5]309 local_except->set_init(
[86d5ba7c]310 new ListInit({ new SingleInit(
311 new VirtualCastExpr( nameOf( except_obj ),
312 local_except->get_type()
313 )
[03eedd5]314 ) })
315 );
[86d5ba7c]316#endif
317 block->push_back( new DeclStmt( noLabels, local_except ) );
318
319 // Add the cleanup attribute.
320 local_except->get_attributes().push_back( new Attribute(
321 "cleanup",
322 { new NameExpr( "__cfaehm__cleanup_terminate" ) }
323 ) );
324
325 // Update variables in the body to point to this local copy.
326 {
327 VarExprReplacer::DeclMap mapping;
328 mapping[ handler_decl ] = local_except;
329 VarExprReplacer mapper( mapping );
330 handler->get_body()->accept( mapper );
331 }
332
333 block->push_back( handler->get_body() );
[288eede]334 handler->set_body( nullptr );
335
[86d5ba7c]336 std::list<Statement *> caseBody
337 { block, new ReturnStmt( noLabels, nullptr ) };
[288eede]338 handler_wrappers.push_back( new CaseStmt(
[ba912706]339 noLabels,
340 new ConstantExpr( Constant::from_int( index ) ),
[288eede]341 caseBody
342 ) );
[ba912706]343 }
344 // TODO: Some sort of meaningful error on default perhaps?
345
[288eede]346 std::list<Statement*> stmt_handlers;
347 while ( !handler_wrappers.empty() ) {
348 stmt_handlers.push_back( handler_wrappers.front() );
349 handler_wrappers.pop_front();
350 }
351
[ba912706]352 SwitchStmt * handler_lookup = new SwitchStmt(
353 noLabels,
[288eede]354 nameOf( index_obj ),
355 stmt_handlers
[ba912706]356 );
357 CompoundStmt * body = new CompoundStmt( noLabels );
358 body->push_back( handler_lookup );
359
360 return new FunctionDecl("catch", Type::StorageClasses(),
[288eede]361 LinkageSpec::Cforall, func_type, body);
[ba912706]362 }
363
364 // Create a single check from a moddified handler.
[288eede]365 // except_obj is referenced, modded_handler will be freed.
[948b0c8]366 CompoundStmt * ExceptionMutatorCore::create_single_matcher(
[288eede]367 DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
368 CompoundStmt * block = new CompoundStmt( noLabels );
369
[86d5ba7c]370 ObjectDecl * local_except =
371 dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
372 assert( local_except );
373 block->push_back( new DeclStmt( noLabels, local_except ) );
374#if 0
375 // Virtual Exception Version
376 // {
377 // `modded_handler.decl`
378 // if ( `decl.name = (virtual)`except`
379 // [&& `modded_handler.cond`] ) {
380 // `modded_handler.body`
381 // }
382 // }
383
384 // Check for type match.
385 Expression * cond = UntypedExpr::createAssign( nameOf( local_except ),
386 new VirtualCastExpr( nameOf( except_obj ),
387 local_except->get_type()->clone() ) );
388#endif
389
[288eede]390 // INTEGERconstant Version
[86d5ba7c]391 // {
392 // `modded_handler.decl` = *`except`
393 // if ( `decl.name` == `modded_handler.cond` ) {
394 // `modded_handler.body`
395 // }
396 // }
[288eede]397 ConstantExpr * number =
398 dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
399 assert( number );
400 modded_handler->set_cond( nullptr );
[ba912706]401
[288eede]402 Expression * cond;
403 {
404 std::list<Expression *> args;
405 args.push_back( number );
[307a732]406
407 std::list<Expression *> rhs_args;
408 rhs_args.push_back( nameOf( except_obj ) );
409 Expression * rhs = new UntypedExpr(
410 new NameExpr( "*?" ), rhs_args );
411 args.push_back( rhs );
412
[288eede]413 cond = new UntypedExpr( new NameExpr( "?==?" /*???*/), args );
414 }
[ba912706]415
[86d5ba7c]416 // Add the check on the conditional if it is provided.
[ba912706]417 if ( modded_handler->get_cond() ) {
[288eede]418 cond = new LogicalExpr( cond, modded_handler->get_cond() );
[ba912706]419 }
[86d5ba7c]420 // Construct the match condition.
[ba912706]421 block->push_back( new IfStmt( noLabels,
[288eede]422 cond, modded_handler->get_body(), nullptr ) );
[ba912706]423
424 modded_handler->set_decl( nullptr );
425 modded_handler->set_cond( nullptr );
426 modded_handler->set_body( nullptr );
427 delete modded_handler;
428 return block;
429 }
430
[948b0c8]431 FunctionDecl * ExceptionMutatorCore::create_terminate_match(
432 CatchList &handlers ) {
[86d5ba7c]433 // int match(exception * except) {
434 // HANDLER WRAPPERS { return `index`; }
435 // }
436
[ba912706]437 CompoundStmt * body = new CompoundStmt( noLabels );
438
[288eede]439 FunctionType * func_type = match_func_t.clone();
440 DeclarationWithType * except_obj = func_type->get_parameters().back();
441
[ba912706]442 // Index 1..{number of handlers}
443 int index = 0;
444 CatchList::iterator it;
445 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
446 ++index;
447 CatchStmt * handler = *it;
448
[288eede]449 // Body should have been taken by create_terminate_catch.
450 assert( nullptr == handler->get_body() );
451
452 // Create new body.
[ba912706]453 handler->set_body( new ReturnStmt( noLabels,
454 new ConstantExpr( Constant::from_int( index ) ) ) );
455
[288eede]456 // Create the handler.
457 body->push_back( create_single_matcher( except_obj, handler ) );
458 *it = nullptr;
[ba912706]459 }
460
[307a732]461 body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
462 Constant::from_int( 0 ) ) ) );
463
[ba912706]464 return new FunctionDecl("match", Type::StorageClasses(),
[288eede]465 LinkageSpec::Cforall, func_type, body);
[ba912706]466 }
467
[948b0c8]468 CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
[ba912706]469 FunctionDecl * try_wrapper,
470 FunctionDecl * terminate_catch,
[948b0c8]471 FunctionDecl * terminate_match ) {
[86d5ba7c]472 // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
[ba912706]473
[288eede]474 UntypedExpr * caller = new UntypedExpr( new NameExpr(
475 "__cfaehm__try_terminate" ) );
476 std::list<Expression *>& args = caller->get_args();
[ba912706]477 args.push_back( nameOf( try_wrapper ) );
478 args.push_back( nameOf( terminate_catch ) );
479 args.push_back( nameOf( terminate_match ) );
480
[288eede]481 CompoundStmt * callStmt = new CompoundStmt( noLabels );
482 callStmt->push_back( new ExprStmt( noLabels, caller ) );
483 return callStmt;
[ba912706]484 }
485
[948b0c8]486 FunctionDecl * ExceptionMutatorCore::create_resume_handler(
487 CatchList &handlers ) {
[86d5ba7c]488 // bool handle(exception * except) {
489 // HANDLER WRAPPERS { `hander->body`; return true; }
490 // }
[288eede]491 CompoundStmt * body = new CompoundStmt( noLabels );
492
493 FunctionType * func_type = match_func_t.clone();
494 DeclarationWithType * except_obj = func_type->get_parameters().back();
[ba912706]495
496 CatchList::iterator it;
497 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
498 CatchStmt * handler = *it;
499
500 // Modifiy body.
501 CompoundStmt * handling_code =
502 dynamic_cast<CompoundStmt*>( handler->get_body() );
503 if ( ! handling_code ) {
504 handling_code = new CompoundStmt( noLabels );
505 handling_code->push_back( handler->get_body() );
506 }
[288eede]507 handling_code->push_back( new ReturnStmt( noLabels,
[ad0be81]508 new ConstantExpr( Constant::from_bool( true ) ) ) );
[ba912706]509 handler->set_body( handling_code );
510
511 // Create the handler.
[288eede]512 body->push_back( create_single_matcher( except_obj, handler ) );
513 *it = nullptr;
[ba912706]514 }
515
[ad0be81]516 body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
517 Constant::from_bool( false ) ) ) );
518
[ba912706]519 return new FunctionDecl("handle", Type::StorageClasses(),
[288eede]520 LinkageSpec::Cforall, func_type, body);
[ba912706]521 }
522
[948b0c8]523 CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
[ba912706]524 Statement * wraps,
525 FunctionDecl * resume_handler ) {
526 CompoundStmt * body = new CompoundStmt( noLabels );
527
[288eede]528 // struct __try_resume_node __resume_node
529 // __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
530 // ** unwinding of the stack here could cause problems **
531 // ** however I don't think that can happen currently **
532 // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
[ba912706]533
534 std::list< Attribute * > attributes;
535 {
536 std::list< Expression * > attr_params;
[288eede]537 attr_params.push_back( new NameExpr(
538 "__cfaehm__try_resume_cleanup" ) );
539 attributes.push_back( new Attribute( "cleanup", attr_params ) );
[ba912706]540 }
541
[288eede]542 ObjectDecl * obj = new ObjectDecl(
543 "__resume_node",
[ba912706]544 Type::StorageClasses(),
545 LinkageSpec::Cforall,
546 nullptr,
[288eede]547 new StructInstType(
548 Type::Qualifiers(),
549 node_decl
550 ),
551 nullptr,
[ba912706]552 attributes
[288eede]553 );
554 appendDeclStmt( body, obj );
555
556 UntypedExpr *setup = new UntypedExpr( new NameExpr(
557 "__cfaehm__try_resume_setup" ) );
[307a732]558 setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
[288eede]559 setup->get_args().push_back( nameOf( resume_handler ) );
560
561 body->push_back( new ExprStmt( noLabels, setup ) );
562
[ba912706]563 body->push_back( wraps );
564 return body;
565 }
566
[948b0c8]567 FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
568 TryStmt * tryStmt ) {
[86d5ba7c]569 // void finally() { <finally code> }
[288eede]570 FinallyStmt * finally = tryStmt->get_finally();
571 CompoundStmt * body = finally->get_block();
572 finally->set_block( nullptr );
573 delete finally;
[ba912706]574 tryStmt->set_finally( nullptr );
575
576 return new FunctionDecl("finally", Type::StorageClasses(),
[307a732]577 LinkageSpec::Cforall, finally_func_t.clone(), body);
[ba912706]578 }
579
[948b0c8]580 ObjectDecl * ExceptionMutatorCore::create_finally_hook(
581 FunctionDecl * finally_wrapper ) {
[288eede]582 // struct __cfaehm__cleanup_hook __finally_hook
583 // __attribute__((cleanup( finally_wrapper )));
[ba912706]584
585 // Make Cleanup Attribute.
586 std::list< Attribute * > attributes;
587 {
588 std::list< Expression * > attr_params;
589 attr_params.push_back( nameOf( finally_wrapper ) );
[288eede]590 attributes.push_back( new Attribute( "cleanup", attr_params ) );
[ba912706]591 }
592
[288eede]593 return new ObjectDecl(
594 "__finally_hook",
[ba912706]595 Type::StorageClasses(),
596 LinkageSpec::Cforall,
597 nullptr,
[288eede]598 new StructInstType(
[ac10576]599 noQualifiers,
[288eede]600 hook_decl
601 ),
[ba912706]602 nullptr,
603 attributes
604 );
605 }
606
[948b0c8]607 // Visiting/Mutating Functions
[86d5ba7c]608 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
609 // Currently, we make up the declaration, as there isn't one for
610 // integers.
[948b0c8]611 assert( ! catchStmt->get_decl() );
[86d5ba7c]612 ObjectDecl * tmp = new ObjectDecl(
613 "_hidden_local",
614 Type::StorageClasses(),
615 LinkageSpec::Cforall,
616 nullptr,
617 new PointerType(
618 noQualifiers,
619 new BasicType( noQualifiers, BasicType::SignedInt )
620 ),
621 nullptr
622 );
623 catchStmt->set_decl( tmp );
624
[03eedd5]625 // Validate the Statement's form.
626 ObjectDecl * decl =
627 dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
628 if ( decl && true /* check decl->get_type() */ ) {
629 // Pass.
630 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
631 throw SemanticError("catch must have exception type");
632 } else {
633 throw SemanticError("catchResume must have exception type");
634 }
635
636 // Track the handler context.
[86d5ba7c]637 GuardValue( cur_context );
638 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
639 cur_context = TerHandler;
640
641 GuardValue( handler_except_decl );
[03eedd5]642 handler_except_decl = decl;
[86d5ba7c]643 } else {
644 cur_context = ResHandler;
645 }
646 }
647
648 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
649 if ( !structDecl->has_body() ) {
650 // Skip children?
651 return;
652 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
653 assert( nullptr == node_decl );
654 node_decl = structDecl;
655 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
656 assert( nullptr == hook_decl );
657 hook_decl = structDecl;
658 }
659 // Later we might get the exception type as well.
660 }
661
[ba912706]662 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
663 // Ignoring throwStmt->get_target() for now.
664 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
665 if ( throwStmt->get_expr() ) {
666 return create_terminate_throw( throwStmt );
[288eede]667 } else if ( TerHandler == cur_context ) {
[948b0c8]668 return create_terminate_rethrow( throwStmt );
[ba912706]669 } else {
670 assertf(false, "Invalid throw in %s at %i\n",
[288eede]671 throwStmt->location.filename.c_str(),
[ba912706]672 throwStmt->location.linenumber);
673 return nullptr;
674 }
675 } else {
676 if ( throwStmt->get_expr() ) {
677 return create_resume_throw( throwStmt );
[288eede]678 } else if ( ResHandler == cur_context ) {
[ba912706]679 return create_resume_rethrow( throwStmt );
680 } else {
681 assertf(false, "Invalid throwResume in %s at %i\n",
[288eede]682 throwStmt->location.filename.c_str(),
[ba912706]683 throwStmt->location.linenumber);
684 return nullptr;
685 }
686 }
687 }
688
689 Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
[288eede]690 assert( node_decl );
691 assert( hook_decl );
692
[ba912706]693 // Generate a prefix for the function names?
694
[288eede]695 CompoundStmt * block = new CompoundStmt( noLabels );
696 CompoundStmt * inner = take_try_block( tryStmt );
[ba912706]697
698 if ( tryStmt->get_finally() ) {
699 // Define the helper function.
700 FunctionDecl * finally_block =
701 create_finally_wrapper( tryStmt );
702 appendDeclStmt( block, finally_block );
703 // Create and add the finally cleanup hook.
[948b0c8]704 appendDeclStmt( block, create_finally_hook( finally_block ) );
[ba912706]705 }
706
[288eede]707 CatchList termination_handlers;
708 CatchList resumption_handlers;
709 split( tryStmt->get_catchers(),
[1abc5ab]710 termination_handlers, resumption_handlers );
[ba912706]711
[288eede]712 if ( resumption_handlers.size() ) {
[ba912706]713 // Define the helper function.
714 FunctionDecl * resume_handler =
715 create_resume_handler( resumption_handlers );
716 appendDeclStmt( block, resume_handler );
717 // Prepare hooks
[948b0c8]718 inner = create_resume_wrapper( inner, resume_handler );
[ba912706]719 }
720
721 if ( termination_handlers.size() ) {
722 // Define the three helper functions.
723 FunctionDecl * try_wrapper = create_try_wrapper( inner );
724 appendDeclStmt( block, try_wrapper );
725 FunctionDecl * terminate_catch =
726 create_terminate_catch( termination_handlers );
727 appendDeclStmt( block, terminate_catch );
728 FunctionDecl * terminate_match =
729 create_terminate_match( termination_handlers );
730 appendDeclStmt( block, terminate_match );
731 // Build the call to the try wrapper.
732 inner = create_terminate_caller(
733 try_wrapper, terminate_catch, terminate_match );
734 }
735
736 // Embed the try block.
737 block->push_back( inner );
738
739 return block;
740 }
741
[1abc5ab]742 void translateEHM( std::list< Declaration *> & translationUnit ) {
[ba912706]743 PassVisitor<ExceptionMutatorCore> translator;
[6fca7ea]744 mutateAll( translationUnit, translator );
[ba912706]745 }
746}
Note: See TracBrowser for help on using the repository browser.