source: src/ControlStruct/ExceptTranslate.cc @ f1bcd004

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since f1bcd004 was 8f6dfe7, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Cleaned up the generated exception functions a bit.

  • Property mode set to 100644
File size: 21.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 Aug 17 17:19:00 2017
13// Update Count     : 9
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, 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
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(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 )
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( noLabels, call );
208        }
209
210        Statement * ExceptionMutatorCore::create_terminate_throw(
211                        ThrowStmt *throwStmt ) {
212                // __throw_terminate( `throwStmt->get_name()` ); }
213                return create_given_throw( "__cfaehm__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( 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,
234                        new UntypedExpr( new NameExpr( "__cfaehm__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( "__cfaehm__throw_resume", throwStmt );
244        }
245
246        Statement * ExceptionMutatorCore::create_resume_rethrow(
247                        ThrowStmt *throwStmt ) {
248                // return false;
249                Statement * result = new ReturnStmt(
250                        throwStmt->get_labels(),
251                        new ConstantExpr( Constant::from_bool( false ) )
252                        );
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( noLabels );
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( 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() );
323                        handler->set_body( nullptr );
324
325                        std::list<Statement *> caseBody
326                                        { block, new ReturnStmt( noLabels, nullptr ) };
327                        handler_wrappers.push_back( new CaseStmt(
328                                noLabels,
329                                new ConstantExpr( Constant::from_int( index ) ),
330                                caseBody
331                                ) );
332                }
333                // TODO: Some sort of meaningful error on default perhaps?
334
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
341                SwitchStmt * handler_lookup = new SwitchStmt(
342                        noLabels,
343                        nameOf( index_obj ),
344                        stmt_handlers
345                        );
346                CompoundStmt * body = new CompoundStmt( noLabels );
347                body->push_back( handler_lookup );
348
349                return new FunctionDecl("catch", Type::StorageClasses(),
350                        LinkageSpec::Cforall, func_type, body);
351        }
352
353        // Create a single check from a moddified handler.
354        // except_obj is referenced, modded_handler will be freed.
355        CompoundStmt * ExceptionMutatorCore::create_single_matcher(
356                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
357                // {
358                //     `modded_handler.decl`
359                //     if ( `decl.name = (virtual `decl.type`)`except`
360                //             [&& `modded_handler.cond`] ) {
361                //         `modded_handler.body`
362                //     }
363                // }
364
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
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() ) );
377
378                // Add the check on the conditional if it is provided.
379                if ( modded_handler->get_cond() ) {
380                        cond = new LogicalExpr( cond, modded_handler->get_cond() );
381                }
382                // Construct the match condition.
383                block->push_back( new IfStmt( noLabels,
384                        cond, modded_handler->get_body(), nullptr ) );
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
393        FunctionDecl * ExceptionMutatorCore::create_terminate_match(
394                        CatchList &handlers ) {
395                // int match(exception * except) {
396                //     HANDLER WRAPPERS { return `index`; }
397                // }
398
399                CompoundStmt * body = new CompoundStmt( noLabels );
400
401                FunctionType * func_type = match_func_t.clone();
402                DeclarationWithType * except_obj = func_type->get_parameters().back();
403
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
411                        // Body should have been taken by create_terminate_catch.
412                        assert( nullptr == handler->get_body() );
413
414                        // Create new body.
415                        handler->set_body( new ReturnStmt( noLabels,
416                                new ConstantExpr( Constant::from_int( index ) ) ) );
417
418                        // Create the handler.
419                        body->push_back( create_single_matcher( except_obj, handler ) );
420                        *it = nullptr;
421                }
422
423                body->push_back( new ReturnStmt( noLabels,
424                        new ConstantExpr( Constant::from_int( 0 ) ) ) );
425
426                return new FunctionDecl("match", Type::StorageClasses(),
427                        LinkageSpec::Cforall, func_type, body);
428        }
429
430        CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
431                        FunctionDecl * try_wrapper,
432                        FunctionDecl * terminate_catch,
433                        FunctionDecl * terminate_match ) {
434                // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
435
436                UntypedExpr * caller = new UntypedExpr( new NameExpr(
437                        "__cfaehm__try_terminate" ) );
438                std::list<Expression *>& args = caller->get_args();
439                args.push_back( nameOf( try_wrapper ) );
440                args.push_back( nameOf( terminate_catch ) );
441                args.push_back( nameOf( terminate_match ) );
442
443                CompoundStmt * callStmt = new CompoundStmt( noLabels );
444                callStmt->push_back( new ExprStmt( noLabels, caller ) );
445                return callStmt;
446        }
447
448        FunctionDecl * ExceptionMutatorCore::create_resume_handler(
449                        CatchList &handlers ) {
450                // bool handle(exception * except) {
451                //     HANDLER WRAPPERS { `hander->body`; return true; }
452                // }
453                CompoundStmt * body = new CompoundStmt( noLabels );
454
455                FunctionType * func_type = handle_func_t.clone();
456                DeclarationWithType * except_obj = func_type->get_parameters().back();
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                        }
469                        handling_code->push_back( new ReturnStmt( noLabels,
470                                new ConstantExpr( Constant::from_bool( true ) ) ) );
471                        handler->set_body( handling_code );
472
473                        // Create the handler.
474                        body->push_back( create_single_matcher( except_obj, handler ) );
475                        *it = nullptr;
476                }
477
478                body->push_back( new ReturnStmt( noLabels,
479                        new ConstantExpr( Constant::from_bool( false ) ) ) );
480
481                return new FunctionDecl("handle", Type::StorageClasses(),
482                        LinkageSpec::Cforall, func_type, body);
483        }
484
485        CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
486                        Statement * wraps,
487                        FunctionDecl * resume_handler ) {
488                CompoundStmt * body = new CompoundStmt( noLabels );
489
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 );
495
496                std::list< Attribute * > attributes;
497                {
498                        std::list< Expression * > attr_params;
499                        attr_params.push_back( new NameExpr(
500                                "__cfaehm__try_resume_cleanup" ) );
501                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
502                }
503
504                ObjectDecl * obj = new ObjectDecl(
505                        "__resume_node",
506                        Type::StorageClasses(),
507                        LinkageSpec::Cforall,
508                        nullptr,
509                        new StructInstType(
510                                Type::Qualifiers(),
511                                node_decl
512                                ),
513                        nullptr,
514                        attributes
515                        );
516                appendDeclStmt( body, obj );
517
518                UntypedExpr *setup = new UntypedExpr( new NameExpr(
519                        "__cfaehm__try_resume_setup" ) );
520                setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
521                setup->get_args().push_back( nameOf( resume_handler ) );
522
523                body->push_back( new ExprStmt( noLabels, setup ) );
524
525                body->push_back( wraps );
526                return body;
527        }
528
529        FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
530                        TryStmt * tryStmt ) {
531                // void finally() { <finally code> }
532                FinallyStmt * finally = tryStmt->get_finally();
533                CompoundStmt * body = finally->get_block();
534                finally->set_block( nullptr );
535                delete finally;
536                tryStmt->set_finally( nullptr );
537
538                return new FunctionDecl("finally", Type::StorageClasses(),
539                        LinkageSpec::Cforall, finally_func_t.clone(), body);
540        }
541
542        ObjectDecl * ExceptionMutatorCore::create_finally_hook(
543                        FunctionDecl * finally_wrapper ) {
544                // struct __cfaehm__cleanup_hook __finally_hook
545                //      __attribute__((cleanup( finally_wrapper )));
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 ) );
552                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
553                }
554
555                return new ObjectDecl(
556                        "__finally_hook",
557                        Type::StorageClasses(),
558                        LinkageSpec::Cforall,
559                        nullptr,
560                        new StructInstType(
561                                noQualifiers,
562                                hook_decl
563                                ),
564                        nullptr,
565                        attributes
566                        );
567        }
568
569        // Visiting/Mutating Functions
570        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
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.
583                GuardValue( cur_context );
584                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
585                        cur_context = TerHandler;
586
587                        GuardValue( handler_except_decl );
588                        handler_except_decl = decl;
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;
598                } else if ( structDecl->get_name() == "__cfaehm__base_exception_t" ) {
599                        assert( nullptr == except_decl );
600                        except_decl = structDecl;
601                        init_func_types();
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
612        Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
613                assert( except_decl );
614
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 );
619                        } else if ( TerHandler == cur_context ) {
620                                return create_terminate_rethrow( throwStmt );
621                        } else {
622                                assertf(false, "Invalid throw in %s at %i\n",
623                                        throwStmt->location.filename.c_str(),
624                                        throwStmt->location.linenumber);
625                                return nullptr;
626                        }
627                } else {
628                        if ( throwStmt->get_expr() ) {
629                                return create_resume_throw( throwStmt );
630                        } else if ( ResHandler == cur_context ) {
631                                return create_resume_rethrow( throwStmt );
632                        } else {
633                                assertf(false, "Invalid throwResume in %s at %i\n",
634                                        throwStmt->location.filename.c_str(),
635                                        throwStmt->location.linenumber);
636                                return nullptr;
637                        }
638                }
639        }
640
641        Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
642                assert( except_decl );
643                assert( node_decl );
644                assert( hook_decl );
645
646                // Generate a prefix for the function names?
647
648                CompoundStmt * block = new CompoundStmt( noLabels );
649                CompoundStmt * inner = take_try_block( tryStmt );
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.
657                        appendDeclStmt( block, create_finally_hook( finally_block ) );
658                }
659
660                CatchList termination_handlers;
661                CatchList resumption_handlers;
662                split( tryStmt->get_catchers(),
663                           termination_handlers, resumption_handlers );
664
665                if ( resumption_handlers.size() ) {
666                        // Define the helper function.
667                        FunctionDecl * resume_handler =
668                                create_resume_handler( resumption_handlers );
669                        appendDeclStmt( block, resume_handler );
670                        // Prepare hooks
671                        inner = create_resume_wrapper( inner, resume_handler );
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
695        void translateEHM( std::list< Declaration *> & translationUnit ) {
696                PassVisitor<ExceptionMutatorCore> translator;
697                mutateAll( translationUnit, translator );
698        }
699}
Note: See TracBrowser for help on using the repository browser.