Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    r66ba544 r3090127  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr May 21 13:18:00 2020
    13 // Update Count     : 15
     12// Last Modified On : Fri Mar 27 11:58:00 2020
     13// Update Count     : 13
    1414//
    1515
     
    6464        }
    6565
    66         class ThrowMutatorCore : public WithGuards {
    67                 ObjectDecl * terminate_handler_except;
    68                 enum Context { NoHandler, TerHandler, ResHandler } cur_context;
    69 
    70                 // The helper functions for code/syntree generation.
    71                 Statement * create_either_throw(
    72                         ThrowStmt * throwStmt, const char * throwFunc );
    73                 Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
    74                 Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    75 
    76         public:
    77                 ThrowMutatorCore() :
    78                         terminate_handler_except( nullptr ),
    79                         cur_context( NoHandler )
    80                 {}
    81 
    82                 void premutate( CatchStmt *catchStmt );
    83                 Statement * postmutate( ThrowStmt *throwStmt );
    84         };
    85 
    86         // ThrowStmt Mutation Helpers
    87 
    88         Statement * ThrowMutatorCore::create_either_throw(
    89                         ThrowStmt * throwStmt, const char * throwFunc ) {
    90                 // `throwFunc`( `throwStmt->get_name()` );
    91                 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
    92                 call->get_args().push_back( throwStmt->get_expr() );
    93                 throwStmt->set_expr( nullptr );
    94                 delete throwStmt;
    95                 return new ExprStmt( call );
    96         }
    97 
    98         Statement * ThrowMutatorCore::create_terminate_rethrow(
    99                         ThrowStmt *throwStmt ) {
    100                 // { `terminate_handler_except` = 0p; __rethrow_terminate(); }
    101                 assert( nullptr == throwStmt->get_expr() );
    102                 assert( terminate_handler_except );
    103 
    104                 CompoundStmt * result = new CompoundStmt();
    105                 result->labels =  throwStmt->labels;
    106                 result->push_back( new ExprStmt( UntypedExpr::createAssign(
    107                         nameOf( terminate_handler_except ),
    108                         new ConstantExpr( Constant::null(
    109                                 //new PointerType(
    110                                 //      noQualifiers,
    111                                         terminate_handler_except->get_type()->clone()
    112                                 //      )
    113                                 ) )
    114                         ) ) );
    115                 result->push_back( new ExprStmt(
    116                         new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
    117                         ) );
    118                 delete throwStmt;
    119                 return result;
    120         }
    121 
    122         Statement * ThrowMutatorCore::create_resume_rethrow(
    123                         ThrowStmt *throwStmt ) {
    124                 // return false;
    125                 Statement * result = new ReturnStmt(
    126                         new ConstantExpr( Constant::from_bool( false ) )
    127                         );
    128                 result->labels = throwStmt->labels;
    129                 delete throwStmt;
    130                 return result;
    131         }
    132 
    133         // Visiting/Mutating Functions
    134 
    135         void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) {
    136                 // Validate the statement's form.
    137                 ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
    138                 // Also checking the type would be nice.
    139                 if ( decl ) {
    140                         // Pass.
    141                 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    142                         SemanticError(catchStmt->location, "catch must have exception type");
    143                 } else {
    144                         SemanticError(catchStmt->location, "catchResume must have exception type");
    145                 }
    146 
    147                 // Track the handler context.
    148                 GuardValue( cur_context );
    149                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    150                         cur_context = TerHandler;
    151 
    152                         GuardValue( terminate_handler_except );
    153                         terminate_handler_except = decl;
    154                 } else {
    155                         cur_context = ResHandler;
    156                 }
    157         }
    158 
    159         Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) {
    160                 // Ignoring throwStmt->get_target() for now.
    161                 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
    162                         if ( throwStmt->get_expr() ) {
    163                                 return create_either_throw( throwStmt, "$throw" );
    164                         } else if ( TerHandler == cur_context ) {
    165                                 return create_terminate_rethrow( throwStmt );
    166                         } else {
    167                                 abort("Invalid throw in %s at %i\n",
    168                                         throwStmt->location.filename.c_str(),
    169                                         throwStmt->location.first_line);
    170                         }
    171                 } else {
    172                         if ( throwStmt->get_expr() ) {
    173                                 return create_either_throw( throwStmt, "$throwResume" );
    174                         } else if ( ResHandler == cur_context ) {
    175                                 return create_resume_rethrow( throwStmt );
    176                         } else {
    177                                 abort("Invalid throwResume in %s at %i\n",
    178                                         throwStmt->location.filename.c_str(),
    179                                         throwStmt->location.first_line);
    180                         }
    181                 }
    182         }
    183 
    184         class TryMutatorCore {
     66        class ExceptionMutatorCore : public WithGuards {
     67                enum Context { NoHandler, TerHandler, ResHandler };
     68
     69                // Also need to handle goto, break & continue.
     70                // They need to be cut off in a ResHandler, until we enter another
     71                // loop, switch or the goto stays within the function.
     72
     73                Context cur_context;
     74
     75                // The current (innermost) termination handler exception declaration.
     76                ObjectDecl * handler_except_decl;
     77
    18578                // The built in types used in translation.
    18679                StructDecl * except_decl;
     
    18982
    19083                // The many helper functions for code/syntree generation.
     84                Statement * create_given_throw(
     85                        const char * throwFunc, ThrowStmt * throwStmt );
     86                Statement * create_terminate_throw( ThrowStmt * throwStmt );
     87                Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
     88                Statement * create_resume_throw( ThrowStmt * throwStmt );
     89                Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    19190                CompoundStmt * take_try_block( TryStmt * tryStmt );
    19291                FunctionDecl * create_try_wrapper( CompoundStmt * body );
     
    222121
    223122        public:
    224                 TryMutatorCore() :
     123                ExceptionMutatorCore() :
     124                        cur_context( NoHandler ),
     125                        handler_except_decl( nullptr ),
    225126                        except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
    226127                        try_func_t( noQualifiers, false ),
     
    231132                {}
    232133
     134                void premutate( CatchStmt *catchStmt );
    233135                void premutate( StructDecl *structDecl );
    234136                Statement * postmutate( ThrowStmt *throwStmt );
     
    236138        };
    237139
    238         void TryMutatorCore::init_func_types() {
     140        void ExceptionMutatorCore::init_func_types() {
    239141                assert( except_decl );
    240142
     
    294196        }
    295197
     198        // ThrowStmt Mutation Helpers
     199
     200        Statement * ExceptionMutatorCore::create_given_throw(
     201                        const char * throwFunc, ThrowStmt * throwStmt ) {
     202                // `throwFunc`( `throwStmt->get_name` );
     203                UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
     204                call->get_args().push_back( throwStmt->get_expr() );
     205                throwStmt->set_expr( nullptr );
     206                delete throwStmt;
     207                return new ExprStmt( call );
     208        }
     209
     210        Statement * ExceptionMutatorCore::create_terminate_throw(
     211                        ThrowStmt *throwStmt ) {
     212                // __throw_terminate( `throwStmt->get_name()` ); }
     213                return create_given_throw( "__cfaehm_throw_terminate", throwStmt );
     214        }
     215
     216        Statement * ExceptionMutatorCore::create_terminate_rethrow(
     217                        ThrowStmt *throwStmt ) {
     218                // { `handler_except_decl` = NULL; __rethrow_terminate(); }
     219                assert( nullptr == throwStmt->get_expr() );
     220                assert( handler_except_decl );
     221
     222                CompoundStmt * result = new CompoundStmt();
     223                result->labels =  throwStmt->labels;
     224                result->push_back( new ExprStmt( UntypedExpr::createAssign(
     225                        nameOf( handler_except_decl ),
     226                        new ConstantExpr( Constant::null(
     227                                new PointerType(
     228                                        noQualifiers,
     229                                        handler_except_decl->get_type()->clone()
     230                                        )
     231                                ) )
     232                        ) ) );
     233                result->push_back( new ExprStmt(
     234                        new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
     235                        ) );
     236                delete throwStmt;
     237                return result;
     238        }
     239
     240        Statement * ExceptionMutatorCore::create_resume_throw(
     241                        ThrowStmt *throwStmt ) {
     242                // __throw_resume( `throwStmt->get_name` );
     243                return create_given_throw( "__cfaehm_throw_resume", throwStmt );
     244        }
     245
     246        Statement * ExceptionMutatorCore::create_resume_rethrow(
     247                        ThrowStmt *throwStmt ) {
     248                // return false;
     249                Statement * result = new ReturnStmt(
     250                        new ConstantExpr( Constant::from_bool( false ) )
     251                        );
     252                result->labels = throwStmt->labels;
     253                delete throwStmt;
     254                return result;
     255        }
     256
    296257        // TryStmt Mutation Helpers
    297258
    298         CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
     259        CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
    299260                CompoundStmt * block = tryStmt->get_block();
    300261                tryStmt->set_block( nullptr );
     
    302263        }
    303264
    304         FunctionDecl * TryMutatorCore::create_try_wrapper(
     265        FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
    305266                        CompoundStmt *body ) {
    306267
     
    309270        }
    310271
    311         FunctionDecl * TryMutatorCore::create_terminate_catch(
     272        FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
    312273                        CatchList &handlers ) {
    313274                std::list<CaseStmt *> handler_wrappers;
     
    389350        // Create a single check from a moddified handler.
    390351        // except_obj is referenced, modded_handler will be freed.
    391         CompoundStmt * TryMutatorCore::create_single_matcher(
     352        CompoundStmt * ExceptionMutatorCore::create_single_matcher(
    392353                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    393354                // {
     
    427388        }
    428389
    429         FunctionDecl * TryMutatorCore::create_terminate_match(
     390        FunctionDecl * ExceptionMutatorCore::create_terminate_match(
    430391                        CatchList &handlers ) {
    431392                // int match(exception * except) {
     
    464425        }
    465426
    466         CompoundStmt * TryMutatorCore::create_terminate_caller(
     427        CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
    467428                        FunctionDecl * try_wrapper,
    468429                        FunctionDecl * terminate_catch,
     
    482443        }
    483444
    484         FunctionDecl * TryMutatorCore::create_resume_handler(
     445        FunctionDecl * ExceptionMutatorCore::create_resume_handler(
    485446                        CatchList &handlers ) {
    486447                // bool handle(exception * except) {
     
    519480        }
    520481
    521         CompoundStmt * TryMutatorCore::create_resume_wrapper(
     482        CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
    522483                        Statement * wraps,
    523484                        FunctionDecl * resume_handler ) {
     
    563524        }
    564525
    565         FunctionDecl * TryMutatorCore::create_finally_wrapper(
     526        FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
    566527                        TryStmt * tryStmt ) {
    567                 // void finally() { `finally->block` }
     528                // void finally() { <finally code> }
    568529                FinallyStmt * finally = tryStmt->get_finally();
    569530                CompoundStmt * body = finally->get_block();
     
    576537        }
    577538
    578         ObjectDecl * TryMutatorCore::create_finally_hook(
     539        ObjectDecl * ExceptionMutatorCore::create_finally_hook(
    579540                        FunctionDecl * finally_wrapper ) {
    580541                // struct __cfaehm_cleanup_hook __finally_hook
    581                 //      __attribute__((cleanup( `finally_wrapper` )));
     542                //      __attribute__((cleanup( finally_wrapper )));
    582543
    583544                // Make Cleanup Attribute.
     
    604565
    605566        // Visiting/Mutating Functions
    606         void TryMutatorCore::premutate( StructDecl *structDecl ) {
     567        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
     568                // Validate the Statement's form.
     569                ObjectDecl * decl =
     570                        dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
     571                if ( decl && true /* check decl->get_type() */ ) {
     572                        // Pass.
     573                } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
     574                        SemanticError(catchStmt->location, "catch must have exception type");
     575                } else {
     576                        SemanticError(catchStmt->location, "catchResume must have exception type");
     577                }
     578
     579                // Track the handler context.
     580                GuardValue( cur_context );
     581                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
     582                        cur_context = TerHandler;
     583
     584                        GuardValue( handler_except_decl );
     585                        handler_except_decl = decl;
     586                } else {
     587                        cur_context = ResHandler;
     588                }
     589        }
     590
     591        void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
    607592                if ( !structDecl->has_body() ) {
    608593                        // Skip children?
     
    619604                        hook_decl = structDecl;
    620605                }
    621         }
    622 
    623         Statement * TryMutatorCore::postmutate( ThrowStmt * ) {
    624                 // All throws should be removed by this point.
    625                 assert( false );
    626         }
    627 
    628         Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) {
     606                // Later we might get the exception type as well.
     607        }
     608
     609        Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
     610                assert( except_decl );
     611
     612                // Ignoring throwStmt->get_target() for now.
     613                if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
     614                        if ( throwStmt->get_expr() ) {
     615                                return create_terminate_throw( throwStmt );
     616                        } else if ( TerHandler == cur_context ) {
     617                                return create_terminate_rethrow( throwStmt );
     618                        } else {
     619                                abort("Invalid throw in %s at %i\n",
     620                                        throwStmt->location.filename.c_str(),
     621                                        throwStmt->location.first_line);
     622                        }
     623                } else {
     624                        if ( throwStmt->get_expr() ) {
     625                                return create_resume_throw( throwStmt );
     626                        } else if ( ResHandler == cur_context ) {
     627                                return create_resume_rethrow( throwStmt );
     628                        } else {
     629                                abort("Invalid throwResume in %s at %i\n",
     630                                        throwStmt->location.filename.c_str(),
     631                                        throwStmt->location.first_line);
     632                        }
     633                }
     634        }
     635
     636        Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
    629637                assert( except_decl );
    630638                assert( node_decl );
     
    680688        }
    681689
    682         void translateThrows( std::list< Declaration *> & translationUnit ) {
    683                 PassVisitor<ThrowMutatorCore> translator;
     690        void translateEHM( std::list< Declaration *> & translationUnit ) {
     691                PassVisitor<ExceptionMutatorCore> translator;
    684692                mutateAll( translationUnit, translator );
    685693        }
    686 
    687         void translateTries( std::list< Declaration *> & translationUnit ) {
    688                 PassVisitor<TryMutatorCore> translator;
    689                 mutateAll( translationUnit, translator );
    690         }
    691694}
Note: See TracChangeset for help on using the changeset viewer.