Ignore:
Timestamp:
Jun 29, 2017, 5:09:37 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
1abc5ab
Parents:
2a7b3ca (diff), fe5c01d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:/u/cforall/software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    r2a7b3ca r949934e  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Jun 22 15:57:00 2017
    13 // Update Count     : 0
     12// Last Modified On : Thr Jun 29 15:18:00 2017
     13// Update Count     : 1
    1414//
    1515
    1616#include "ExceptTranslate.h"
    1717#include "Common/PassVisitor.h"
     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"
    1823
    1924namespace ControlFlow {
     
    3439
    3540        static void init_func_types() {
    36                 static init_complete = false;
     41                static bool init_complete = false;
    3742                if (init_complete) {
    3843                        return;
    3944                }
    4045                ObjectDecl index_obj(
    41                         "index_t",
     46                        "__handler_index",
    4247                        Type::StorageClasses(),
    4348                        LinkageSpec::Cforall,
     
    4752                );
    4853                ObjectDecl exception_obj(
    49                         "exception_t",
     54                        "__exception_inst",
    5055                        Type::StorageClasses(),
    5156                        LinkageSpec::Cforall,
     
    5560                );
    5661                ObjectDecl bool_obj(
    57                         "bool_t",
     62                        "__ret_bool",
    5863                        Type::StorageClasses(),
    5964                        LinkageSpec::Cforall,
     
    8085                    CatchList& resHandlers ) {
    8186                while ( !allHandlers.empty() ) {
    82                         Statement * stmt = allHandlers.front();
     87                        CatchStmt * stmt = allHandlers.front();
    8388                        allHandlers.pop_front();
    84                         if (CaseStmt::Terminate == stmt->get_kind()) {
     89                        if (CatchStmt::Terminate == stmt->get_kind()) {
    8590                                terHandlers.push_back(stmt);
    8691                        } else {
     
    9297        template<typename T>
    9398        void free_all( std::list<T *> &list ) {
    94                 std::list<T *>::iterator it;
     99                typename std::list<T *>::iterator it;
    95100                for ( it = list.begin() ; it != list.end() ; ++it ) {
    96101                        delete *it;
     
    100105
    101106        void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
    102                 block->push_back(new DeclStmt(no_labels, item));
    103         }
    104 
    105         Expression * nameOf( FunctionDecl * function ) {
    106                 return new VariableExpr( function );
     107                block->push_back(new DeclStmt(noLabels, item));
     108        }
     109
     110        Expression * nameOf( DeclarationWithType * decl ) {
     111                return new VariableExpr( decl );
    107112        }
    108113
     
    111116        Statement * create_terminate_throw( ThrowStmt *throwStmt ) {
    112117                // __throw_terminate( EXPR );
    113                 ApplicationExpr * call = new ApplicationExpr( /* ... */ );
    114                 call->get_args.push_back( throwStmt->get_expr() );
     118                UntypedExpr * call = new UntypedExpr( new NameExpr(
     119                        "__cfaehm__throw_termination" ) );
     120                call->get_args().push_back( throwStmt->get_expr() );
    115121                Statement * result = new ExprStmt( throwStmt->get_labels(), call );
    116122                throwStmt->set_expr( nullptr );
     
    120126        Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) {
    121127                // __rethrow_terminate();
     128                assert( nullptr == throwStmt->get_expr() );
    122129                Statement * result = new ExprStmt(
    123130                        throwStmt->get_labels(),
    124                         new ApplicationExpr( /* ... */ );
     131                        new UntypedExpr( new NameExpr( "__cfaehm__rethrow_termination" ) )
    125132                        );
    126133                delete throwStmt;
     
    129136        Statement * create_resume_throw( ThrowStmt *throwStmt ) {
    130137                // __throw_resume( EXPR );
    131                 ApplicationExpr * call = new ApplicationExpr( /* ... */ );
    132                 call->get_args.push_back( throwStmt->get_expr() );
     138                UntypedExpr * call = new UntypedExpr( new NameExpr(
     139                        "__cfaehm__throw_resumption" ) );
     140                call->get_args().push_back( throwStmt->get_expr() );
    133141                Statement * result = new ExprStmt( throwStmt->get_labels(), call );
    134142                throwStmt->set_expr( nullptr );
     
    140148                Statement * result = new ReturnStmt(
    141149                        throwStmt->get_labels(),
    142                         new ConstantExpr(
    143                                 Constant(
    144                                         new BasicType(
    145                                                 Type::Qualifiers(),
    146                                                 BasicType::Bool
    147                                                 ),
    148                                         "0")
    149                                 )
     150                        new ConstantExpr( Constant::from_bool( false ) )
    150151                        );
    151152                delete throwStmt;
     
    160161                return block;
    161162        }
    162         FunctionDecl * create_try_wrapper( TryStmt *tryStmt ) {
    163                 CompoundStmt * body = base_try->get_block();
    164                 base_try->set_block(nullptr);
    165 
    166                 return new FunctionDecl("try", Type::StorageClasses(),
    167                         LinkageSpec::Cforall, void_func_t, body);
     163        FunctionDecl * create_try_wrapper( CompoundStmt *body ) {
     164
     165                return new FunctionDecl( "try", Type::StorageClasses(),
     166                        LinkageSpec::Cforall, void_func_t.clone(), body );
    168167        }
    169168
    170169        FunctionDecl * create_terminate_catch( CatchList &handlers ) {
    171170                std::list<CaseStmt *> handler_wrappers;
     171
     172                FunctionType *func_type = catch_func_t.clone();
     173                DeclarationWithType * index_obj = func_type->get_parameters().front();
     174        //      DeclarationWithType * except_obj = func_type->get_parameters().back();
    172175
    173176                // Index 1..{number of handlers}
     
    178181                        CatchStmt * handler = *it;
    179182
    180                         std::list<Statement *> core;
    181                         if ( /*the exception is named*/ ) {
    182                                 ObjectDecl * local_except = /* Dynamic case, same */;
    183                                 core->push_back( new DeclStmt( noLabel, local_except ) );
    184                         }
    185                         // Append the provided statement to the handler.
    186                         core->push_back( cur_handler->get_body() );
    187                         // Append return onto the inner block? case stmt list?
    188                         CaseStmt * wrapper = new CaseStmt(
     183                        // INTEGERconstant Version
     184                        // case `index`:
     185                        // {
     186                        //     `handler.body`
     187                        // }
     188                        // return;
     189                        std::list<Statement *> caseBody;
     190                        caseBody.push_back( handler->get_body() );
     191                        handler->set_body( nullptr );
     192                        caseBody.push_back( new ReturnStmt( noLabels, nullptr ) );
     193
     194                        handler_wrappers.push_back( new CaseStmt(
    189195                                noLabels,
    190196                                new ConstantExpr( Constant::from_int( index ) ),
    191                                 core
    192                                 );
    193                         handler_wrappers.push_back(wrapper);
     197                                caseBody
     198                                ) );
    194199                }
    195200                // TODO: Some sort of meaningful error on default perhaps?
     201
     202                std::list<Statement*> stmt_handlers;
     203                while ( !handler_wrappers.empty() ) {
     204                        stmt_handlers.push_back( handler_wrappers.front() );
     205                        handler_wrappers.pop_front();
     206                }
    196207
    197208                SwitchStmt * handler_lookup = new SwitchStmt(
    198209                        noLabels,
    199                         /*parameter 0: index*/,
    200                         handler_wrappers,
    201                         false
     210                        nameOf( index_obj ),
     211                        stmt_handlers
    202212                        );
    203213                CompoundStmt * body = new CompoundStmt( noLabels );
     
    205215
    206216                return new FunctionDecl("catch", Type::StorageClasses(),
    207                         LinkageSpec::Cforall, catch_func_t, body);
     217                        LinkageSpec::Cforall, func_type, body);
    208218        }
    209219
    210220        // Create a single check from a moddified handler.
    211         CompoundStmt *create_single_matcher( CatchStmt * modded_handler ) {
    212                 CompoundStmt * block = new CompoundStmt( noLables );
    213 
    214                 appendDeclStmt( block, modded_handler->get_decl() );
    215 
    216                 // TODO: This is not the actual check.
    217                 LogicalExpr * cond = new ConstantExpr( Constant::from_bool( false ) );
     221        // except_obj is referenced, modded_handler will be freed.
     222        CompoundStmt *create_single_matcher(
     223                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
     224                CompoundStmt * block = new CompoundStmt( noLabels );
     225
     226                // INTEGERconstant Version
     227                assert( nullptr == modded_handler->get_decl() );
     228                ConstantExpr * number =
     229                        dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
     230                assert( number );
     231                modded_handler->set_cond( nullptr );
     232
     233                Expression * cond;
     234                {
     235                        std::list<Expression *> args;
     236                        args.push_back( number );
     237                        args.push_back( nameOf( except_obj ) );
     238                        cond = new UntypedExpr( new NameExpr( "?==?" /*???*/), args );
     239                }
    218240
    219241                if ( modded_handler->get_cond() ) {
    220                         cond = new LogicalExpr( cond, modded_handler->get_cond() )q
     242                        cond = new LogicalExpr( cond, modded_handler->get_cond() );
    221243                }
    222244                block->push_back( new IfStmt( noLabels,
    223                         cond, modded_handler->get_body() );
     245                        cond, modded_handler->get_body(), nullptr ) );
    224246
    225247                modded_handler->set_decl( nullptr );
     
    232254        FunctionDecl * create_terminate_match( CatchList &handlers ) {
    233255                CompoundStmt * body = new CompoundStmt( noLabels );
     256
     257                FunctionType * func_type = match_func_t.clone();
     258                DeclarationWithType * except_obj = func_type->get_parameters().back();
    234259
    235260                // Index 1..{number of handlers}
     
    240265                        CatchStmt * handler = *it;
    241266
    242                         // body should have been taken by create_terminate_catch.
    243                         // assert( nullptr == handler->get_body() );
     267                        // Body should have been taken by create_terminate_catch.
     268                        assert( nullptr == handler->get_body() );
     269
     270                        // Create new body.
    244271                        handler->set_body( new ReturnStmt( noLabels,
    245272                                new ConstantExpr( Constant::from_int( index ) ) ) );
    246273
    247                         body->push_back( create_single_matcher( handler ) );
     274                        // Create the handler.
     275                        body->push_back( create_single_matcher( except_obj, handler ) );
     276                        *it = nullptr;
    248277                }
    249278
    250279                return new FunctionDecl("match", Type::StorageClasses(),
    251                         LinkageSpec::Cforall, match_func_t, body);
    252         }
    253 
    254         Statement * create_terminate_caller(
     280                        LinkageSpec::Cforall, func_type, body);
     281        }
     282
     283        CompoundStmt * create_terminate_caller(
    255284                        FunctionDecl * try_wrapper,
    256285                        FunctionDecl * terminate_catch,
    257286                        FunctionDecl * terminate_match) {
    258287
    259                 ApplicationExpr * caller = new ApplicationExpr( /* ... */ );
    260                 std::list<Expression *>& args = caller.get_args();
     288                UntypedExpr * caller = new UntypedExpr( new NameExpr(
     289                        "__cfaehm__try_terminate" ) );
     290                std::list<Expression *>& args = caller->get_args();
    261291                args.push_back( nameOf( try_wrapper ) );
    262292                args.push_back( nameOf( terminate_catch ) );
    263293                args.push_back( nameOf( terminate_match ) );
    264294
    265                 return new ExprStmt( noLabels, caller );
     295                CompoundStmt * callStmt = new CompoundStmt( noLabels );
     296                callStmt->push_back( new ExprStmt( noLabels, caller ) );
     297                return callStmt;
    266298        }
    267299
    268300        FunctionDecl * create_resume_handler( CatchList &handlers ) {
    269                 CompoundStmt * body = new CompountStmt( noLabels );
     301                CompoundStmt * body = new CompoundStmt( noLabels );
     302
     303                FunctionType * func_type = match_func_t.clone();
     304                DeclarationWithType * except_obj = func_type->get_parameters().back();
    270305
    271306                CatchList::iterator it;
     
    280315                                handling_code->push_back( handler->get_body() );
    281316                        }
    282                         handling_code->push_back( new ReturnStmt( noLabel,
     317                        handling_code->push_back( new ReturnStmt( noLabels,
    283318                                new ConstantExpr( Constant::from_bool( false ) ) ) );
    284319                        handler->set_body( handling_code );
    285320
    286321                        // Create the handler.
    287                         body->push_back( create_single_matcher( handler ) );
     322                        body->push_back( create_single_matcher( except_obj, handler ) );
     323                        *it = nullptr;
    288324                }
    289325
    290326                return new FunctionDecl("handle", Type::StorageClasses(),
    291                         LinkageSpec::Cforall, handle_func_t, body);
    292         }
    293 
    294         Statement * create_resume_wrapper(
     327                        LinkageSpec::Cforall, func_type, body);
     328        }
     329
     330        CompoundStmt * create_resume_wrapper(
     331                        StructDecl * node_decl,
    295332                        Statement * wraps,
    296333                        FunctionDecl * resume_handler ) {
    297334                CompoundStmt * body = new CompoundStmt( noLabels );
    298335
    299                 // struct node = {current top resume handler, call to resume_handler};
    300                 // __attribute__((cleanup( ... )));
    301                 // set top resume handler to node.
    302                 // The wrapped statement.
    303 
    304                 ListInit * node_init;
    305                 {
    306                         std::list<Initializer*> field_inits;
    307                         field_inits.push_back( new SingleInit( /* ... */ ) );
    308                         field_inits.push_back( new SingleInit( nameOf( resume_handler ) ) );
    309                         node_init = new ListInit( field_inits );
    310                 }
     336                // struct __try_resume_node __resume_node
     337                //      __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
     338                // ** unwinding of the stack here could cause problems **
     339                // ** however I don't think that can happen currently **
     340                // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
    311341
    312342                std::list< Attribute * > attributes;
    313343                {
    314344                        std::list< Expression * > attr_params;
    315                         attr_params.push_back( nameOf( /* ... deconstructor ... */ ) );
    316                         attrributes.push_back( new Attribute( "cleanup", attr_params ) );
    317                 }
    318 
    319                 appendDeclStmt( body,
    320                 /**/ ObjectDecl(
    321                         "resume_node",
     345                        attr_params.push_back( new NameExpr(
     346                                "__cfaehm__try_resume_cleanup" ) );
     347                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
     348                }
     349
     350                ObjectDecl * obj = new ObjectDecl(
     351                        "__resume_node",
    322352                        Type::StorageClasses(),
    323353                        LinkageSpec::Cforall,
    324354                        nullptr,
    325                         /* Type* = resume_node */,
    326                         node_init,
     355                        new StructInstType(
     356                                Type::Qualifiers(),
     357                                node_decl
     358                                ),
     359                        nullptr,
    327360                        attributes
    328                         )
    329                 );
     361                        );
     362                appendDeclStmt( body, obj );
     363
     364                UntypedExpr *setup = new UntypedExpr( new NameExpr(
     365                        "__cfaehm__try_resume_setup" ) );
     366                setup->get_args().push_back( nameOf( obj ) );
     367                setup->get_args().push_back( nameOf( resume_handler ) );
     368
     369                body->push_back( new ExprStmt( noLabels, setup ) );
     370
    330371                body->push_back( wraps );
    331372                return body;
     
    333374
    334375        FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
    335                 CompoundStmt * body = tryStmt->get_finally();
     376                FinallyStmt * finally = tryStmt->get_finally();
     377                CompoundStmt * body = finally->get_block();
     378                finally->set_block( nullptr );
     379                delete finally;
    336380                tryStmt->set_finally( nullptr );
    337381
    338382                return new FunctionDecl("finally", Type::StorageClasses(),
    339                         LinkageSpec::Cforall, void_func_t, body);
    340         }
    341 
    342         ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper ) {
    343                 // struct _cleanup_hook NAME __attribute__((cleanup( ... )));
     383                        LinkageSpec::Cforall, void_func_t.clone(), body);
     384        }
     385
     386        ObjectDecl * create_finally_hook(
     387                        StructDecl * hook_decl, FunctionDecl * finally_wrapper ) {
     388                // struct __cfaehm__cleanup_hook __finally_hook
     389                //      __attribute__((cleanup( finally_wrapper )));
    344390
    345391                // Make Cleanup Attribute.
     
    348394                        std::list< Expression * > attr_params;
    349395                        attr_params.push_back( nameOf( finally_wrapper ) );
    350                         attrributes.push_back( new Attribute( "cleanup", attr_params ) );
    351                 }
    352 
    353                 return ObjectDecl( /* ... */
    354                         const std::string &name "finally_hook",
     396                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
     397                }
     398
     399                return new ObjectDecl(
     400                        "__finally_hook",
    355401                        Type::StorageClasses(),
    356402                        LinkageSpec::Cforall,
    357403                        nullptr,
    358                         /* ... Type * ... */,
     404                        new StructInstType(
     405                                emptyQualifiers,
     406                                hook_decl
     407                                ),
    359408                        nullptr,
    360409                        attributes
     
    363412
    364413
    365         class ExceptionMutatorCore : public WithScoping {
     414        class ExceptionMutatorCore : public WithScopes {
    366415                enum Context { NoHandler, TerHandler, ResHandler };
    367416
     
    370419                // loop, switch or the goto stays within the function.
    371420
    372                 Context curContext;
     421                Context cur_context;
    373422
    374423                // We might not need this, but a unique base for each try block's
     
    377426                //unsigned int try_count = 0;
    378427
     428                StructDecl *node_decl;
     429                StructDecl *hook_decl;
    379430
    380431        public:
    381432                ExceptionMutatorCore() :
    382                         curContext(NoHandler)
     433                        cur_context(NoHandler),
     434                        node_decl(nullptr), hook_decl(nullptr)
    383435                {}
    384436
    385                 void premutate( CatchStmt *tryStmt );
     437                void premutate( CatchStmt *catchStmt );
     438                void premutate( StructDecl *structDecl );
    386439                Statement * postmutate( ThrowStmt *throwStmt );
    387440                Statement * postmutate( TryStmt *tryStmt );
     
    393446                        if ( throwStmt->get_expr() ) {
    394447                                return create_terminate_throw( throwStmt );
    395                         } else if ( TerHandler == curContext ) {
     448                        } else if ( TerHandler == cur_context ) {
    396449                                return create_terminate_rethrow( throwStmt );
    397450                        } else {
    398451                                assertf(false, "Invalid throw in %s at %i\n",
    399                                         throwStmt->location.filename,
     452                                        throwStmt->location.filename.c_str(),
    400453                                        throwStmt->location.linenumber);
    401454                                return nullptr;
     
    404457                        if ( throwStmt->get_expr() ) {
    405458                                return create_resume_throw( throwStmt );
    406                         } else if ( ResHandler == curContext ) {
     459                        } else if ( ResHandler == cur_context ) {
    407460                                return create_resume_rethrow( throwStmt );
    408461                        } else {
    409462                                assertf(false, "Invalid throwResume in %s at %i\n",
    410                                         throwStmt->location.filename,
     463                                        throwStmt->location.filename.c_str(),
    411464                                        throwStmt->location.linenumber);
    412465                                return nullptr;
     
    416469
    417470        Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
     471                assert( node_decl );
     472                assert( hook_decl );
     473
    418474                // Generate a prefix for the function names?
    419475
    420                 CompoundStmt * block = new CompoundStmt();
    421                 Statement * inner = take_try_block( tryStmt );
     476                CompoundStmt * block = new CompoundStmt( noLabels );
     477                CompoundStmt * inner = take_try_block( tryStmt );
    422478
    423479                if ( tryStmt->get_finally() ) {
     
    427483                        appendDeclStmt( block, finally_block );
    428484                        // Create and add the finally cleanup hook.
    429                         appendDeclStmt( block, create_finally_hook( finally_block ) );
    430                 }
    431 
    432                 StatementList termination_handlers;
    433                 StatementList resumption_handlers;
    434                 split( tryStmt->get_handlers(),
     485                        appendDeclStmt( block,
     486                                create_finally_hook( hook_decl, finally_block ) );
     487                }
     488
     489                CatchList termination_handlers;
     490                CatchList resumption_handlers;
     491                split( tryStmt->get_catchers(),
    435492                       termination_handlers, resumption_handlers );
    436493
    437                 if ( resumeption_handlers.size() ) {
     494                if ( resumption_handlers.size() ) {
    438495                        // Define the helper function.
    439496                        FunctionDecl * resume_handler =
     
    441498                        appendDeclStmt( block, resume_handler );
    442499                        // Prepare hooks
    443                         inner = create_resume_wrapper( inner, resume_handler );
     500                        inner = create_resume_wrapper( node_decl, inner, resume_handler );
    444501                }
    445502
     
    462519                block->push_back( inner );
    463520
    464                 free_all( termination_handlers );
    465                 free_all( resumption_handlers );
     521                //free_all( termination_handlers );
     522                //free_all( resumption_handlers );
    466523
    467524                return block;
     
    469526
    470527        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
    471                 GuardValue( curContext );
    472                 if ( CatchStmt::Termination == catchStmt->get_kind() ) {
    473                         curContext = TerHandler;
     528                GuardValue( cur_context );
     529                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
     530                        cur_context = TerHandler;
    474531                } else {
    475                         curContext = ResHandler;
    476                 }
     532                        cur_context = ResHandler;
     533                }
     534        }
     535
     536        void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
     537                if ( !structDecl->has_body() ) {
     538                        // Skip children?
     539                        return;
     540                } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
     541                        assert( nullptr == node_decl );
     542                        node_decl = structDecl;
     543                } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
     544                        assert( nullptr == hook_decl );
     545                        hook_decl = structDecl;
     546                }
     547                // Later we might get the exception type as well.
    477548        }
    478549
    479550    void translateEHM( std::list< Declaration *> & translationUnit ) {
     551                init_func_types();
     552
    480553                PassVisitor<ExceptionMutatorCore> translator;
    481554                for ( Declaration * decl : translationUnit ) {
    482                         decl->mutate( translator );
     555                        decl->acceptMutator( translator );
    483556                }
    484557        }
Note: See TracChangeset for help on using the changeset viewer.