source: src/ControlStruct/ExceptTranslate.cc@ 5fb6830

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 5fb6830 was cbce272, checked in by Andrew Beach <ajbeach@…>, 8 years ago

Structure based exception handling.

  • Property mode set to 100644
File size: 20.6 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
[cbce272]12// Last Modified On : Tus Aug 8 16:54:00 2017
[948b0c8]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 )
[cbce272]118 {}
[948b0c8]119
120 void premutate( CatchStmt *catchStmt );
121 void premutate( StructDecl *structDecl );
122 Statement * postmutate( ThrowStmt *throwStmt );
123 Statement * postmutate( TryStmt *tryStmt );
124 };
125
126 void ExceptionMutatorCore::init_func_types() {
[cbce272]127 assert( except_decl );
128
[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,
[cbce272]144 new StructInstType( noQualifiers, except_decl )
[307a732]145 ),
[ba912706]146 /*init*/ NULL
[307a732]147 );
[ba912706]148 ObjectDecl bool_obj(
[288eede]149 "__ret_bool",
[ba912706]150 Type::StorageClasses(),
151 LinkageSpec::Cforall,
152 /*bitfieldWidth*/ NULL,
[948b0c8]153 new BasicType( noQualifiers, BasicType::Bool ),
[ba912706]154 /*init*/ NULL
[307a732]155 );
156 ObjectDecl voidptr_obj(
157 "__hook",
158 Type::StorageClasses(),
159 LinkageSpec::Cforall,
160 NULL,
161 new PointerType(
[ac10576]162 noQualifiers,
[307a732]163 new VoidType(
[ac10576]164 noQualifiers
[307a732]165 ),
[948b0c8]166 std::list<Attribute *>{ new Attribute( "unused" ) }
[307a732]167 ),
168 NULL
169 );
[ba912706]170
[307a732]171 catch_func_t.get_parameters().push_back( index_obj.clone() );
172 catch_func_t.get_parameters().push_back( exception_obj.clone() );
173 match_func_t.get_returnVals().push_back( index_obj.clone() );
174 match_func_t.get_parameters().push_back( exception_obj.clone() );
175 handle_func_t.get_returnVals().push_back( bool_obj.clone() );
176 handle_func_t.get_parameters().push_back( exception_obj.clone() );
177 finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
[ba912706]178 }
179
180 // ThrowStmt Mutation Helpers
181
[948b0c8]182 Statement * ExceptionMutatorCore::create_given_throw(
[307a732]183 const char * throwFunc, ThrowStmt * throwStmt ) {
[cbce272]184 // `throwFunc`( `throwStmt->get_name` );
[307a732]185 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
[cbce272]186 call->get_args().push_back( throwStmt->get_expr() );
[ba912706]187 throwStmt->set_expr( nullptr );
188 delete throwStmt;
[cbce272]189 return new ExprStmt( noLabels, call );
[ba912706]190 }
[307a732]191
[948b0c8]192 Statement * ExceptionMutatorCore::create_terminate_throw(
193 ThrowStmt *throwStmt ) {
[cbce272]194 // __throw_terminate( `throwStmt->get_name()` ); }
[38ac6ec]195 return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
[307a732]196 }
[86d5ba7c]197
[948b0c8]198 Statement * ExceptionMutatorCore::create_terminate_rethrow(
199 ThrowStmt *throwStmt ) {
[86d5ba7c]200 // { `handler_except_decl` = NULL; __rethrow_terminate(); }
[288eede]201 assert( nullptr == throwStmt->get_expr() );
[86d5ba7c]202 assert( handler_except_decl );
203
204 CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
205 result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
206 nameOf( handler_except_decl ),
207 new ConstantExpr( Constant::null(
208 new PointerType(
209 noQualifiers,
210 handler_except_decl->get_type()->clone()
211 )
212 ) )
213 ) ) );
214 result->push_back( new ExprStmt(
215 noLabels,
[38ac6ec]216 new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
[86d5ba7c]217 ) );
[ba912706]218 delete throwStmt;
219 return result;
220 }
[86d5ba7c]221
[948b0c8]222 Statement * ExceptionMutatorCore::create_resume_throw(
223 ThrowStmt *throwStmt ) {
[cbce272]224 // __throw_resume( `throwStmt->get_name` );
[38ac6ec]225 return create_given_throw( "__cfaehm__throw_resume", throwStmt );
[ba912706]226 }
[86d5ba7c]227
[948b0c8]228 Statement * ExceptionMutatorCore::create_resume_rethrow(
229 ThrowStmt *throwStmt ) {
[ba912706]230 // return false;
231 Statement * result = new ReturnStmt(
232 throwStmt->get_labels(),
[288eede]233 new ConstantExpr( Constant::from_bool( false ) )
[ba912706]234 );
235 delete throwStmt;
236 return result;
237 }
238
239 // TryStmt Mutation Helpers
240
[948b0c8]241 CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
[ba912706]242 CompoundStmt * block = tryStmt->get_block();
243 tryStmt->set_block( nullptr );
244 return block;
245 }
[948b0c8]246
247 FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
248 CompoundStmt *body ) {
[ba912706]249
[288eede]250 return new FunctionDecl( "try", Type::StorageClasses(),
[307a732]251 LinkageSpec::Cforall, try_func_t.clone(), body );
[ba912706]252 }
253
[948b0c8]254 FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
255 CatchList &handlers ) {
[ba912706]256 std::list<CaseStmt *> handler_wrappers;
257
[288eede]258 FunctionType *func_type = catch_func_t.clone();
259 DeclarationWithType * index_obj = func_type->get_parameters().front();
[86d5ba7c]260 DeclarationWithType * except_obj = func_type->get_parameters().back();
[288eede]261
[ba912706]262 // Index 1..{number of handlers}
263 int index = 0;
264 CatchList::iterator it = handlers.begin();
265 for ( ; it != handlers.end() ; ++it ) {
266 ++index;
267 CatchStmt * handler = *it;
268
[288eede]269 // case `index`:
270 // {
[cbce272]271 // `handler.decl` = { (virtual `decl.type`)`except` };
272 // `handler.body`;
[288eede]273 // }
274 // return;
[86d5ba7c]275 CompoundStmt * block = new CompoundStmt( noLabels );
276
[03eedd5]277 // Just copy the exception value. (Post Validation)
[86d5ba7c]278 ObjectDecl * handler_decl =
[03eedd5]279 static_cast<ObjectDecl *>( handler->get_decl() );
[86d5ba7c]280 ObjectDecl * local_except = handler_decl->clone();
[03eedd5]281 local_except->set_init(
[86d5ba7c]282 new ListInit({ new SingleInit(
283 new VirtualCastExpr( nameOf( except_obj ),
284 local_except->get_type()
285 )
[03eedd5]286 ) })
287 );
[86d5ba7c]288 block->push_back( new DeclStmt( noLabels, local_except ) );
289
290 // Add the cleanup attribute.
291 local_except->get_attributes().push_back( new Attribute(
292 "cleanup",
293 { new NameExpr( "__cfaehm__cleanup_terminate" ) }
294 ) );
295
296 // Update variables in the body to point to this local copy.
297 {
298 VarExprReplacer::DeclMap mapping;
299 mapping[ handler_decl ] = local_except;
300 VarExprReplacer mapper( mapping );
301 handler->get_body()->accept( mapper );
302 }
303
304 block->push_back( handler->get_body() );
[288eede]305 handler->set_body( nullptr );
306
[86d5ba7c]307 std::list<Statement *> caseBody
308 { block, new ReturnStmt( noLabels, nullptr ) };
[288eede]309 handler_wrappers.push_back( new CaseStmt(
[ba912706]310 noLabels,
311 new ConstantExpr( Constant::from_int( index ) ),
[288eede]312 caseBody
313 ) );
[ba912706]314 }
315 // TODO: Some sort of meaningful error on default perhaps?
316
[288eede]317 std::list<Statement*> stmt_handlers;
318 while ( !handler_wrappers.empty() ) {
319 stmt_handlers.push_back( handler_wrappers.front() );
320 handler_wrappers.pop_front();
321 }
322
[ba912706]323 SwitchStmt * handler_lookup = new SwitchStmt(
324 noLabels,
[288eede]325 nameOf( index_obj ),
326 stmt_handlers
[ba912706]327 );
328 CompoundStmt * body = new CompoundStmt( noLabels );
329 body->push_back( handler_lookup );
330
331 return new FunctionDecl("catch", Type::StorageClasses(),
[288eede]332 LinkageSpec::Cforall, func_type, body);
[ba912706]333 }
334
335 // Create a single check from a moddified handler.
[288eede]336 // except_obj is referenced, modded_handler will be freed.
[948b0c8]337 CompoundStmt * ExceptionMutatorCore::create_single_matcher(
[288eede]338 DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
[86d5ba7c]339 // {
340 // `modded_handler.decl`
[cbce272]341 // if ( `decl.name = (virtual `decl.type`)`except`
[86d5ba7c]342 // [&& `modded_handler.cond`] ) {
343 // `modded_handler.body`
344 // }
345 // }
346
[cbce272]347 CompoundStmt * block = new CompoundStmt( noLabels );
348
349 // Local Declaration
350 ObjectDecl * local_except =
351 dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
352 assert( local_except );
353 block->push_back( new DeclStmt( noLabels, local_except ) );
354
[86d5ba7c]355 // Check for type match.
356 Expression * cond = UntypedExpr::createAssign( nameOf( local_except ),
357 new VirtualCastExpr( nameOf( except_obj ),
358 local_except->get_type()->clone() ) );
[ba912706]359
[86d5ba7c]360 // Add the check on the conditional if it is provided.
[ba912706]361 if ( modded_handler->get_cond() ) {
[288eede]362 cond = new LogicalExpr( cond, modded_handler->get_cond() );
[ba912706]363 }
[86d5ba7c]364 // Construct the match condition.
[ba912706]365 block->push_back( new IfStmt( noLabels,
[288eede]366 cond, modded_handler->get_body(), nullptr ) );
[ba912706]367
368 modded_handler->set_decl( nullptr );
369 modded_handler->set_cond( nullptr );
370 modded_handler->set_body( nullptr );
371 delete modded_handler;
372 return block;
373 }
374
[948b0c8]375 FunctionDecl * ExceptionMutatorCore::create_terminate_match(
376 CatchList &handlers ) {
[86d5ba7c]377 // int match(exception * except) {
378 // HANDLER WRAPPERS { return `index`; }
379 // }
380
[ba912706]381 CompoundStmt * body = new CompoundStmt( noLabels );
382
[288eede]383 FunctionType * func_type = match_func_t.clone();
384 DeclarationWithType * except_obj = func_type->get_parameters().back();
385
[ba912706]386 // Index 1..{number of handlers}
387 int index = 0;
388 CatchList::iterator it;
389 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
390 ++index;
391 CatchStmt * handler = *it;
392
[288eede]393 // Body should have been taken by create_terminate_catch.
394 assert( nullptr == handler->get_body() );
395
396 // Create new body.
[ba912706]397 handler->set_body( new ReturnStmt( noLabels,
398 new ConstantExpr( Constant::from_int( index ) ) ) );
399
[288eede]400 // Create the handler.
401 body->push_back( create_single_matcher( except_obj, handler ) );
402 *it = nullptr;
[ba912706]403 }
404
[307a732]405 body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
406 Constant::from_int( 0 ) ) ) );
407
[ba912706]408 return new FunctionDecl("match", Type::StorageClasses(),
[288eede]409 LinkageSpec::Cforall, func_type, body);
[ba912706]410 }
411
[948b0c8]412 CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
[ba912706]413 FunctionDecl * try_wrapper,
414 FunctionDecl * terminate_catch,
[948b0c8]415 FunctionDecl * terminate_match ) {
[86d5ba7c]416 // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
[ba912706]417
[288eede]418 UntypedExpr * caller = new UntypedExpr( new NameExpr(
419 "__cfaehm__try_terminate" ) );
420 std::list<Expression *>& args = caller->get_args();
[ba912706]421 args.push_back( nameOf( try_wrapper ) );
422 args.push_back( nameOf( terminate_catch ) );
423 args.push_back( nameOf( terminate_match ) );
424
[288eede]425 CompoundStmt * callStmt = new CompoundStmt( noLabels );
426 callStmt->push_back( new ExprStmt( noLabels, caller ) );
427 return callStmt;
[ba912706]428 }
429
[948b0c8]430 FunctionDecl * ExceptionMutatorCore::create_resume_handler(
431 CatchList &handlers ) {
[86d5ba7c]432 // bool handle(exception * except) {
433 // HANDLER WRAPPERS { `hander->body`; return true; }
434 // }
[288eede]435 CompoundStmt * body = new CompoundStmt( noLabels );
436
437 FunctionType * func_type = match_func_t.clone();
438 DeclarationWithType * except_obj = func_type->get_parameters().back();
[ba912706]439
440 CatchList::iterator it;
441 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
442 CatchStmt * handler = *it;
443
444 // Modifiy body.
445 CompoundStmt * handling_code =
446 dynamic_cast<CompoundStmt*>( handler->get_body() );
447 if ( ! handling_code ) {
448 handling_code = new CompoundStmt( noLabels );
449 handling_code->push_back( handler->get_body() );
450 }
[288eede]451 handling_code->push_back( new ReturnStmt( noLabels,
[ad0be81]452 new ConstantExpr( Constant::from_bool( true ) ) ) );
[ba912706]453 handler->set_body( handling_code );
454
455 // Create the handler.
[288eede]456 body->push_back( create_single_matcher( except_obj, handler ) );
457 *it = nullptr;
[ba912706]458 }
459
[ad0be81]460 body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
461 Constant::from_bool( false ) ) ) );
462
[ba912706]463 return new FunctionDecl("handle", Type::StorageClasses(),
[288eede]464 LinkageSpec::Cforall, func_type, body);
[ba912706]465 }
466
[948b0c8]467 CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
[ba912706]468 Statement * wraps,
469 FunctionDecl * resume_handler ) {
470 CompoundStmt * body = new CompoundStmt( noLabels );
471
[288eede]472 // struct __try_resume_node __resume_node
473 // __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
474 // ** unwinding of the stack here could cause problems **
475 // ** however I don't think that can happen currently **
476 // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
[ba912706]477
478 std::list< Attribute * > attributes;
479 {
480 std::list< Expression * > attr_params;
[288eede]481 attr_params.push_back( new NameExpr(
482 "__cfaehm__try_resume_cleanup" ) );
483 attributes.push_back( new Attribute( "cleanup", attr_params ) );
[ba912706]484 }
485
[288eede]486 ObjectDecl * obj = new ObjectDecl(
487 "__resume_node",
[ba912706]488 Type::StorageClasses(),
489 LinkageSpec::Cforall,
490 nullptr,
[288eede]491 new StructInstType(
492 Type::Qualifiers(),
493 node_decl
494 ),
495 nullptr,
[ba912706]496 attributes
[288eede]497 );
498 appendDeclStmt( body, obj );
499
500 UntypedExpr *setup = new UntypedExpr( new NameExpr(
501 "__cfaehm__try_resume_setup" ) );
[307a732]502 setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
[288eede]503 setup->get_args().push_back( nameOf( resume_handler ) );
504
505 body->push_back( new ExprStmt( noLabels, setup ) );
506
[ba912706]507 body->push_back( wraps );
508 return body;
509 }
510
[948b0c8]511 FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
512 TryStmt * tryStmt ) {
[86d5ba7c]513 // void finally() { <finally code> }
[288eede]514 FinallyStmt * finally = tryStmt->get_finally();
515 CompoundStmt * body = finally->get_block();
516 finally->set_block( nullptr );
517 delete finally;
[ba912706]518 tryStmt->set_finally( nullptr );
519
520 return new FunctionDecl("finally", Type::StorageClasses(),
[307a732]521 LinkageSpec::Cforall, finally_func_t.clone(), body);
[ba912706]522 }
523
[948b0c8]524 ObjectDecl * ExceptionMutatorCore::create_finally_hook(
525 FunctionDecl * finally_wrapper ) {
[288eede]526 // struct __cfaehm__cleanup_hook __finally_hook
527 // __attribute__((cleanup( finally_wrapper )));
[ba912706]528
529 // Make Cleanup Attribute.
530 std::list< Attribute * > attributes;
531 {
532 std::list< Expression * > attr_params;
533 attr_params.push_back( nameOf( finally_wrapper ) );
[288eede]534 attributes.push_back( new Attribute( "cleanup", attr_params ) );
[ba912706]535 }
536
[288eede]537 return new ObjectDecl(
538 "__finally_hook",
[ba912706]539 Type::StorageClasses(),
540 LinkageSpec::Cforall,
541 nullptr,
[288eede]542 new StructInstType(
[ac10576]543 noQualifiers,
[288eede]544 hook_decl
545 ),
[ba912706]546 nullptr,
547 attributes
548 );
549 }
550
[948b0c8]551 // Visiting/Mutating Functions
[86d5ba7c]552 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
[03eedd5]553 // Validate the Statement's form.
554 ObjectDecl * decl =
555 dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
556 if ( decl && true /* check decl->get_type() */ ) {
557 // Pass.
558 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
559 throw SemanticError("catch must have exception type");
560 } else {
561 throw SemanticError("catchResume must have exception type");
562 }
563
564 // Track the handler context.
[86d5ba7c]565 GuardValue( cur_context );
566 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
567 cur_context = TerHandler;
568
569 GuardValue( handler_except_decl );
[03eedd5]570 handler_except_decl = decl;
[86d5ba7c]571 } else {
572 cur_context = ResHandler;
573 }
574 }
575
576 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
577 if ( !structDecl->has_body() ) {
578 // Skip children?
579 return;
[cbce272]580 } else if ( structDecl->get_name() == "__cfaehm__base_exception_t" ) {
581 assert( nullptr == except_decl );
582 except_decl = structDecl;
583 init_func_types();
[86d5ba7c]584 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
585 assert( nullptr == node_decl );
586 node_decl = structDecl;
587 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
588 assert( nullptr == hook_decl );
589 hook_decl = structDecl;
590 }
591 // Later we might get the exception type as well.
592 }
593
[ba912706]594 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
[cbce272]595 assert( except_decl );
596
[ba912706]597 // Ignoring throwStmt->get_target() for now.
598 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
599 if ( throwStmt->get_expr() ) {
600 return create_terminate_throw( throwStmt );
[288eede]601 } else if ( TerHandler == cur_context ) {
[948b0c8]602 return create_terminate_rethrow( throwStmt );
[ba912706]603 } else {
604 assertf(false, "Invalid throw in %s at %i\n",
[288eede]605 throwStmt->location.filename.c_str(),
[ba912706]606 throwStmt->location.linenumber);
607 return nullptr;
608 }
609 } else {
610 if ( throwStmt->get_expr() ) {
611 return create_resume_throw( throwStmt );
[288eede]612 } else if ( ResHandler == cur_context ) {
[ba912706]613 return create_resume_rethrow( throwStmt );
614 } else {
615 assertf(false, "Invalid throwResume in %s at %i\n",
[288eede]616 throwStmt->location.filename.c_str(),
[ba912706]617 throwStmt->location.linenumber);
618 return nullptr;
619 }
620 }
621 }
622
623 Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
[cbce272]624 assert( except_decl );
[288eede]625 assert( node_decl );
626 assert( hook_decl );
627
[ba912706]628 // Generate a prefix for the function names?
629
[288eede]630 CompoundStmt * block = new CompoundStmt( noLabels );
631 CompoundStmt * inner = take_try_block( tryStmt );
[ba912706]632
633 if ( tryStmt->get_finally() ) {
634 // Define the helper function.
635 FunctionDecl * finally_block =
636 create_finally_wrapper( tryStmt );
637 appendDeclStmt( block, finally_block );
638 // Create and add the finally cleanup hook.
[948b0c8]639 appendDeclStmt( block, create_finally_hook( finally_block ) );
[ba912706]640 }
641
[288eede]642 CatchList termination_handlers;
643 CatchList resumption_handlers;
644 split( tryStmt->get_catchers(),
[1abc5ab]645 termination_handlers, resumption_handlers );
[ba912706]646
[288eede]647 if ( resumption_handlers.size() ) {
[ba912706]648 // Define the helper function.
649 FunctionDecl * resume_handler =
650 create_resume_handler( resumption_handlers );
651 appendDeclStmt( block, resume_handler );
652 // Prepare hooks
[948b0c8]653 inner = create_resume_wrapper( inner, resume_handler );
[ba912706]654 }
655
656 if ( termination_handlers.size() ) {
657 // Define the three helper functions.
658 FunctionDecl * try_wrapper = create_try_wrapper( inner );
659 appendDeclStmt( block, try_wrapper );
660 FunctionDecl * terminate_catch =
661 create_terminate_catch( termination_handlers );
662 appendDeclStmt( block, terminate_catch );
663 FunctionDecl * terminate_match =
664 create_terminate_match( termination_handlers );
665 appendDeclStmt( block, terminate_match );
666 // Build the call to the try wrapper.
667 inner = create_terminate_caller(
668 try_wrapper, terminate_catch, terminate_match );
669 }
670
671 // Embed the try block.
672 block->push_back( inner );
673
674 return block;
675 }
676
[1abc5ab]677 void translateEHM( std::list< Declaration *> & translationUnit ) {
[ba912706]678 PassVisitor<ExceptionMutatorCore> translator;
[6fca7ea]679 mutateAll( translationUnit, translator );
[ba912706]680 }
681}
Note: See TracBrowser for help on using the repository browser.