Changeset 9fba8e6 for src


Ignore:
Timestamp:
Dec 19, 2023, 9:54:57 AM (9 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
0a6d2045
Parents:
b7898ac
Message:

Clean-up in the exception translate pass. This changes some patterns from pre-translation and sets some things up for later reworks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cpp

    rb7898ac r9fba8e6  
    145145        ast::CompoundStmt * take_try_block( ast::TryStmt * tryStmt );
    146146        ast::FunctionDecl * create_try_wrapper( const ast::CompoundStmt * body );
     147        ast::CaseClause * create_terminate_catch_case(
     148                const ast::DeclWithType * except_obj, int index, ast::CatchClause * clause );
    147149        ast::FunctionDecl * create_terminate_catch( CatchList &handlers );
    148150        ast::CompoundStmt * create_single_matcher(
     
    164166        ast::ObjectDecl * make_voidptr_object( CodeLocation const & ) const;
    165167        ast::ObjectDecl * make_unused_index_object( CodeLocation const & ) const;
    166         // void (*function)();
    167         ast::FunctionDecl * make_try_function( CodeLocation const & ) const;
    168         // void (*function)(int, exception);
    169         ast::FunctionDecl * make_catch_function( CodeLocation const & ) const;
    170         // int (*function)(exception);
    171         ast::FunctionDecl * make_match_function( CodeLocation const & ) const;
    172         // bool (*function)(exception);
    173         ast::FunctionDecl * make_handle_function( CodeLocation const & ) const;
    174         // void (*function)(__attribute__((unused)) void *);
    175         ast::FunctionDecl * make_finally_function( CodeLocation const & ) const;
    176168
    177169public:
     
    248240}
    249241
    250 ast::FunctionDecl * TryMutatorCore::make_try_function(
    251                 CodeLocation const & location ) const {
     242// TryStmt Mutation Helpers
     243
     244ast::FunctionDecl * TryMutatorCore::create_try_wrapper(
     245                const ast::CompoundStmt *body ) {
     246        // void (*try)(void) `body`
    252247        return new ast::FunctionDecl(
    253                 location,
     248                body->location,
    254249                "try",
    255250                {}, //no param
    256251                {}, //no return
    257                 nullptr,
     252                ast::mutate( body ),
    258253                ast::Storage::Classes{},
    259254                ast::Linkage::Cforall
     
    261256}
    262257
    263 ast::FunctionDecl * TryMutatorCore::make_catch_function(
    264                 CodeLocation const & location ) const {
    265         return new ast::FunctionDecl(
    266                 location,
    267                 "catch",
    268                 { make_index_object( location ), make_exception_object( location ) },
    269                 {}, //return void
    270                 nullptr,
    271                 ast::Storage::Classes{},
    272                 ast::Linkage::Cforall
    273         );
    274 }
    275 
    276 ast::FunctionDecl * TryMutatorCore::make_match_function(
    277                 CodeLocation const & location ) const {
    278         return new ast::FunctionDecl(
    279                 location,
    280                 "match",
    281                 { make_exception_object( location ) },
    282                 { make_unused_index_object( location ) },
    283                 nullptr,
    284                 ast::Storage::Classes{},
    285                 ast::Linkage::Cforall
    286         );
    287 }
    288 
    289 ast::FunctionDecl * TryMutatorCore::make_handle_function(
    290                 CodeLocation const & location ) const {
    291         return new ast::FunctionDecl(
    292                 location,
    293                 "handle",
    294                 { make_exception_object( location ) },
    295                 { make_bool_object( location ) },
    296                 nullptr,
    297                 ast::Storage::Classes{},
    298                 ast::Linkage::Cforall
    299         );
    300 }
    301 
    302 ast::FunctionDecl * TryMutatorCore::make_finally_function(
    303                 CodeLocation const & location ) const {
    304         return new ast::FunctionDecl(
    305                 location,
    306                 "finally",
    307                 { make_voidptr_object( location ) },
    308                 {}, //return void
    309                 nullptr,
    310                 ast::Storage::Classes{},
    311                 ast::Linkage::Cforall,
    312                 {},
    313                 { ast::Function::Inline }
    314         );
    315 }
    316 
    317 // TryStmt Mutation Helpers
    318 
    319 ast::FunctionDecl * TryMutatorCore::create_try_wrapper(
    320                 const ast::CompoundStmt *body ) {
    321 
    322         ast::FunctionDecl * ret = make_try_function( body->location );
    323         ret->stmts = body;
    324         return ret;
     258ast::CaseClause * TryMutatorCore::create_terminate_catch_case(
     259                const ast::DeclWithType * except_obj, int index, ast::CatchClause * clause ) {
     260        // case `index`:
     261        // {
     262        //     __attribute__((cleanup(__cfaehm_cleanup_terminate)))
     263        //     `handler.decl` = { (virtual `decl.type`)`except` };
     264        //     `handler.body`;
     265        // }
     266        // return;
     267        const CodeLocation & location = clause->location;
     268
     269        auto clause_except = clause->decl.strict_as<ast::ObjectDecl>();
     270        auto local_except = ast::deepCopy( clause_except );
     271        local_except->attributes.push_back( new ast::Attribute(
     272                "cleanup",
     273                { new ast::NameExpr( location, "__cfaehm_cleanup_terminate" ) }
     274        ) );
     275
     276        local_except->init = new ast::ListInit( location, {
     277                new ast::SingleInit( location,
     278                        new ast::VirtualCastExpr( location,
     279                                new ast::VariableExpr( location, except_obj ),
     280                                ast::deepCopy( local_except->get_type() )
     281                        )
     282                )
     283        } );
     284
     285        ast::DeclReplacer::DeclMap mapping;
     286        mapping[clause_except] = local_except;
     287        const ast::Stmt * body = strict_dynamic_cast<const ast::Stmt *>(
     288                ast::DeclReplacer::replace(clause->body, mapping));
     289
     290        return new ast::CaseClause( location,
     291                ast::ConstantExpr::from_int( location, index ),
     292                {
     293                        new ast::CompoundStmt( location, {
     294                                new ast::DeclStmt( location, local_except ),
     295                                body,
     296                        } ),
     297                        new ast::ReturnStmt( location, nullptr ),
     298                }
     299        );
    325300}
    326301
    327302ast::FunctionDecl * TryMutatorCore::create_terminate_catch(
    328303                CatchList &handlers ) {
     304        // void catch(int index, exception * except) {
     305        //     switch (index) { CATCH_CASE... }
     306        // }
     307
     308        assert( !handlers.empty() );
    329309        std::vector<ast::ptr<ast::CaseClause>> handler_wrappers;
    330 
    331         assert (!handlers.empty());
    332         const CodeLocation loc = handlers.front()->location;
    333 
    334         ast::FunctionDecl * func_t = make_catch_function( loc );
    335         const ast::DeclWithType * index_obj = func_t->params.front();
    336         const ast::DeclWithType * except_obj = func_t->params.back();
     310        const CodeLocation & location = handlers.front()->location;
     311
     312        const ast::DeclWithType * index_obj = make_index_object( location );
     313        const ast::DeclWithType * except_obj = make_exception_object( location );
    337314
    338315        // Index 1..{number of handlers}
    339         int index = 0;
    340         CatchList::iterator it = handlers.begin();
    341         for ( ; it != handlers.end() ; ++it ) {
    342                 ++index;
    343                 ast::CatchClause * handler = *it;
    344                 const CodeLocation loc = handler->location;
    345 
    346                 // case `index`:
    347                 // {
    348                 //     `handler.decl` = { (virtual `decl.type`)`except` };
    349                 //     `handler.body`;
    350                 // }
    351                 // return;
    352                 ast::CompoundStmt * block = new ast::CompoundStmt(loc);
    353 
    354                 // Just copy the exception value. (Post Validation)
    355                 const ast::ObjectDecl * handler_decl =
    356                         handler->decl.strict_as<ast::ObjectDecl>();
    357                 ast::ObjectDecl * local_except = ast::deepCopy(handler_decl);
    358                 ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
    359                         new ast::VariableExpr( loc, except_obj ),
    360                         local_except->get_type()
    361                         );
    362                 vcex->location = handler->location;
    363                 local_except->init = new ast::ListInit(loc, { new ast::SingleInit( loc, vcex ) });
    364                 block->push_back( new ast::DeclStmt( loc, local_except ) );
    365 
    366                 // Add the cleanup attribute.
    367                 local_except->attributes.push_back( new ast::Attribute(
    368                         "cleanup",
    369                         { new ast::NameExpr( loc, "__cfaehm_cleanup_terminate" ) }
    370                         ) );
    371 
    372                 ast::DeclReplacer::DeclMap mapping;
    373                 mapping[handler_decl] = local_except;
    374                 const ast::Stmt * mutBody = strict_dynamic_cast<const ast::Stmt *>(
    375                         ast::DeclReplacer::replace(handler->body, mapping));
    376 
    377 
    378                 block->push_back( mutBody );
    379                 // handler->body = nullptr;
    380 
    381                 handler_wrappers.push_back( new ast::CaseClause(loc,
    382                         ast::ConstantExpr::from_int(loc, index) ,
    383                         { block, new ast::ReturnStmt( loc, nullptr ) }
    384                         ));
     316        for ( const auto & [index, handler] : enumerate( handlers ) ) {
     317                handler_wrappers.push_back(
     318                        create_terminate_catch_case( except_obj, index + 1, handler ) );
    385319        }
    386320        // TODO: Some sort of meaningful error on default perhaps?
    387321
    388         ast::SwitchStmt * handler_lookup = new ast::SwitchStmt( loc,
    389                 new ast::VariableExpr( loc, index_obj ),
     322        ast::SwitchStmt * handler_lookup = new ast::SwitchStmt( location,
     323                new ast::VariableExpr( location, index_obj ),
    390324                std::move(handler_wrappers)
    391325                );
    392         ast::CompoundStmt * body = new ast::CompoundStmt( loc, {handler_lookup} );
    393 
    394         func_t->stmts = body;
    395         return func_t;
     326        ast::CompoundStmt * body = new ast::CompoundStmt( location, {handler_lookup} );
     327
     328        // void (*catch)(int, exception_t *) `body`
     329        return new ast::FunctionDecl(
     330                location,
     331                "catch",
     332                { index_obj, except_obj },
     333                {}, //return void
     334                body,
     335                ast::Storage::Classes{},
     336                ast::Linkage::Cforall
     337        );
    396338}
    397339
     
    441383        // }
    442384
    443         assert (!handlers.empty());
    444         const CodeLocation loc = handlers.front()->location;
    445 
    446         ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    447 
    448         ast::FunctionDecl * func_t = make_match_function( loc );
    449         const ast::DeclWithType * except_obj = func_t->params.back();
     385        assert( !handlers.empty() );
     386        const CodeLocation & location = handlers.front()->location;
     387
     388        ast::CompoundStmt * body = new ast::CompoundStmt( location );
     389        const ast::DeclWithType * except_obj = make_exception_object( location );
    450390
    451391        // Index 1..{number of handlers}
     
    469409        }
    470410
    471         body->push_back( new ast::ReturnStmt(loc,
    472                 ast::ConstantExpr::from_int( loc, 0 ) ));
    473 
    474         func_t->stmts = body;
    475 
    476         return func_t;
     411        body->push_back( new ast::ReturnStmt( location,
     412                ast::ConstantExpr::from_int( location, 0 ) ));
     413
     414        // void (*match)(exception_t *) `body`
     415        return new ast::FunctionDecl(
     416                location,
     417                "match",
     418                { except_obj },
     419                { make_unused_index_object( location ) },
     420                body,
     421                ast::Storage::Classes{},
     422                ast::Linkage::Cforall
     423        );
    477424}
    478425
     
    489436        // }
    490437
    491         ast::ObjectDecl * index = new ast::ObjectDecl( loc, "__handler_index",
    492                 new ast::BasicType( ast::BasicType::SignedInt ),
    493                 new ast::SingleInit( loc,
    494                         new ast::UntypedExpr( loc,
    495                                 new ast::NameExpr( loc, "__cfaehm_try_terminate" ),
    496                                 {
    497                                         new ast::VariableExpr( loc, try_wrapper ),
    498                                         new ast::VariableExpr( loc, terminate_match ),
    499                                 }
    500                         )
     438        ast::ObjectDecl * index = make_index_object( loc );
     439        index->init = new ast::SingleInit( loc,
     440                new ast::UntypedExpr( loc,
     441                        new ast::NameExpr( loc, "__cfaehm_try_terminate" ),
     442                        {
     443                                new ast::VariableExpr( loc, try_wrapper ),
     444                                new ast::VariableExpr( loc, terminate_match ),
     445                        }
    501446                )
    502447        );
     
    526471        //     HANDLER WRAPPERS { `hander->body`; return true; }
    527472        // }
    528         assert (!handlers.empty());
    529         const CodeLocation loc = handlers.front()->location;
    530         ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    531 
    532         ast::FunctionDecl * func_t = make_handle_function( loc );
    533         const ast::DeclWithType * except_obj = func_t->params.back();
     473
     474        assert( !handlers.empty() );
     475        const CodeLocation & location = handlers.front()->location;
     476
     477        ast::CompoundStmt * body = new ast::CompoundStmt( location );
     478        const ast::DeclWithType * except_obj = make_exception_object( location );
    534479
    535480        CatchList::iterator it;
     
    555500        }
    556501
    557         body->push_back( new ast::ReturnStmt(loc,
    558                 ast::ConstantExpr::from_bool(loc, false ) ) );
    559         func_t->stmts = body;
    560 
    561         return func_t;
     502        body->push_back( new ast::ReturnStmt( location,
     503                ast::ConstantExpr::from_bool( location, false ) ) );
     504
     505        // bool (*handle)(exception_t *) `body`
     506        return new ast::FunctionDecl(
     507                location,
     508                "handle",
     509                { except_obj },
     510                { make_bool_object( location ) },
     511                body,
     512                ast::Storage::Classes{},
     513                ast::Linkage::Cforall
     514        );
    562515}
    563516
     
    601554ast::FunctionDecl * TryMutatorCore::create_finally_wrapper(
    602555                ast::TryStmt * tryStmt ) {
    603         // void finally() { `finally->block` }
     556        // void finally(__attribute__((unused)) void *) `finally->body`
    604557        const ast::FinallyClause * finally = tryStmt->finally;
    605         const ast::CompoundStmt * body = finally->body;
    606 
    607         ast::FunctionDecl * func_t = make_finally_function( tryStmt->location );
    608         func_t->stmts = body;
    609 
    610         tryStmt->finally = nullptr;
    611 
    612         return func_t;
     558        return new ast::FunctionDecl(
     559                tryStmt->location,
     560                "finally",
     561                { make_voidptr_object( tryStmt->location ) },
     562                {}, //return void
     563                ast::mutate( finally->body.get() ),
     564                ast::Storage::Classes{},
     565                ast::Linkage::Cforall,
     566                {},
     567                { ast::Function::Inline }
     568        );
    613569}
    614570
     
    618574        //      __attribute__((cleanup( `finally_wrapper` )));
    619575
    620         const CodeLocation loc = finally_wrapper->location;
     576        const CodeLocation & location = finally_wrapper->location;
    621577        return new ast::ObjectDecl(
    622                 loc,
     578                location,
    623579                "__finally_hook",
    624580                new ast::StructInstType(
     
    629585                ast::Linkage::Cforall,
    630586                nullptr,
    631                 {new ast::Attribute("cleanup", {new ast::VariableExpr{loc, finally_wrapper}})}
     587                {new ast::Attribute("cleanup", {new ast::VariableExpr(location, finally_wrapper)})}
    632588                );
    633589}
Note: See TracChangeset for help on using the changeset viewer.