source: src/ControlStruct/ExceptTranslate.cc @ 68f9c43

new-envwith_gc
Last change on this file since 68f9c43 was 68f9c43, checked in by Aaron Moss <a3moss@…>, 6 years ago

First pass at delete removal

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