Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    r1abc5ab5 rba912706  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Jun 29 15:18:00 2017
    13 // Update Count     : 1
     12// Last Modified On : Thr Jun 22 15:57:00 2017
     13// Update Count     : 0
    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"
    2318
    2419namespace ControlFlow {
     
    3934
    4035        static void init_func_types() {
    41                 static bool init_complete = false;
     36                static init_complete = false;
    4237                if (init_complete) {
    4338                        return;
    4439                }
    4540                ObjectDecl index_obj(
    46                         "__handler_index",
     41                        "index_t",
    4742                        Type::StorageClasses(),
    4843                        LinkageSpec::Cforall,
     
    5247                );
    5348                ObjectDecl exception_obj(
    54                         "__exception_inst",
     49                        "exception_t",
    5550                        Type::StorageClasses(),
    5651                        LinkageSpec::Cforall,
     
    6055                );
    6156                ObjectDecl bool_obj(
    62                         "__ret_bool",
     57                        "bool_t",
    6358                        Type::StorageClasses(),
    6459                        LinkageSpec::Cforall,
     
    8378
    8479        void split( CatchList& allHandlers, CatchList& terHandlers,
    85                                 CatchList& resHandlers ) {
     80                    CatchList& resHandlers ) {
    8681                while ( !allHandlers.empty() ) {
    87                         CatchStmt * stmt = allHandlers.front();
     82                        Statement * stmt = allHandlers.front();
    8883                        allHandlers.pop_front();
    89                         if (CatchStmt::Terminate == stmt->get_kind()) {
     84                        if (CaseStmt::Terminate == stmt->get_kind()) {
    9085                                terHandlers.push_back(stmt);
    9186                        } else {
     
    9792        template<typename T>
    9893        void free_all( std::list<T *> &list ) {
    99                 typename std::list<T *>::iterator it;
     94                std::list<T *>::iterator it;
    10095                for ( it = list.begin() ; it != list.end() ; ++it ) {
    10196                        delete *it;
     
    105100
    106101        void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
    107                 block->push_back(new DeclStmt(noLabels, item));
    108         }
    109 
    110         Expression * nameOf( DeclarationWithType * decl ) {
    111                 return new VariableExpr( decl );
     102                block->push_back(new DeclStmt(no_labels, item));
     103        }
     104
     105        Expression * nameOf( FunctionDecl * function ) {
     106                return new VariableExpr( function );
    112107        }
    113108
     
    116111        Statement * create_terminate_throw( ThrowStmt *throwStmt ) {
    117112                // __throw_terminate( EXPR );
    118                 UntypedExpr * call = new UntypedExpr( new NameExpr(
    119                         "__cfaehm__throw_termination" ) );
    120                 call->get_args().push_back( throwStmt->get_expr() );
     113                ApplicationExpr * call = new ApplicationExpr( /* ... */ );
     114                call->get_args.push_back( throwStmt->get_expr() );
    121115                Statement * result = new ExprStmt( throwStmt->get_labels(), call );
    122116                throwStmt->set_expr( nullptr );
     
    126120        Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) {
    127121                // __rethrow_terminate();
    128                 assert( nullptr == throwStmt->get_expr() );
    129122                Statement * result = new ExprStmt(
    130123                        throwStmt->get_labels(),
    131                         new UntypedExpr( new NameExpr( "__cfaehm__rethrow_termination" ) )
     124                        new ApplicationExpr( /* ... */ );
    132125                        );
    133126                delete throwStmt;
     
    136129        Statement * create_resume_throw( ThrowStmt *throwStmt ) {
    137130                // __throw_resume( EXPR );
    138                 UntypedExpr * call = new UntypedExpr( new NameExpr(
    139                         "__cfaehm__throw_resumption" ) );
    140                 call->get_args().push_back( throwStmt->get_expr() );
     131                ApplicationExpr * call = new ApplicationExpr( /* ... */ );
     132                call->get_args.push_back( throwStmt->get_expr() );
    141133                Statement * result = new ExprStmt( throwStmt->get_labels(), call );
    142134                throwStmt->set_expr( nullptr );
     
    148140                Statement * result = new ReturnStmt(
    149141                        throwStmt->get_labels(),
    150                         new ConstantExpr( Constant::from_bool( false ) )
     142                        new ConstantExpr(
     143                                Constant(
     144                                        new BasicType(
     145                                                Type::Qualifiers(),
     146                                                BasicType::Bool
     147                                                ),
     148                                        "0")
     149                                )
    151150                        );
    152151                delete throwStmt;
     
    161160                return block;
    162161        }
    163         FunctionDecl * create_try_wrapper( CompoundStmt *body ) {
    164 
    165                 return new FunctionDecl( "try", Type::StorageClasses(),
    166                         LinkageSpec::Cforall, void_func_t.clone(), body );
     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);
    167168        }
    168169
    169170        FunctionDecl * create_terminate_catch( CatchList &handlers ) {
    170171                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();
    175172
    176173                // Index 1..{number of handlers}
     
    181178                        CatchStmt * handler = *it;
    182179
    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(
     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(
    195189                                noLabels,
    196190                                new ConstantExpr( Constant::from_int( index ) ),
    197                                 caseBody
    198                                 ) );
     191                                core
     192                                );
     193                        handler_wrappers.push_back(wrapper);
    199194                }
    200195                // 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                 }
    207196
    208197                SwitchStmt * handler_lookup = new SwitchStmt(
    209198                        noLabels,
    210                         nameOf( index_obj ),
    211                         stmt_handlers
     199                        /*parameter 0: index*/,
     200                        handler_wrappers,
     201                        false
    212202                        );
    213203                CompoundStmt * body = new CompoundStmt( noLabels );
     
    215205
    216206                return new FunctionDecl("catch", Type::StorageClasses(),
    217                         LinkageSpec::Cforall, func_type, body);
     207                        LinkageSpec::Cforall, catch_func_t, body);
    218208        }
    219209
    220210        // Create a single check from a moddified handler.
    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                 }
     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 ) );
    240218
    241219                if ( modded_handler->get_cond() ) {
    242                         cond = new LogicalExpr( cond, modded_handler->get_cond() );
     220                        cond = new LogicalExpr( cond, modded_handler->get_cond() )q
    243221                }
    244222                block->push_back( new IfStmt( noLabels,
    245                         cond, modded_handler->get_body(), nullptr ) );
     223                        cond, modded_handler->get_body() );
    246224
    247225                modded_handler->set_decl( nullptr );
     
    254232        FunctionDecl * create_terminate_match( CatchList &handlers ) {
    255233                CompoundStmt * body = new CompoundStmt( noLabels );
    256 
    257                 FunctionType * func_type = match_func_t.clone();
    258                 DeclarationWithType * except_obj = func_type->get_parameters().back();
    259234
    260235                // Index 1..{number of handlers}
     
    265240                        CatchStmt * handler = *it;
    266241
    267                         // Body should have been taken by create_terminate_catch.
    268                         assert( nullptr == handler->get_body() );
    269 
    270                         // Create new body.
     242                        // body should have been taken by create_terminate_catch.
     243                        // assert( nullptr == handler->get_body() );
    271244                        handler->set_body( new ReturnStmt( noLabels,
    272245                                new ConstantExpr( Constant::from_int( index ) ) ) );
    273246
    274                         // Create the handler.
    275                         body->push_back( create_single_matcher( except_obj, handler ) );
    276                         *it = nullptr;
     247                        body->push_back( create_single_matcher( handler ) );
    277248                }
    278249
    279250                return new FunctionDecl("match", Type::StorageClasses(),
    280                         LinkageSpec::Cforall, func_type, body);
    281         }
    282 
    283         CompoundStmt * create_terminate_caller(
     251                        LinkageSpec::Cforall, match_func_t, body);
     252        }
     253
     254        Statement * create_terminate_caller(
    284255                        FunctionDecl * try_wrapper,
    285256                        FunctionDecl * terminate_catch,
    286257                        FunctionDecl * terminate_match) {
    287258
    288                 UntypedExpr * caller = new UntypedExpr( new NameExpr(
    289                         "__cfaehm__try_terminate" ) );
    290                 std::list<Expression *>& args = caller->get_args();
     259                ApplicationExpr * caller = new ApplicationExpr( /* ... */ );
     260                std::list<Expression *>& args = caller.get_args();
    291261                args.push_back( nameOf( try_wrapper ) );
    292262                args.push_back( nameOf( terminate_catch ) );
    293263                args.push_back( nameOf( terminate_match ) );
    294264
    295                 CompoundStmt * callStmt = new CompoundStmt( noLabels );
    296                 callStmt->push_back( new ExprStmt( noLabels, caller ) );
    297                 return callStmt;
     265                return new ExprStmt( noLabels, caller );
    298266        }
    299267
    300268        FunctionDecl * create_resume_handler( CatchList &handlers ) {
    301                 CompoundStmt * body = new CompoundStmt( noLabels );
    302 
    303                 FunctionType * func_type = match_func_t.clone();
    304                 DeclarationWithType * except_obj = func_type->get_parameters().back();
     269                CompoundStmt * body = new CompountStmt( noLabels );
    305270
    306271                CatchList::iterator it;
     
    315280                                handling_code->push_back( handler->get_body() );
    316281                        }
    317                         handling_code->push_back( new ReturnStmt( noLabels,
     282                        handling_code->push_back( new ReturnStmt( noLabel,
    318283                                new ConstantExpr( Constant::from_bool( false ) ) ) );
    319284                        handler->set_body( handling_code );
    320285
    321286                        // Create the handler.
    322                         body->push_back( create_single_matcher( except_obj, handler ) );
    323                         *it = nullptr;
     287                        body->push_back( create_single_matcher( handler ) );
    324288                }
    325289
    326290                return new FunctionDecl("handle", Type::StorageClasses(),
    327                         LinkageSpec::Cforall, func_type, body);
    328         }
    329 
    330         CompoundStmt * create_resume_wrapper(
    331                         StructDecl * node_decl,
     291                        LinkageSpec::Cforall, handle_func_t, body);
     292        }
     293
     294        Statement * create_resume_wrapper(
    332295                        Statement * wraps,
    333296                        FunctionDecl * resume_handler ) {
    334297                CompoundStmt * body = new CompoundStmt( noLabels );
    335298
    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 );
     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                }
    341311
    342312                std::list< Attribute * > attributes;
    343313                {
    344314                        std::list< Expression * > attr_params;
    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",
     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",
    352322                        Type::StorageClasses(),
    353323                        LinkageSpec::Cforall,
    354324                        nullptr,
    355                         new StructInstType(
    356                                 Type::Qualifiers(),
    357                                 node_decl
    358                                 ),
    359                         nullptr,
     325                        /* Type* = resume_node */,
     326                        node_init,
    360327                        attributes
    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 
     328                        )
     329                );
    371330                body->push_back( wraps );
    372331                return body;
     
    374333
    375334        FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
    376                 FinallyStmt * finally = tryStmt->get_finally();
    377                 CompoundStmt * body = finally->get_block();
    378                 finally->set_block( nullptr );
    379                 delete finally;
     335                CompoundStmt * body = tryStmt->get_finally();
    380336                tryStmt->set_finally( nullptr );
    381337
    382338                return new FunctionDecl("finally", Type::StorageClasses(),
    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 )));
     339                        LinkageSpec::Cforall, void_func_t, body);
     340        }
     341
     342        ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper ) {
     343                // struct _cleanup_hook NAME __attribute__((cleanup( ... )));
    390344
    391345                // Make Cleanup Attribute.
     
    394348                        std::list< Expression * > attr_params;
    395349                        attr_params.push_back( nameOf( finally_wrapper ) );
    396                         attributes.push_back( new Attribute( "cleanup", attr_params ) );
    397                 }
    398 
    399                 return new ObjectDecl(
    400                         "__finally_hook",
     350                        attrributes.push_back( new Attribute( "cleanup", attr_params ) );
     351                }
     352
     353                return ObjectDecl( /* ... */
     354                        const std::string &name "finally_hook",
    401355                        Type::StorageClasses(),
    402356                        LinkageSpec::Cforall,
    403357                        nullptr,
    404                         new StructInstType(
    405                                 emptyQualifiers,
    406                                 hook_decl
    407                                 ),
     358                        /* ... Type * ... */,
    408359                        nullptr,
    409360                        attributes
     
    412363
    413364
    414         class ExceptionMutatorCore : public WithGuards {
     365        class ExceptionMutatorCore : public WithScoping {
    415366                enum Context { NoHandler, TerHandler, ResHandler };
    416367
     
    419370                // loop, switch or the goto stays within the function.
    420371
    421                 Context cur_context;
     372                Context curContext;
    422373
    423374                // We might not need this, but a unique base for each try block's
     
    426377                //unsigned int try_count = 0;
    427378
    428                 StructDecl *node_decl;
    429                 StructDecl *hook_decl;
    430379
    431380        public:
    432381                ExceptionMutatorCore() :
    433                         cur_context(NoHandler),
    434                         node_decl(nullptr), hook_decl(nullptr)
     382                        curContext(NoHandler)
    435383                {}
    436384
    437                 void premutate( CatchStmt *catchStmt );
    438                 void premutate( StructDecl *structDecl );
     385                void premutate( CatchStmt *tryStmt );
    439386                Statement * postmutate( ThrowStmt *throwStmt );
    440387                Statement * postmutate( TryStmt *tryStmt );
     
    446393                        if ( throwStmt->get_expr() ) {
    447394                                return create_terminate_throw( throwStmt );
    448                         } else if ( TerHandler == cur_context ) {
     395                        } else if ( TerHandler == curContext ) {
    449396                                return create_terminate_rethrow( throwStmt );
    450397                        } else {
    451398                                assertf(false, "Invalid throw in %s at %i\n",
    452                                         throwStmt->location.filename.c_str(),
     399                                        throwStmt->location.filename,
    453400                                        throwStmt->location.linenumber);
    454401                                return nullptr;
     
    457404                        if ( throwStmt->get_expr() ) {
    458405                                return create_resume_throw( throwStmt );
    459                         } else if ( ResHandler == cur_context ) {
     406                        } else if ( ResHandler == curContext ) {
    460407                                return create_resume_rethrow( throwStmt );
    461408                        } else {
    462409                                assertf(false, "Invalid throwResume in %s at %i\n",
    463                                         throwStmt->location.filename.c_str(),
     410                                        throwStmt->location.filename,
    464411                                        throwStmt->location.linenumber);
    465412                                return nullptr;
     
    469416
    470417        Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
    471                 assert( node_decl );
    472                 assert( hook_decl );
    473 
    474418                // Generate a prefix for the function names?
    475419
    476                 CompoundStmt * block = new CompoundStmt( noLabels );
    477                 CompoundStmt * inner = take_try_block( tryStmt );
     420                CompoundStmt * block = new CompoundStmt();
     421                Statement * inner = take_try_block( tryStmt );
    478422
    479423                if ( tryStmt->get_finally() ) {
     
    483427                        appendDeclStmt( block, finally_block );
    484428                        // Create and add the finally cleanup hook.
    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(),
    492                            termination_handlers, resumption_handlers );
    493 
    494                 if ( resumption_handlers.size() ) {
     429                        appendDeclStmt( block, create_finally_hook( finally_block ) );
     430                }
     431
     432                StatementList termination_handlers;
     433                StatementList resumption_handlers;
     434                split( tryStmt->get_handlers(),
     435                       termination_handlers, resumption_handlers );
     436
     437                if ( resumeption_handlers.size() ) {
    495438                        // Define the helper function.
    496439                        FunctionDecl * resume_handler =
     
    498441                        appendDeclStmt( block, resume_handler );
    499442                        // Prepare hooks
    500                         inner = create_resume_wrapper( node_decl, inner, resume_handler );
     443                        inner = create_resume_wrapper( inner, resume_handler );
    501444                }
    502445
     
    519462                block->push_back( inner );
    520463
    521                 //free_all( termination_handlers );
    522                 //free_all( resumption_handlers );
     464                free_all( termination_handlers );
     465                free_all( resumption_handlers );
    523466
    524467                return block;
     
    526469
    527470        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
    528                 GuardValue( cur_context );
    529                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    530                         cur_context = TerHandler;
     471                GuardValue( curContext );
     472                if ( CatchStmt::Termination == catchStmt->get_kind() ) {
     473                        curContext = TerHandler;
    531474                } else {
    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.
    548         }
    549 
    550         void translateEHM( std::list< Declaration *> & translationUnit ) {
    551                 init_func_types();
    552 
     475                        curContext = ResHandler;
     476                }
     477        }
     478
     479    void translateEHM( std::list< Declaration *> & translationUnit ) {
    553480                PassVisitor<ExceptionMutatorCore> translator;
    554481                for ( Declaration * decl : translationUnit ) {
    555                         decl->acceptMutator( translator );
     482                        decl->mutate( translator );
    556483                }
    557484        }
Note: See TracChangeset for help on using the changeset viewer.