source: src/ControlStruct/ExceptTranslate.cc@ ec010a9

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since ec010a9 was d48e529, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Begin to introduce support for yylloc in the parser and extend CodeLocation to include start column and end column/line number information

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