Changes in / [79dbb79:59310bf]


Ignore:
Location:
src
Files:
1 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    r79dbb79 r59310bf  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 28 14:03:00 2017
    13 // Update Count     : 5
     12// Last Modified On : Tus Jul 18 10:09:00 2017
     13// Update Count     : 4
    1414//
    1515
     
    2121#include "SynTree/Type.h"
    2222#include "SynTree/Attribute.h"
    23 #include "SynTree/VarExprReplacer.h"
    2423
    2524namespace ControlStruct {
    2625
     26        // This (large) section could probably be moved out of the class
     27        // and be static helpers instead.
     28
     29        // Type(Qualifiers &, false, std::list<Attribute *> &)
     30
    2731        // void (*function)();
    28         static FunctionType try_func_t(noQualifiers, false);
     32        static FunctionType try_func_t(Type::Qualifiers(), false);
    2933        // void (*function)(int, exception);
    30         static FunctionType catch_func_t(noQualifiers, false);
     34        static FunctionType catch_func_t(Type::Qualifiers(), false);
    3135        // int (*function)(exception);
    32         static FunctionType match_func_t(noQualifiers, false);
     36        static FunctionType match_func_t(Type::Qualifiers(), false);
    3337        // bool (*function)(exception);
    34         static FunctionType handle_func_t(noQualifiers, false);
     38        static FunctionType handle_func_t(Type::Qualifiers(), false);
    3539        // void (*function)(__attribute__((unused)) void *);
    36         static FunctionType finally_func_t(noQualifiers, false);
     40        static FunctionType finally_func_t(Type::Qualifiers(), false);
    3741
    3842        static void init_func_types() {
     
    111115        }
    112116
     117        template<typename T>
     118        void free_all( std::list<T *> &list ) {
     119                typename std::list<T *>::iterator it;
     120                for ( it = list.begin() ; it != list.end() ; ++it ) {
     121                        delete *it;
     122                }
     123                list.clear();
     124        }
     125
    113126        void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
    114127                block->push_back(new DeclStmt(noLabels, item));
     
    123136        Statement * create_given_throw(
    124137                        const char * throwFunc, ThrowStmt * throwStmt ) {
    125                 // There is an extra copy here we might be able to remove with
    126                 // references.
    127138                // { int NAME = EXPR; throwFunc( &NAME ); }
    128139                CompoundStmt * result = new CompoundStmt( noLabels );
     
    148159                return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
    149160        }
    150 
    151         Statement * create_terminate_rethrow( ThrowStmt *throwStmt,
    152                         ObjectDecl *handler_except_decl ) {
    153                 // { `handler_except_decl` = NULL; __rethrow_terminate(); }
     161        Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) {
     162                // __rethrow_terminate();
    154163                assert( nullptr == throwStmt->get_expr() );
    155                 assert( handler_except_decl );
    156 
    157                 CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
    158                 result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
    159                         nameOf( handler_except_decl ),
    160                         new ConstantExpr( Constant::null(
    161                                 new PointerType(
    162                                         noQualifiers,
    163                                         handler_except_decl->get_type()->clone()
    164                                         )
    165                                 ) )
    166                         ) ) );
    167                 result->push_back( new ExprStmt(
    168                         noLabels,
     164                Statement * result = new ExprStmt(
     165                        throwStmt->get_labels(),
    169166                        new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
    170                         ) );
     167                        );
    171168                delete throwStmt;
    172169                return result;
    173170        }
    174 
    175171        Statement * create_resume_throw( ThrowStmt *throwStmt ) {
    176172                // __throw_resume( EXPR );
    177173                return create_given_throw( "__cfaehm__throw_resume", throwStmt );
    178174        }
    179 
    180175        Statement * create_resume_rethrow( ThrowStmt *throwStmt ) {
    181176                // return false;
     
    206201                FunctionType *func_type = catch_func_t.clone();
    207202                DeclarationWithType * index_obj = func_type->get_parameters().front();
    208                 DeclarationWithType * except_obj = func_type->get_parameters().back();
     203        //      DeclarationWithType * except_obj = func_type->get_parameters().back();
    209204
    210205                // Index 1..{number of handlers}
     
    218213                        // case `index`:
    219214                        // {
    220                         //     `handler.decl` {inserted} = { except_obj };
    221215                        //     `handler.body`
    222216                        // }
    223217                        // return;
    224                         CompoundStmt * block = new CompoundStmt( noLabels );
    225 
    226                         // Just copy the exception value.
    227                         // TODO: Or just store an ObjectDecl?
    228                         ObjectDecl * handler_decl =
    229                                 dynamic_cast<ObjectDecl*>( handler->get_decl() );
    230                         assert( handler_decl );
    231                         ObjectDecl * local_except = handler_decl->clone();
    232                         local_except->set_init(
    233                                 new ListInit({ new SingleInit( nameOf( except_obj ) ) }) );
    234 #if 0
    235                         // Virtual Exception Vision
    236                         // case `index`:
    237                         // {
    238                         //     `handler.decl` = { (virtual `decl.type`)`except` };
    239                         //     `handler.body`;
    240                         // }
    241                         // return;
    242 
    243                         // Save a cast copy of the exception (should always succeed).
    244                         ObjectDecl * local_except = handler->get_decl()->clone();
    245                         local_except.set_init(
    246                                 new ListInit({ new SingleInit(
    247                                         new VirtualCastExpr( nameOf( except_obj ),
    248                                                 local_except->get_type()
    249                                                 )
    250                                         ) }) );
    251 #endif
    252                         block->push_back( new DeclStmt( noLabels, local_except ) );
    253 
    254                         // Add the cleanup attribute.
    255                         local_except->get_attributes().push_back( new Attribute(
    256                                 "cleanup",
    257                                 { new NameExpr( "__cfaehm__cleanup_terminate" ) }
    258                                 ) );
    259 
    260                         // Update variables in the body to point to this local copy.
    261                         {
    262                                 VarExprReplacer::DeclMap mapping;
    263                                 mapping[ handler_decl ] = local_except;
    264                                 VarExprReplacer mapper( mapping );
    265                                 handler->get_body()->accept( mapper );
    266                         }
    267 
    268                         block->push_back( handler->get_body() );
     218                        std::list<Statement *> caseBody;
     219                        caseBody.push_back( handler->get_body() );
    269220                        handler->set_body( nullptr );
    270 
    271                         std::list<Statement *> caseBody
    272                                         { block, new ReturnStmt( noLabels, nullptr ) };
     221                        caseBody.push_back( new ReturnStmt( noLabels, nullptr ) );
     222
    273223                        handler_wrappers.push_back( new CaseStmt(
    274224                                noLabels,
     
    303253                CompoundStmt * block = new CompoundStmt( noLabels );
    304254
    305                 ObjectDecl * local_except =
    306                         dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
    307                 assert( local_except );
    308                 block->push_back( new DeclStmt( noLabels, local_except ) );
    309 #if 0
    310                 // Virtual Exception Version
    311                 // {
    312                 //     `modded_handler.decl`
    313                 //     if ( `decl.name = (virtual)`except`
    314                 //             [&& `modded_handler.cond`] ) {
    315                 //         `modded_handler.body`
    316                 //     }
    317                 // }
    318 
    319                 // Check for type match.
    320                 Expression * cond = UntypedExpr::createAssign( nameOf( local_except ),
    321                         new VirtualCastExpr( nameOf( except_obj ),
    322                                 local_except->get_type()->clone() ) );
    323 #endif
    324 
    325255                // INTEGERconstant Version
    326                 // {
    327                 //     `modded_handler.decl` = *`except`
    328                 //     if ( `decl.name` == `modded_handler.cond` ) {
    329                 //         `modded_handler.body`
    330                 //     }
    331                 // }
     256                assert( nullptr == modded_handler->get_decl() );
    332257                ConstantExpr * number =
    333258                        dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
     
    349274                }
    350275
    351                 // Add the check on the conditional if it is provided.
    352276                if ( modded_handler->get_cond() ) {
    353277                        cond = new LogicalExpr( cond, modded_handler->get_cond() );
    354278                }
    355                 // Construct the match condition.
    356279                block->push_back( new IfStmt( noLabels,
    357280                        cond, modded_handler->get_body(), nullptr ) );
     
    365288
    366289        FunctionDecl * create_terminate_match( CatchList &handlers ) {
    367                 // int match(exception * except) {
    368                 //     HANDLER WRAPPERS { return `index`; }
    369                 // }
    370 
    371290                CompoundStmt * body = new CompoundStmt( noLabels );
    372291
     
    404323                        FunctionDecl * terminate_catch,
    405324                        FunctionDecl * terminate_match) {
    406                 // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
    407325
    408326                UntypedExpr * caller = new UntypedExpr( new NameExpr(
     
    419337
    420338        FunctionDecl * create_resume_handler( CatchList &handlers ) {
    421                 // bool handle(exception * except) {
    422                 //     HANDLER WRAPPERS { `hander->body`; return true; }
    423                 // }
    424339                CompoundStmt * body = new CompoundStmt( noLabels );
    425340
     
    500415
    501416        FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
    502                 // void finally() { <finally code> }
    503417                FinallyStmt * finally = tryStmt->get_finally();
    504418                CompoundStmt * body = finally->get_block();
     
    548462                Context cur_context;
    549463
    550                 // The current (innermost) termination handler exception declaration.
    551                 ObjectDecl * handler_except_decl;
    552 
    553464                // We might not need this, but a unique base for each try block's
    554465                // generated functions might be nice.
     
    562473                ExceptionMutatorCore() :
    563474                        cur_context(NoHandler),
    564                         handler_except_decl( nullptr ),
    565                         node_decl( nullptr ), hook_decl( nullptr )
     475                        node_decl(nullptr), hook_decl(nullptr)
    566476                {}
    567477
     
    571481                Statement * postmutate( TryStmt *tryStmt );
    572482        };
    573 
    574         void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
    575                 // Currently, we make up the declaration, as there isn't one for
    576                 // integers.
    577                 ObjectDecl * tmp = new ObjectDecl(
    578                         "_hidden_local",
    579                         Type::StorageClasses(),
    580                         LinkageSpec::Cforall,
    581                         nullptr,
    582                         new PointerType(
    583                                 noQualifiers,
    584                                 new BasicType( noQualifiers, BasicType::SignedInt )
    585                                 ),
    586                         nullptr
    587                         );
    588                 catchStmt->set_decl( tmp );
    589 
    590                 GuardValue( cur_context );
    591                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    592                         cur_context = TerHandler;
    593 
    594                         GuardValue( handler_except_decl );
    595                         handler_except_decl = tmp;
    596                         //handler_except_decl = catchStmt->get_decl();
    597                 } else {
    598                         cur_context = ResHandler;
    599                 }
    600         }
    601 
    602         void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
    603                 if ( !structDecl->has_body() ) {
    604                         // Skip children?
    605                         return;
    606                 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
    607                         assert( nullptr == node_decl );
    608                         node_decl = structDecl;
    609                 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
    610                         assert( nullptr == hook_decl );
    611                         hook_decl = structDecl;
    612                 }
    613                 // Later we might get the exception type as well.
    614         }
    615483
    616484        Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
     
    620488                                return create_terminate_throw( throwStmt );
    621489                        } else if ( TerHandler == cur_context ) {
    622                                 return create_terminate_rethrow(
    623                                         throwStmt, handler_except_decl );
     490                                return create_terminate_rethrow( throwStmt );
    624491                        } else {
    625492                                assertf(false, "Invalid throw in %s at %i\n",
     
    693560                block->push_back( inner );
    694561
     562                //free_all( termination_handlers );
     563                //free_all( resumption_handlers );
     564
    695565                return block;
     566        }
     567
     568        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
     569                GuardValue( cur_context );
     570                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
     571                        cur_context = TerHandler;
     572                } else {
     573                        cur_context = ResHandler;
     574                }
     575        }
     576
     577        void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
     578                if ( !structDecl->has_body() ) {
     579                        // Skip children?
     580                        return;
     581                } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
     582                        assert( nullptr == node_decl );
     583                        node_decl = structDecl;
     584                } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
     585                        assert( nullptr == hook_decl );
     586                        hook_decl = structDecl;
     587                }
     588                // Later we might get the exception type as well.
    696589        }
    697590
  • src/libcfa/exception.c

    r79dbb79 r59310bf  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:13:00 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 28 12:41:00 2017
    13 // Update Count     : 3
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jul 26 10:37:51 2017
     13// Update Count     : 2
    1414//
    1515
     
    3333
    3434// Temperary global exception context. Does not work with concurency.
    35 struct exception_context_t {
     35struct shared_stack_t {
    3636    struct __cfaehm__try_resume_node * top_resume;
    3737    struct __cfaehm__try_resume_node * current_resume;
    3838
    39     exception * current_exception;
     39    exception current_exception;
    4040    int current_handler_index;
    41 
    42         // Storage to avoid using the heap for exceptions.
    43         exception built_in_storage;
    44 } shared_stack = {NULL, NULL, 0, 0, 0};
    45 
    46 // Get the current exception context.
    47 // There can be a single global until multithreading occurs, then each stack
    48 // needs its own. It will have to be updated to handle that.
    49 struct exception_context_t * this_exception_context() {
    50         return &shared_stack;
    51 }
    52 //#define SAVE_EXCEPTION_CONTEXT(to_name)
    53 //struct exception_context_t * to_name = this_exception_context();
    54 //exception * this_exception() {
    55 //    return this_exception_context()->current_exception;
    56 //}
     41} shared_stack = {NULL, NULL, 0, 0};
     42
    5743
    5844
     
    10894// TERMINATION ===============================================================
    10995
    110 // MEMORY MANAGEMENT (still for integers)
    111 // May have to move to cfa for constructors and destructors.
    112 
    113 // Creates a copy of the indicated exception and sets current_exception to it.
    114 static void __cfaehm__allocate_exception( exception * except ) {
    115         struct exception_context_t * context = this_exception_context();
    116 
    117         // Try to use the context's store, otherwise use the heap.
    118         if ( 0 == context->built_in_storage ) {
    119                 context->current_exception = &context->built_in_storage;
    120         } else {
    121                 exception * new_copy = malloc( sizeof( exception/*int*/ ) );
    122                 if ( ! new_copy ) {
    123                         // Failure: cannot allocate exception. Terminate thread.
    124                         exit(1); // <- thread or program?
    125                 }
    126                 context->current_exception = new_copy;
    127         }
    128 
    129         // Copy the exception to storage.
    130         *context->current_exception = *except;
    131 }
    132 
    133 // Delete the provided exception, unsetting current_exception if relivant.
    134 static void __cfaehm__delete_exception( exception * except ) {
    135         struct exception_context_t * context = this_exception_context();
    136 
    137         // DEBUG
    138         printf( "Deleting Exception %d (%s)\n", *except,
    139                 (&context->built_in_storage == except) ? "builtin" : "dynamic" );
    140 
    141         if ( context->current_exception == except ) {
    142                 // TODO: This should restore it to the last exception.
    143                 context->current_exception = NULL;
    144         }
    145         if ( &context->built_in_storage == except ) {
    146                 // You can't throw the exception '0'.
    147                 context->built_in_storage = 0;
    148         } else {
    149                 // Only secondary or too large exceptions are thrown.
    150                 free( except );
    151         }
    152 }
    153 
    154 // If this isn't a rethrow (*except==0), delete the provided exception.
    155 void __cfaehm__cleanup_terminate( exception ** except ) {
    156         if ( *except ) __cfaehm__delete_exception( *except );
    157 }
    158 
     96// Requires -fexceptions to work.
     97
     98// Global which defines the current exception.  Currently an int just to make matching easier.
     99//int this_exception; (became shared_stack.current_exception)
    159100
    160101// We need a piece of storage to raise the exception
     
    176117}
    177118
    178 // The exception that is being thrown must already be stored.
    179 __attribute__((noreturn)) void __cfaehm__begin_unwind(void) {
    180         if ( ! this_exception_context()->current_exception ) {
    181                 printf("UNWIND ERROR missing exception in begin unwind\n");
    182                 abort();
    183         }
    184 
     119void __cfaehm__throw_terminate( exception * val ) {
     120        // Store the current exception
     121        shared_stack.current_exception = *val;
     122
     123        // DEBUG
     124        printf("Throwing termination exception %d\n", *val);
    185125
    186126        // Call stdlibc to raise the exception
     
    208148}
    209149
    210 void __cfaehm__throw_terminate( exception * val ) {
    211         // DEBUG
    212         printf("Throwing termination exception\n");
    213 
    214         __cfaehm__allocate_exception( val );
    215         __cfaehm__begin_unwind();
    216 }
    217 
     150// Nesting this the other way would probably be faster.
    218151void __cfaehm__rethrow_terminate(void) {
    219152        // DEBUG
    220153        printf("Rethrowing termination exception\n");
    221154
    222         __cfaehm__begin_unwind();
     155        __cfaehm__throw_terminate(&shared_stack.current_exception);
    223156}
    224157
     
    330263                                        _Unwind_Reason_Code (*matcher)(exception *) =
    331264                                                MATCHER_FROM_CONTEXT(context);
    332                                         int index = matcher(shared_stack.current_exception);
     265                                        int index = matcher(&shared_stack.current_exception);
    333266                                        _Unwind_Reason_Code ret = (0 == index)
    334267                                                ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
     
    426359        // Exception handler
    427360        catch_block( shared_stack.current_handler_index,
    428                      shared_stack.current_exception );
     361                    &shared_stack.current_exception );
    429362}
    430363
  • src/libcfa/exception.h

    r79dbb79 r59310bf  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:11:00 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 27 12:42:00 2017
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:57:02 2017
     13// Update Count     : 3
    1414//
    1515
    1616#pragma once
    1717
     18// Later to be a special structure type.
     19typedef int exception;
    1820
    1921#ifdef __CFORALL__
    2022extern "C" {
    2123#endif
    22 
    23 #if 1
    24 typedef int exception;
    25 #else
    26 struct exception_t;
    27 struct exception_t_vtable {
    28         struct exception_t_vtable const * parent;
    29         size_t size;
    30         void (*copy)(struct exception_t *this, struct exception_t * other);
    31         void (*free)(struct exception_t *this);
    32         const char (*msg)(struct exception_t *this);
    33 };
    34 struct exception_t {
    35         struct exception_vtable const * virtual_table;
    36 };
    37 typedef struct exception_t exception;
    38 #endif
    39 
    4024
    4125// Used in throw statement translation.
     
    5034    int (*match_block)(exception * except));
    5135
    52 // Clean-up the exception in catch blocks.
    53 void __cfaehm__cleanup_terminate(exception ** except);
    54 
    5536// Data structure creates a list of resume handlers.
    5637struct __cfaehm__try_resume_node {
     
    5940};
    6041
    61 // These act as constructor and destructor for the resume node.
    6242void __cfaehm__try_resume_setup(
    6343    struct __cfaehm__try_resume_node * node,
     
    6747
    6848// Check for a standard way to call fake deconstructors.
    69 struct __cfaehm__cleanup_hook {};
     49struct __cfaehm__cleanup_hook {
     50};
    7051
    7152#ifdef __CFORALL__
Note: See TracChangeset for help on using the changeset viewer.