Ignore:
Timestamp:
Aug 11, 2020, 4:40:15 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
0d070ca
Parents:
07d867b (diff), 129674b (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' into new-ast

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    r07d867b r22f94a4  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Mar 27 11:58:00 2020
    13 // Update Count     : 13
     12// Last Modified On : Wed Jun 24 11:18:00 2020
     13// Update Count     : 17
    1414//
    1515
     
    6464        }
    6565
    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 
     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 {
    78168                // The built in types used in translation.
    79169                StructDecl * except_decl;
     
    82172
    83173                // 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 );
    90174                CompoundStmt * take_try_block( TryStmt * tryStmt );
    91175                FunctionDecl * create_try_wrapper( CompoundStmt * body );
     
    101185                FunctionDecl * create_finally_wrapper( TryStmt * tryStmt );
    102186                ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper );
     187                Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    103188
    104189                // Types used in translation, make sure to use clone.
     
    121206
    122207        public:
    123                 ExceptionMutatorCore() :
    124                         cur_context( NoHandler ),
    125                         handler_except_decl( nullptr ),
     208                TryMutatorCore() :
    126209                        except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
    127210                        try_func_t( noQualifiers, false ),
     
    132215                {}
    133216
    134                 void premutate( CatchStmt *catchStmt );
    135217                void premutate( StructDecl *structDecl );
     218                Statement * postmutate( TryStmt *tryStmt );
    136219                Statement * postmutate( ThrowStmt *throwStmt );
    137                 Statement * postmutate( TryStmt *tryStmt );
    138220        };
    139221
    140         void ExceptionMutatorCore::init_func_types() {
     222        void TryMutatorCore::init_func_types() {
    141223                assert( except_decl );
    142224
     
    196278        }
    197279
    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 
    257280        // TryStmt Mutation Helpers
    258281
    259         CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
     282        CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
    260283                CompoundStmt * block = tryStmt->get_block();
    261284                tryStmt->set_block( nullptr );
     
    263286        }
    264287
    265         FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
     288        FunctionDecl * TryMutatorCore::create_try_wrapper(
    266289                        CompoundStmt *body ) {
    267290
     
    270293        }
    271294
    272         FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
     295        FunctionDecl * TryMutatorCore::create_terminate_catch(
    273296                        CatchList &handlers ) {
    274297                std::list<CaseStmt *> handler_wrappers;
     
    350373        // Create a single check from a moddified handler.
    351374        // except_obj is referenced, modded_handler will be freed.
    352         CompoundStmt * ExceptionMutatorCore::create_single_matcher(
     375        CompoundStmt * TryMutatorCore::create_single_matcher(
    353376                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    354377                // {
     
    388411        }
    389412
    390         FunctionDecl * ExceptionMutatorCore::create_terminate_match(
     413        FunctionDecl * TryMutatorCore::create_terminate_match(
    391414                        CatchList &handlers ) {
    392415                // int match(exception * except) {
     
    425448        }
    426449
    427         CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
     450        CompoundStmt * TryMutatorCore::create_terminate_caller(
    428451                        FunctionDecl * try_wrapper,
    429452                        FunctionDecl * terminate_catch,
     
    443466        }
    444467
    445         FunctionDecl * ExceptionMutatorCore::create_resume_handler(
     468        FunctionDecl * TryMutatorCore::create_resume_handler(
    446469                        CatchList &handlers ) {
    447470                // bool handle(exception * except) {
     
    480503        }
    481504
    482         CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
     505        CompoundStmt * TryMutatorCore::create_resume_wrapper(
    483506                        Statement * wraps,
    484507                        FunctionDecl * resume_handler ) {
     
    524547        }
    525548
    526         FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
     549        FunctionDecl * TryMutatorCore::create_finally_wrapper(
    527550                        TryStmt * tryStmt ) {
    528                 // void finally() { <finally code> }
     551                // void finally() { `finally->block` }
    529552                FinallyStmt * finally = tryStmt->get_finally();
    530553                CompoundStmt * body = finally->get_block();
     
    537560        }
    538561
    539         ObjectDecl * ExceptionMutatorCore::create_finally_hook(
     562        ObjectDecl * TryMutatorCore::create_finally_hook(
    540563                        FunctionDecl * finally_wrapper ) {
    541564                // struct __cfaehm_cleanup_hook __finally_hook
    542                 //      __attribute__((cleanup( finally_wrapper )));
     565                //      __attribute__((cleanup( `finally_wrapper` )));
    543566
    544567                // Make Cleanup Attribute.
     
    564587        }
    565588
     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
    566599        // Visiting/Mutating Functions
    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 ) {
     600        void TryMutatorCore::premutate( StructDecl *structDecl ) {
    592601                if ( !structDecl->has_body() ) {
    593602                        // Skip children?
     
    604613                        hook_decl = structDecl;
    605614                }
    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 ) {
     615        }
     616
     617        Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) {
    637618                assert( except_decl );
    638619                assert( node_decl );
     
    688669        }
    689670
    690         void translateEHM( std::list< Declaration *> & translationUnit ) {
    691                 PassVisitor<ExceptionMutatorCore> translator;
     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;
    692679                mutateAll( translationUnit, translator );
    693680        }
     681
     682        void translateTries( std::list< Declaration *> & translationUnit ) {
     683                PassVisitor<TryMutatorCore> translator;
     684                mutateAll( translationUnit, translator );
     685        }
    694686}
Note: See TracChangeset for help on using the changeset viewer.