source: src/ControlStruct/ExceptTranslate.cc @ 66ba544

arm-ehjacob/cs343-translationnew-astnew-ast-unique-expr
Last change on this file since 66ba544 was 66ba544, checked in by Andrew Beach <ajbeach@…>, 19 months ago

Dead code elimination in the try block translation.

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