source: src/ControlStruct/ExceptTranslate.cc @ 86d5ba7c

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 86d5ba7c was 86d5ba7c, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Added the memory management calls to the exception control flow.

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