source: src/ControlStruct/ExceptTranslate.cc@ 2890212

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 2890212 was 933f32f, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Merge branch 'master' into cleanup-dtors

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