source: src/ControlStruct/ExceptTranslate.cc@ a603f06

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 a603f06 was 03eedd5, checked in by Andrew Beach <ajbeach@…>, 8 years ago

Just a little bit of cleanup in the time I have left.

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