Ignore:
Timestamp:
Jul 28, 2017, 2:06:10 PM (7 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
03eedd5, 79dbb79
Parents:
a2e0687
Message:

Added the memory management calls to the exception control flow.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    ra2e0687 r86d5ba7c  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Jul 18 10:09:00 2017
    13 // Update Count     : 4
     12// Last Modified On : Fri Jul 28 14:03:00 2017
     13// Update Count     : 5
    1414//
    1515
     
    2121#include "SynTree/Type.h"
    2222#include "SynTree/Attribute.h"
     23#include "SynTree/VarExprReplacer.h"
    2324
    2425namespace ControlStruct {
    2526
    26         // This (large) section could probably be moved out of the class
    27         // and be static helpers instead.
    28 
    29         // Type(Qualifiers &, false, std::list<Attribute *> &)
    30 
    3127        // void (*function)();
    32         static FunctionType try_func_t(Type::Qualifiers(), false);
     28        static FunctionType try_func_t(noQualifiers, false);
    3329        // void (*function)(int, exception);
    34         static FunctionType catch_func_t(Type::Qualifiers(), false);
     30        static FunctionType catch_func_t(noQualifiers, false);
    3531        // int (*function)(exception);
    36         static FunctionType match_func_t(Type::Qualifiers(), false);
     32        static FunctionType match_func_t(noQualifiers, false);
    3733        // bool (*function)(exception);
    38         static FunctionType handle_func_t(Type::Qualifiers(), false);
     34        static FunctionType handle_func_t(noQualifiers, false);
    3935        // void (*function)(__attribute__((unused)) void *);
    40         static FunctionType finally_func_t(Type::Qualifiers(), false);
     36        static FunctionType finally_func_t(noQualifiers, false);
    4137
    4238        static void init_func_types() {
     
    115111        }
    116112
    117         template<typename T>
    118         void free_all( std::list<T *> &list ) {
    119                 typename std::list<T *>::iterator it;
    120                 for ( it = list.begin() ; it != list.end() ; ++it ) {
    121                         delete *it;
    122                 }
    123                 list.clear();
    124         }
    125 
    126113        void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
    127114                block->push_back(new DeclStmt(noLabels, item));
     
    136123        Statement * create_given_throw(
    137124                        const char * throwFunc, ThrowStmt * throwStmt ) {
     125                // There is an extra copy here we might be able to remove with
     126                // references.
    138127                // { int NAME = EXPR; throwFunc( &NAME ); }
    139128                CompoundStmt * result = new CompoundStmt( noLabels );
     
    159148                return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
    160149        }
    161         Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) {
    162                 // __rethrow_terminate();
     150
     151        Statement * create_terminate_rethrow( ThrowStmt *throwStmt,
     152                        ObjectDecl *handler_except_decl ) {
     153                // { `handler_except_decl` = NULL; __rethrow_terminate(); }
    163154                assert( nullptr == throwStmt->get_expr() );
    164                 Statement * result = new ExprStmt(
    165                         throwStmt->get_labels(),
     155                assert( handler_except_decl );
     156
     157                CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
     158                result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
     159                        nameOf( handler_except_decl ),
     160                        new ConstantExpr( Constant::null(
     161                                new PointerType(
     162                                        noQualifiers,
     163                                        handler_except_decl->get_type()->clone()
     164                                        )
     165                                ) )
     166                        ) ) );
     167                result->push_back( new ExprStmt(
     168                        noLabels,
    166169                        new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
    167                         );
     170                        ) );
    168171                delete throwStmt;
    169172                return result;
    170173        }
     174
    171175        Statement * create_resume_throw( ThrowStmt *throwStmt ) {
    172176                // __throw_resume( EXPR );
    173177                return create_given_throw( "__cfaehm__throw_resume", throwStmt );
    174178        }
     179
    175180        Statement * create_resume_rethrow( ThrowStmt *throwStmt ) {
    176181                // return false;
     
    201206                FunctionType *func_type = catch_func_t.clone();
    202207                DeclarationWithType * index_obj = func_type->get_parameters().front();
    203         //      DeclarationWithType * except_obj = func_type->get_parameters().back();
     208                DeclarationWithType * except_obj = func_type->get_parameters().back();
    204209
    205210                // Index 1..{number of handlers}
     
    213218                        // case `index`:
    214219                        // {
     220                        //     `handler.decl` {inserted} = { except_obj };
    215221                        //     `handler.body`
    216222                        // }
    217223                        // return;
    218                         std::list<Statement *> caseBody;
    219                         caseBody.push_back( handler->get_body() );
     224                        CompoundStmt * block = new CompoundStmt( noLabels );
     225
     226                        // Just copy the exception value.
     227                        // TODO: Or just store an ObjectDecl?
     228                        ObjectDecl * handler_decl =
     229                                dynamic_cast<ObjectDecl*>( handler->get_decl() );
     230                        assert( handler_decl );
     231                        ObjectDecl * local_except = handler_decl->clone();
     232                        local_except->set_init(
     233                                new ListInit({ new SingleInit( nameOf( except_obj ) ) }) );
     234#if 0
     235                        // Virtual Exception Vision
     236                        // case `index`:
     237                        // {
     238                        //     `handler.decl` = { (virtual `decl.type`)`except` };
     239                        //     `handler.body`;
     240                        // }
     241                        // return;
     242
     243                        // Save a cast copy of the exception (should always succeed).
     244                        ObjectDecl * local_except = handler->get_decl()->clone();
     245                        local_except.set_init(
     246                                new ListInit({ new SingleInit(
     247                                        new VirtualCastExpr( nameOf( except_obj ),
     248                                                local_except->get_type()
     249                                                )
     250                                        ) }) );
     251#endif
     252                        block->push_back( new DeclStmt( noLabels, local_except ) );
     253
     254                        // Add the cleanup attribute.
     255                        local_except->get_attributes().push_back( new Attribute(
     256                                "cleanup",
     257                                { new NameExpr( "__cfaehm__cleanup_terminate" ) }
     258                                ) );
     259
     260                        // Update variables in the body to point to this local copy.
     261                        {
     262                                VarExprReplacer::DeclMap mapping;
     263                                mapping[ handler_decl ] = local_except;
     264                                VarExprReplacer mapper( mapping );
     265                                handler->get_body()->accept( mapper );
     266                        }
     267
     268                        block->push_back( handler->get_body() );
    220269                        handler->set_body( nullptr );
    221                         caseBody.push_back( new ReturnStmt( noLabels, nullptr ) );
    222 
     270
     271                        std::list<Statement *> caseBody
     272                                        { block, new ReturnStmt( noLabels, nullptr ) };
    223273                        handler_wrappers.push_back( new CaseStmt(
    224274                                noLabels,
     
    253303                CompoundStmt * block = new CompoundStmt( noLabels );
    254304
     305                ObjectDecl * local_except =
     306                        dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
     307                assert( local_except );
     308                block->push_back( new DeclStmt( noLabels, local_except ) );
     309#if 0
     310                // Virtual Exception Version
     311                // {
     312                //     `modded_handler.decl`
     313                //     if ( `decl.name = (virtual)`except`
     314                //             [&& `modded_handler.cond`] ) {
     315                //         `modded_handler.body`
     316                //     }
     317                // }
     318
     319                // Check for type match.
     320                Expression * cond = UntypedExpr::createAssign( nameOf( local_except ),
     321                        new VirtualCastExpr( nameOf( except_obj ),
     322                                local_except->get_type()->clone() ) );
     323#endif
     324
    255325                // INTEGERconstant Version
    256                 assert( nullptr == modded_handler->get_decl() );
     326                // {
     327                //     `modded_handler.decl` = *`except`
     328                //     if ( `decl.name` == `modded_handler.cond` ) {
     329                //         `modded_handler.body`
     330                //     }
     331                // }
    257332                ConstantExpr * number =
    258333                        dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
     
    274349                }
    275350
     351                // Add the check on the conditional if it is provided.
    276352                if ( modded_handler->get_cond() ) {
    277353                        cond = new LogicalExpr( cond, modded_handler->get_cond() );
    278354                }
     355                // Construct the match condition.
    279356                block->push_back( new IfStmt( noLabels,
    280357                        cond, modded_handler->get_body(), nullptr ) );
     
    288365
    289366        FunctionDecl * create_terminate_match( CatchList &handlers ) {
     367                // int match(exception * except) {
     368                //     HANDLER WRAPPERS { return `index`; }
     369                // }
     370
    290371                CompoundStmt * body = new CompoundStmt( noLabels );
    291372
     
    323404                        FunctionDecl * terminate_catch,
    324405                        FunctionDecl * terminate_match) {
     406                // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
    325407
    326408                UntypedExpr * caller = new UntypedExpr( new NameExpr(
     
    337419
    338420        FunctionDecl * create_resume_handler( CatchList &handlers ) {
     421                // bool handle(exception * except) {
     422                //     HANDLER WRAPPERS { `hander->body`; return true; }
     423                // }
    339424                CompoundStmt * body = new CompoundStmt( noLabels );
    340425
     
    415500
    416501        FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
     502                // void finally() { <finally code> }
    417503                FinallyStmt * finally = tryStmt->get_finally();
    418504                CompoundStmt * body = finally->get_block();
     
    462548                Context cur_context;
    463549
     550                // The current (innermost) termination handler exception declaration.
     551                ObjectDecl * handler_except_decl;
     552
    464553                // We might not need this, but a unique base for each try block's
    465554                // generated functions might be nice.
     
    473562                ExceptionMutatorCore() :
    474563                        cur_context(NoHandler),
    475                         node_decl(nullptr), hook_decl(nullptr)
     564                        handler_except_decl( nullptr ),
     565                        node_decl( nullptr ), hook_decl( nullptr )
    476566                {}
    477567
     
    481571                Statement * postmutate( TryStmt *tryStmt );
    482572        };
     573
     574        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
     575                // Currently, we make up the declaration, as there isn't one for
     576                // integers.
     577                ObjectDecl * tmp = new ObjectDecl(
     578                        "_hidden_local",
     579                        Type::StorageClasses(),
     580                        LinkageSpec::Cforall,
     581                        nullptr,
     582                        new PointerType(
     583                                noQualifiers,
     584                                new BasicType( noQualifiers, BasicType::SignedInt )
     585                                ),
     586                        nullptr
     587                        );
     588                catchStmt->set_decl( tmp );
     589
     590                GuardValue( cur_context );
     591                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
     592                        cur_context = TerHandler;
     593
     594                        GuardValue( handler_except_decl );
     595                        handler_except_decl = tmp;
     596                        //handler_except_decl = catchStmt->get_decl();
     597                } else {
     598                        cur_context = ResHandler;
     599                }
     600        }
     601
     602        void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
     603                if ( !structDecl->has_body() ) {
     604                        // Skip children?
     605                        return;
     606                } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
     607                        assert( nullptr == node_decl );
     608                        node_decl = structDecl;
     609                } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
     610                        assert( nullptr == hook_decl );
     611                        hook_decl = structDecl;
     612                }
     613                // Later we might get the exception type as well.
     614        }
    483615
    484616        Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
     
    488620                                return create_terminate_throw( throwStmt );
    489621                        } else if ( TerHandler == cur_context ) {
    490                                 return create_terminate_rethrow( throwStmt );
     622                                return create_terminate_rethrow(
     623                                        throwStmt, handler_except_decl );
    491624                        } else {
    492625                                assertf(false, "Invalid throw in %s at %i\n",
     
    560693                block->push_back( inner );
    561694
    562                 //free_all( termination_handlers );
    563                 //free_all( resumption_handlers );
    564 
    565695                return block;
    566         }
    567 
    568         void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
    569                 GuardValue( cur_context );
    570                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    571                         cur_context = TerHandler;
    572                 } else {
    573                         cur_context = ResHandler;
    574                 }
    575         }
    576 
    577         void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
    578                 if ( !structDecl->has_body() ) {
    579                         // Skip children?
    580                         return;
    581                 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
    582                         assert( nullptr == node_decl );
    583                         node_decl = structDecl;
    584                 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
    585                         assert( nullptr == hook_decl );
    586                         hook_decl = structDecl;
    587                 }
    588                 // Later we might get the exception type as well.
    589696        }
    590697
Note: See TracChangeset for help on using the changeset viewer.