Changeset 79dbb79


Ignore:
Timestamp:
Jul 28, 2017, 2:26:29 PM (4 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
926341c, ea5023c
Parents:
59310bf (diff), 86d5ba7c (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' of plg2:software/cfa/cfa-cc

Location:
src
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cc

    r59310bf r79dbb79  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Jul 18 10:09:00 2017
    13 // Update Count     : 4
     12// Last Modified On : Fri Jul 28 14:03:00 2017
     13// Update Count     : 5
    1414//
    1515
     
    2121#include "SynTree/Type.h"
    2222#include "SynTree/Attribute.h"
     23#include "SynTree/VarExprReplacer.h"
    2324
    2425namespace ControlStruct {
    2526
    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 
    3127        // void (*function)();
    32         static FunctionType try_func_t(Type::Qualifiers(), false);
     28        static FunctionType try_func_t(noQualifiers, false);
    3329        // void (*function)(int, exception);
    34         static FunctionType catch_func_t(Type::Qualifiers(), false);
     30        static FunctionType catch_func_t(noQualifiers, false);
    3531        // int (*function)(exception);
    36         static FunctionType match_func_t(Type::Qualifiers(), false);
     32        static FunctionType match_func_t(noQualifiers, false);
    3733        // bool (*function)(exception);
    38         static FunctionType handle_func_t(Type::Qualifiers(), false);
     34        static FunctionType handle_func_t(noQualifiers, false);
    3935        // void (*function)(__attribute__((unused)) void *);
    40         static FunctionType finally_func_t(Type::Qualifiers(), false);
     36        static FunctionType finally_func_t(noQualifiers, false);
    4137
    4238        static void init_func_types() {
     
    115111        }
    116112
    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 
    126113        void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
    127114                block->push_back(new DeclStmt(noLabels, item));
     
    136123        Statement * create_given_throw(
    137124                        const char * throwFunc, ThrowStmt * throwStmt ) {
     125                // There is an extra copy here we might be able to remove with
     126                // references.
    138127                // { int NAME = EXPR; throwFunc( &NAME ); }
    139128                CompoundStmt * result = new CompoundStmt( noLabels );
     
    159148                return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
    160149        }
    161         Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) {
    162                 // __rethrow_terminate();
     150
     151        Statement * create_terminate_rethrow( ThrowStmt *throwStmt,
     152                        ObjectDecl *handler_except_decl ) {
     153                // { `handler_except_decl` = NULL; __rethrow_terminate(); }
    163154                assert( nullptr == throwStmt->get_expr() );
    164                 Statement * result = new ExprStmt(
    165                         throwStmt->get_labels(),
     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,
    166169                        new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
    167                         );
     170                        ) );
    168171                delete throwStmt;
    169172                return result;
    170173        }
     174
    171175        Statement * create_resume_throw( ThrowStmt *throwStmt ) {
    172176                // __throw_resume( EXPR );
    173177                return create_given_throw( "__cfaehm__throw_resume", throwStmt );
    174178        }
     179
    175180        Statement * create_resume_rethrow( ThrowStmt *throwStmt ) {
    176181                // return false;
     
    201206                FunctionType *func_type = catch_func_t.clone();
    202207                DeclarationWithType * index_obj = func_type->get_parameters().front();
    203         //      DeclarationWithType * except_obj = func_type->get_parameters().back();
     208                DeclarationWithType * except_obj = func_type->get_parameters().back();
    204209
    205210                // Index 1..{number of handlers}
     
    213218                        // case `index`:
    214219                        // {
     220                        //     `handler.decl` {inserted} = { except_obj };
    215221                        //     `handler.body`
    216222                        // }
    217223                        // return;
    218                         std::list<Statement *> caseBody;
    219                         caseBody.push_back( handler->get_body() );
     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() );
    220269                        handler->set_body( nullptr );
    221                         caseBody.push_back( new ReturnStmt( noLabels, nullptr ) );
    222 
     270
     271                        std::list<Statement *> caseBody
     272                                        { block, new ReturnStmt( noLabels, nullptr ) };
    223273                        handler_wrappers.push_back( new CaseStmt(
    224274                                noLabels,
     
    253303                CompoundStmt * block = new CompoundStmt( noLabels );
    254304
     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
    255325                // INTEGERconstant Version
    256                 assert( nullptr == modded_handler->get_decl() );
     326                // {
     327                //     `modded_handler.decl` = *`except`
     328                //     if ( `decl.name` == `modded_handler.cond` ) {
     329                //         `modded_handler.body`
     330                //     }
     331                // }
    257332                ConstantExpr * number =
    258333                        dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
     
    274349                }
    275350
     351                // Add the check on the conditional if it is provided.
    276352                if ( modded_handler->get_cond() ) {
    277353                        cond = new LogicalExpr( cond, modded_handler->get_cond() );
    278354                }
     355                // Construct the match condition.
    279356                block->push_back( new IfStmt( noLabels,
    280357                        cond, modded_handler->get_body(), nullptr ) );
     
    288365
    289366        FunctionDecl * create_terminate_match( CatchList &handlers ) {
     367                // int match(exception * except) {
     368                //     HANDLER WRAPPERS { return `index`; }
     369                // }
     370
    290371                CompoundStmt * body = new CompoundStmt( noLabels );
    291372
     
    323404                        FunctionDecl * terminate_catch,
    324405                        FunctionDecl * terminate_match) {
     406                // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
    325407
    326408                UntypedExpr * caller = new UntypedExpr( new NameExpr(
     
    337419
    338420        FunctionDecl * create_resume_handler( CatchList &handlers ) {
     421                // bool handle(exception * except) {
     422                //     HANDLER WRAPPERS { `hander->body`; return true; }
     423                // }
    339424                CompoundStmt * body = new CompoundStmt( noLabels );
    340425
     
    415500
    416501        FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
     502                // void finally() { <finally code> }
    417503                FinallyStmt * finally = tryStmt->get_finally();
    418504                CompoundStmt * body = finally->get_block();
     
    462548                Context cur_context;
    463549
     550                // The current (innermost) termination handler exception declaration.
     551                ObjectDecl * handler_except_decl;
     552
    464553                // We might not need this, but a unique base for each try block's
    465554                // generated functions might be nice.
     
    473562                ExceptionMutatorCore() :
    474563                        cur_context(NoHandler),
    475                         node_decl(nullptr), hook_decl(nullptr)
     564                        handler_except_decl( nullptr ),
     565                        node_decl( nullptr ), hook_decl( nullptr )
    476566                {}
    477567
     
    481571                Statement * postmutate( TryStmt *tryStmt );
    482572        };
     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        }
    483615
    484616        Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
     
    488620                                return create_terminate_throw( throwStmt );
    489621                        } else if ( TerHandler == cur_context ) {
    490                                 return create_terminate_rethrow( throwStmt );
     622                                return create_terminate_rethrow(
     623                                        throwStmt, handler_except_decl );
    491624                        } else {
    492625                                assertf(false, "Invalid throw in %s at %i\n",
     
    560693                block->push_back( inner );
    561694
    562                 //free_all( termination_handlers );
    563                 //free_all( resumption_handlers );
    564 
    565695                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.
    589696        }
    590697
  • src/libcfa/exception.c

    r59310bf r79dbb79  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:13:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 26 10:37:51 2017
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jul 28 12:41:00 2017
     13// Update Count     : 3
    1414//
    1515
     
    3333
    3434// Temperary global exception context. Does not work with concurency.
    35 struct shared_stack_t {
     35struct exception_context_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 } shared_stack = {NULL, NULL, 0, 0};
    42 
     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.
     49struct 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//}
    4357
    4458
     
    94108// TERMINATION ===============================================================
    95109
    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)
     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.
     114static 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.
     134static 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.
     155void __cfaehm__cleanup_terminate( exception ** except ) {
     156        if ( *except ) __cfaehm__delete_exception( *except );
     157}
     158
    100159
    101160// We need a piece of storage to raise the exception
     
    117176}
    118177
    119 void __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);
     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
    125185
    126186        // Call stdlibc to raise the exception
     
    148208}
    149209
    150 // Nesting this the other way would probably be faster.
     210void __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
    151218void __cfaehm__rethrow_terminate(void) {
    152219        // DEBUG
    153220        printf("Rethrowing termination exception\n");
    154221
    155         __cfaehm__throw_terminate(&shared_stack.current_exception);
     222        __cfaehm__begin_unwind();
    156223}
    157224
     
    263330                                        _Unwind_Reason_Code (*matcher)(exception *) =
    264331                                                MATCHER_FROM_CONTEXT(context);
    265                                         int index = matcher(&shared_stack.current_exception);
     332                                        int index = matcher(shared_stack.current_exception);
    266333                                        _Unwind_Reason_Code ret = (0 == index)
    267334                                                ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
     
    359426        // Exception handler
    360427        catch_block( shared_stack.current_handler_index,
    361                     &shared_stack.current_exception );
     428                     shared_stack.current_exception );
    362429}
    363430
  • src/libcfa/exception.h

    r59310bf r79dbb79  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:11:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:57:02 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jul 27 12:42:00 2017
     13// Update Count     : 4
    1414//
    1515
    1616#pragma once
    1717
    18 // Later to be a special structure type.
    19 typedef int exception;
    2018
    2119#ifdef __CFORALL__
    2220extern "C" {
    2321#endif
     22
     23#if 1
     24typedef int exception;
     25#else
     26struct exception_t;
     27struct 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};
     34struct exception_t {
     35        struct exception_vtable const * virtual_table;
     36};
     37typedef struct exception_t exception;
     38#endif
     39
    2440
    2541// Used in throw statement translation.
     
    3450    int (*match_block)(exception * except));
    3551
     52// Clean-up the exception in catch blocks.
     53void __cfaehm__cleanup_terminate(exception ** except);
     54
    3655// Data structure creates a list of resume handlers.
    3756struct __cfaehm__try_resume_node {
     
    4059};
    4160
     61// These act as constructor and destructor for the resume node.
    4262void __cfaehm__try_resume_setup(
    4363    struct __cfaehm__try_resume_node * node,
     
    4767
    4868// Check for a standard way to call fake deconstructors.
    49 struct __cfaehm__cleanup_hook {
    50 };
     69struct __cfaehm__cleanup_hook {};
    5170
    5271#ifdef __CFORALL__
Note: See TracChangeset for help on using the changeset viewer.