source: src/ControlStruct/ExceptTranslate.cc @ 7119daa

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 7119daa was 7119daa, checked in by Andrew Beach <ajbeach@…>, 4 years ago

More clean-up in ExceptTranslate?.

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