Changeset 046a890 for src/ControlStruct


Ignore:
Timestamp:
May 19, 2020, 5:31:20 PM (5 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
918b90c
Parents:
7d6e01d
Message:

That should get default operations working for throws. More tests to come.

Location:
src/ControlStruct
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    r7d6e01d r046a890  
    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 : Tue May 19 16:46:00 2020
     13// Update Count     : 14
    1414//
    1515
     
    6464        }
    6565
    66         class ExceptionMutatorCore : public WithGuards {
     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 : public WithGuards {
    67185                enum Context { NoHandler, TerHandler, ResHandler };
    68186
     
    82200
    83201                // 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 );
    90202                CompoundStmt * take_try_block( TryStmt * tryStmt );
    91203                FunctionDecl * create_try_wrapper( CompoundStmt * body );
     
    121233
    122234        public:
    123                 ExceptionMutatorCore() :
     235                TryMutatorCore() :
    124236                        cur_context( NoHandler ),
    125237                        handler_except_decl( nullptr ),
     
    138250        };
    139251
    140         void ExceptionMutatorCore::init_func_types() {
     252        void TryMutatorCore::init_func_types() {
    141253                assert( except_decl );
    142254
     
    196308        }
    197309
    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 
    257310        // TryStmt Mutation Helpers
    258311
    259         CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
     312        CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
    260313                CompoundStmt * block = tryStmt->get_block();
    261314                tryStmt->set_block( nullptr );
     
    263316        }
    264317
    265         FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
     318        FunctionDecl * TryMutatorCore::create_try_wrapper(
    266319                        CompoundStmt *body ) {
    267320
     
    270323        }
    271324
    272         FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
     325        FunctionDecl * TryMutatorCore::create_terminate_catch(
    273326                        CatchList &handlers ) {
    274327                std::list<CaseStmt *> handler_wrappers;
     
    350403        // Create a single check from a moddified handler.
    351404        // except_obj is referenced, modded_handler will be freed.
    352         CompoundStmt * ExceptionMutatorCore::create_single_matcher(
     405        CompoundStmt * TryMutatorCore::create_single_matcher(
    353406                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    354407                // {
     
    388441        }
    389442
    390         FunctionDecl * ExceptionMutatorCore::create_terminate_match(
     443        FunctionDecl * TryMutatorCore::create_terminate_match(
    391444                        CatchList &handlers ) {
    392445                // int match(exception * except) {
     
    425478        }
    426479
    427         CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
     480        CompoundStmt * TryMutatorCore::create_terminate_caller(
    428481                        FunctionDecl * try_wrapper,
    429482                        FunctionDecl * terminate_catch,
     
    443496        }
    444497
    445         FunctionDecl * ExceptionMutatorCore::create_resume_handler(
     498        FunctionDecl * TryMutatorCore::create_resume_handler(
    446499                        CatchList &handlers ) {
    447500                // bool handle(exception * except) {
     
    480533        }
    481534
    482         CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
     535        CompoundStmt * TryMutatorCore::create_resume_wrapper(
    483536                        Statement * wraps,
    484537                        FunctionDecl * resume_handler ) {
     
    524577        }
    525578
    526         FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
     579        FunctionDecl * TryMutatorCore::create_finally_wrapper(
    527580                        TryStmt * tryStmt ) {
    528581                // void finally() { <finally code> }
     
    537590        }
    538591
    539         ObjectDecl * ExceptionMutatorCore::create_finally_hook(
     592        ObjectDecl * TryMutatorCore::create_finally_hook(
    540593                        FunctionDecl * finally_wrapper ) {
    541594                // struct __cfaehm_cleanup_hook __finally_hook
    542                 //      __attribute__((cleanup( finally_wrapper )));
     595                //      __attribute__((cleanup( `finally_wrapper` )));
    543596
    544597                // Make Cleanup Attribute.
     
    565618
    566619        // Visiting/Mutating Functions
    567         void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
     620        void TryMutatorCore::premutate( CatchStmt *catchStmt ) {
    568621                // Validate the Statement's form.
    569                 ObjectDecl * decl =
    570                         dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
     622                ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
    571623                if ( decl && true /* check decl->get_type() */ ) {
    572624                        // Pass.
     
    589641        }
    590642
    591         void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
     643        void TryMutatorCore::premutate( StructDecl *structDecl ) {
    592644                if ( !structDecl->has_body() ) {
    593645                        // Skip children?
     
    604656                        hook_decl = structDecl;
    605657                }
    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 ) {
     658        }
     659
     660        Statement * TryMutatorCore::postmutate( ThrowStmt * ) {
     661                // All throws should be removed by this point.
     662                assert( false );
     663        }
     664
     665        Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) {
    637666                assert( except_decl );
    638667                assert( node_decl );
     
    688717        }
    689718
    690         void translateEHM( std::list< Declaration *> & translationUnit ) {
    691                 PassVisitor<ExceptionMutatorCore> translator;
     719        void translateThrows( std::list< Declaration *> & translationUnit ) {
     720                PassVisitor<ThrowMutatorCore> translator;
    692721                mutateAll( translationUnit, translator );
    693722        }
     723
     724        void translateTries( std::list< Declaration *> & translationUnit ) {
     725                PassVisitor<TryMutatorCore> translator;
     726                mutateAll( translationUnit, translator );
     727        }
    694728}
  • src/ControlStruct/ExceptTranslate.h

    r7d6e01d r046a890  
    99// Author           : Andrew Beach
    1010// Created On       : Tus Jun 06 10:13:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:19:23 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tus May 19 11:47:00 2020
     13// Update Count     : 5
    1414//
    1515
     
    2121
    2222namespace ControlStruct {
    23         void translateEHM( std::list< Declaration *> & translationUnit );
    24         // Converts exception handling structures into their underlying C code.  Translation does use the exception
    25         // handling header, make sure it is visible wherever translation occurs.
     23        void translateThrows( std::list< Declaration *> & translationUnit );
     24        /* Replaces all throw & throwResume statements with function calls.
     25         * These still need to be resolved, so call this before the reslover.
     26         */
     27
     28        void translateTries( std::list< Declaration *> & translationUnit );
     29        /* Replaces all try blocks (and their many clauses) with function definitions and calls.
     30         * This uses the exception built-ins to produce typed output and should take place after
     31         * the resolver.
     32         */
    2633}
    2734
Note: See TracChangeset for help on using the changeset viewer.