source: src/ControlStruct/ExceptTranslate.cc @ f1a4ccb

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

Reorginization of ExceptTranslate? to make the next steps easier.

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