Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    r7f9968ad r3090127  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jun 24 11:18:00 2020
    13 // Update Count     : 17
     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 
    75         public:
    76                 ThrowMutatorCore() :
    77                         terminate_handler_except( nullptr ),
    78                         cur_context( NoHandler )
    79                 {}
    80 
    81                 void premutate( CatchStmt *catchStmt );
    82                 Statement * postmutate( ThrowStmt *throwStmt );
    83         };
    84 
    85         // ThrowStmt Mutation Helpers
    86 
    87         Statement * ThrowMutatorCore::create_either_throw(
    88                         ThrowStmt * throwStmt, const char * throwFunc ) {
    89                 // `throwFunc`( `throwStmt->get_name()` );
    90                 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
    91                 call->get_args().push_back( throwStmt->get_expr() );
    92                 throwStmt->set_expr( nullptr );
    93                 delete throwStmt;
    94                 return new ExprStmt( call );
    95         }
    96 
    97         Statement * ThrowMutatorCore::create_terminate_rethrow(
    98                         ThrowStmt *throwStmt ) {
    99                 // { `terminate_handler_except` = 0p; __rethrow_terminate(); }
    100                 assert( nullptr == throwStmt->get_expr() );
    101                 assert( terminate_handler_except );
    102 
    103                 CompoundStmt * result = new CompoundStmt();
    104                 result->labels =  throwStmt->labels;
    105                 result->push_back( new ExprStmt( UntypedExpr::createAssign(
    106                         nameOf( terminate_handler_except ),
    107                         new ConstantExpr( Constant::null(
    108                                 terminate_handler_except->get_type()->clone()
    109                                 ) )
    110                         ) ) );
    111                 result->push_back( new ExprStmt(
    112                         new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
    113                         ) );
    114                 delete throwStmt;
    115                 return result;
    116         }
    117 
    118         // Visiting/Mutating Functions
    119 
    120         void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) {
    121                 // Validate the statement's form.
    122                 ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
    123                 // Also checking the type would be nice.
    124                 if ( !decl || !dynamic_cast<PointerType *>( decl->type ) ) {
    125                         std::string kind = (CatchStmt::Terminate == catchStmt->kind) ? "catch" : "catchResume";
    126                         SemanticError( catchStmt->location, kind + " must have pointer to an exception type" );
    127                 }
    128 
    129                 // Track the handler context.
    130                 GuardValue( cur_context );
    131                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    132                         cur_context = TerHandler;
    133 
    134                         GuardValue( terminate_handler_except );
    135                         terminate_handler_except = decl;
    136                 } else {
    137                         cur_context = ResHandler;
    138                 }
    139         }
    140 
    141         Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) {
    142                 // Ignoring throwStmt->get_target() for now.
    143                 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
    144                         if ( throwStmt->get_expr() ) {
    145                                 return create_either_throw( throwStmt, "$throw" );
    146                         } else if ( TerHandler == cur_context ) {
    147                                 return create_terminate_rethrow( throwStmt );
    148                         } else {
    149                                 abort("Invalid throw in %s at %i\n",
    150                                         throwStmt->location.filename.c_str(),
    151                                         throwStmt->location.first_line);
    152                         }
    153                 } else {
    154                         if ( throwStmt->get_expr() ) {
    155                                 return create_either_throw( throwStmt, "$throwResume" );
    156                         } else if ( ResHandler == cur_context ) {
    157                                 // This has to be handled later.
    158                                 return throwStmt;
    159                         } else {
    160                                 abort("Invalid throwResume in %s at %i\n",
    161                                         throwStmt->location.filename.c_str(),
    162                                         throwStmt->location.first_line);
    163                         }
    164                 }
    165         }
    166 
    167         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
    16878                // The built in types used in translation.
    16979                StructDecl * except_decl;
     
    17282
    17383                // 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 );
    17490                CompoundStmt * take_try_block( TryStmt * tryStmt );
    17591                FunctionDecl * create_try_wrapper( CompoundStmt * body );
     
    185101                FunctionDecl * create_finally_wrapper( TryStmt * tryStmt );
    186102                ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper );
    187                 Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    188103
    189104                // Types used in translation, make sure to use clone.
     
    206121
    207122        public:
    208                 TryMutatorCore() :
     123                ExceptionMutatorCore() :
     124                        cur_context( NoHandler ),
     125                        handler_except_decl( nullptr ),
    209126                        except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
    210127                        try_func_t( noQualifiers, false ),
     
    215132                {}
    216133
     134                void premutate( CatchStmt *catchStmt );
    217135                void premutate( StructDecl *structDecl );
     136                Statement * postmutate( ThrowStmt *throwStmt );
    218137                Statement * postmutate( TryStmt *tryStmt );
    219                 Statement * postmutate( ThrowStmt *throwStmt );
    220138        };
    221139
    222         void TryMutatorCore::init_func_types() {
     140        void ExceptionMutatorCore::init_func_types() {
    223141                assert( except_decl );
    224142
     
    278196        }
    279197
     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
    280257        // TryStmt Mutation Helpers
    281258
    282         CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
     259        CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
    283260                CompoundStmt * block = tryStmt->get_block();
    284261                tryStmt->set_block( nullptr );
     
    286263        }
    287264
    288         FunctionDecl * TryMutatorCore::create_try_wrapper(
     265        FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
    289266                        CompoundStmt *body ) {
    290267
     
    293270        }
    294271
    295         FunctionDecl * TryMutatorCore::create_terminate_catch(
     272        FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
    296273                        CatchList &handlers ) {
    297274                std::list<CaseStmt *> handler_wrappers;
     
    373350        // Create a single check from a moddified handler.
    374351        // except_obj is referenced, modded_handler will be freed.
    375         CompoundStmt * TryMutatorCore::create_single_matcher(
     352        CompoundStmt * ExceptionMutatorCore::create_single_matcher(
    376353                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    377354                // {
     
    411388        }
    412389
    413         FunctionDecl * TryMutatorCore::create_terminate_match(
     390        FunctionDecl * ExceptionMutatorCore::create_terminate_match(
    414391                        CatchList &handlers ) {
    415392                // int match(exception * except) {
     
    448425        }
    449426
    450         CompoundStmt * TryMutatorCore::create_terminate_caller(
     427        CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
    451428                        FunctionDecl * try_wrapper,
    452429                        FunctionDecl * terminate_catch,
     
    466443        }
    467444
    468         FunctionDecl * TryMutatorCore::create_resume_handler(
     445        FunctionDecl * ExceptionMutatorCore::create_resume_handler(
    469446                        CatchList &handlers ) {
    470447                // bool handle(exception * except) {
     
    503480        }
    504481
    505         CompoundStmt * TryMutatorCore::create_resume_wrapper(
     482        CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
    506483                        Statement * wraps,
    507484                        FunctionDecl * resume_handler ) {
     
    547524        }
    548525
    549         FunctionDecl * TryMutatorCore::create_finally_wrapper(
     526        FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
    550527                        TryStmt * tryStmt ) {
    551                 // void finally() { `finally->block` }
     528                // void finally() { <finally code> }
    552529                FinallyStmt * finally = tryStmt->get_finally();
    553530                CompoundStmt * body = finally->get_block();
     
    560537        }
    561538
    562         ObjectDecl * TryMutatorCore::create_finally_hook(
     539        ObjectDecl * ExceptionMutatorCore::create_finally_hook(
    563540                        FunctionDecl * finally_wrapper ) {
    564541                // struct __cfaehm_cleanup_hook __finally_hook
    565                 //      __attribute__((cleanup( `finally_wrapper` )));
     542                //      __attribute__((cleanup( finally_wrapper )));
    566543
    567544                // Make Cleanup Attribute.
     
    587564        }
    588565
    589         Statement * TryMutatorCore::create_resume_rethrow( ThrowStmt *throwStmt ) {
    590                 // return false;
    591                 Statement * result = new ReturnStmt(
    592                         new ConstantExpr( Constant::from_bool( false ) )
    593                         );
    594                 result->labels = throwStmt->labels;
    595                 delete throwStmt;
    596                 return result;
    597         }
    598 
    599566        // Visiting/Mutating Functions
    600         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 ) {
    601592                if ( !structDecl->has_body() ) {
    602593                        // Skip children?
     
    613604                        hook_decl = structDecl;
    614605                }
    615         }
    616 
    617         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 ) {
    618637                assert( except_decl );
    619638                assert( node_decl );
     
    669688        }
    670689
    671         Statement * TryMutatorCore::postmutate( ThrowStmt *throwStmt ) {
    672                 // Only valid `throwResume;` statements should remain. (2/3 checks)
    673                 assert( ThrowStmt::Resume == throwStmt->kind && ! throwStmt->expr );
    674                 return create_resume_rethrow( throwStmt );
    675         }
    676 
    677         void translateThrows( std::list< Declaration *> & translationUnit ) {
    678                 PassVisitor<ThrowMutatorCore> translator;
     690        void translateEHM( std::list< Declaration *> & translationUnit ) {
     691                PassVisitor<ExceptionMutatorCore> translator;
    679692                mutateAll( translationUnit, translator );
    680693        }
    681 
    682         void translateTries( std::list< Declaration *> & translationUnit ) {
    683                 PassVisitor<TryMutatorCore> translator;
    684                 mutateAll( translationUnit, translator );
    685         }
    686694}
Note: See TracChangeset for help on using the changeset viewer.