Ignore:
Timestamp:
Aug 10, 2017, 3:39:11 PM (8 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
38d70ab
Parents:
275f4b4 (diff), e1780a2 (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 plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/exception.c

    r275f4b4 rcd7ef0b  
    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 Aug  4 15:20:00 2017
     13// Update Count     : 6
    1414//
     15
     16#include <stddef.h> // for size_t
    1517
    1618#include "exception.h"
     
    3234#include "lsda.h"
    3335
     36
     37// Base exception vtable is abstract, you should not have base exceptions.
     38struct __cfaehm__base_exception_t_vtable
     39                ___cfaehm__base_exception_t_vtable_instance = {
     40        .parent = NULL,
     41        .size = 0,
     42        .copy = NULL,
     43        .free = NULL,
     44        .msg = NULL
     45};
     46
     47
    3448// Temperary global exception context. Does not work with concurency.
    35 struct shared_stack_t {
     49struct exception_context_t {
    3650    struct __cfaehm__try_resume_node * top_resume;
    3751    struct __cfaehm__try_resume_node * current_resume;
    3852
    39     exception current_exception;
     53    exception * current_exception;
    4054    int current_handler_index;
    4155} shared_stack = {NULL, NULL, 0, 0};
    4256
     57// Get the current exception context.
     58// There can be a single global until multithreading occurs, then each stack
     59// needs its own. It will have to be updated to handle that.
     60struct exception_context_t * this_exception_context() {
     61        return &shared_stack;
     62}
     63//#define SAVE_EXCEPTION_CONTEXT(to_name)
     64//struct exception_context_t * to_name = this_exception_context();
     65//exception * this_exception() {
     66//    return this_exception_context()->current_exception;
     67//}
    4368
    4469
     
    5580
    5681        // DEBUG
    57         printf("Throwing resumption exception %d\n", *except);
     82        printf("Throwing resumption exception\n");
    5883
    5984        struct __cfaehm__try_resume_node * original_head = shared_stack.current_resume;
     
    6994        }
    7095
    71         printf("Unhandled exception %d\n", *except);
     96        printf("Unhandled exception\n");
    7297        shared_stack.current_resume = original_head;
    7398
     
    94119// TERMINATION ===============================================================
    95120
    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)
     121// MEMORY MANAGEMENT (still for integers)
     122// May have to move to cfa for constructors and destructors (references).
     123
     124struct __cfaehm__node {
     125        struct __cfaehm__node * next;
     126};
     127
     128#define NODE_TO_EXCEPT(node) ((exception *)(1 + (node)))
     129#define EXCEPT_TO_NODE(except) ((struct __cfaehm__node *)(except) - 1)
     130
     131// Creates a copy of the indicated exception and sets current_exception to it.
     132static void __cfaehm__allocate_exception( exception * except ) {
     133        struct exception_context_t * context = this_exception_context();
     134
     135        // Allocate memory for the exception.
     136        struct __cfaehm__node * store = malloc(
     137                sizeof( struct __cfaehm__node ) + except->virtual_table->size );
     138
     139        if ( ! store ) {
     140                // Failure: cannot allocate exception. Terminate thread.
     141                abort(); // <- Although I think it might be the process.
     142        }
     143
     144        // Add the node to the list:
     145        store->next = EXCEPT_TO_NODE(context->current_exception);
     146        context->current_exception = NODE_TO_EXCEPT(store);
     147
     148        // Copy the exception to storage.
     149        except->virtual_table->copy( context->current_exception, except );
     150}
     151
     152// Delete the provided exception, unsetting current_exception if relivant.
     153static void __cfaehm__delete_exception( exception * except ) {
     154        struct exception_context_t * context = this_exception_context();
     155
     156        // DEBUG
     157        printf( "Deleting Exception\n");
     158
     159        // Remove the exception from the list.
     160        struct __cfaehm__node * to_free = EXCEPT_TO_NODE(except);
     161        struct __cfaehm__node * node;
     162
     163        if ( context->current_exception == except ) {
     164                node = to_free->next;
     165                context->current_exception = (node) ? NODE_TO_EXCEPT(node) : 0;
     166        } else {
     167                node = EXCEPT_TO_NODE(context->current_exception);
     168                // It may always be in the first or second position.
     169                while( to_free != node->next ) {
     170                        node = node->next;
     171                }
     172                node->next = to_free->next;
     173        }
     174
     175        // Free the old exception node.
     176        except->virtual_table->free( except );
     177        free( to_free );
     178}
     179
     180// If this isn't a rethrow (*except==0), delete the provided exception.
     181void __cfaehm__cleanup_terminate( void * except ) {
     182        if ( *(void**)except ) __cfaehm__delete_exception( *(exception**)except );
     183}
     184
    100185
    101186// We need a piece of storage to raise the exception
     
    117202}
    118203
    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);
     204// The exception that is being thrown must already be stored.
     205__attribute__((noreturn)) void __cfaehm__begin_unwind(void) {
     206        if ( ! this_exception_context()->current_exception ) {
     207                printf("UNWIND ERROR missing exception in begin unwind\n");
     208                abort();
     209        }
     210
    125211
    126212        // Call stdlibc to raise the exception
     
    148234}
    149235
    150 // Nesting this the other way would probably be faster.
     236void __cfaehm__throw_terminate( exception * val ) {
     237        // DEBUG
     238        printf("Throwing termination exception\n");
     239
     240        __cfaehm__allocate_exception( val );
     241        __cfaehm__begin_unwind();
     242}
     243
    151244void __cfaehm__rethrow_terminate(void) {
    152245        // DEBUG
    153246        printf("Rethrowing termination exception\n");
    154247
    155         __cfaehm__throw_terminate(&shared_stack.current_exception);
     248        __cfaehm__begin_unwind();
    156249}
    157250
     
    263356                                        _Unwind_Reason_Code (*matcher)(exception *) =
    264357                                                MATCHER_FROM_CONTEXT(context);
    265                                         int index = matcher(&shared_stack.current_exception);
     358                                        int index = matcher(shared_stack.current_exception);
    266359                                        _Unwind_Reason_Code ret = (0 == index)
    267360                                                ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
     
    359452        // Exception handler
    360453        catch_block( shared_stack.current_handler_index,
    361                     &shared_stack.current_exception );
     454                     shared_stack.current_exception );
    362455}
    363456
Note: See TracChangeset for help on using the changeset viewer.