Changeset fe63ae6


Ignore:
Timestamp:
Apr 12, 2021, 5:16:45 PM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
a1b9bc3
Parents:
56c8b86 (diff), 73f4d08 (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

Files:
43 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/coroutine.cfa

    r56c8b86 rfe63ae6  
    4646
    4747//-----------------------------------------------------------------------------
    48 FORALL_DATA_INSTANCE(CoroutineCancelled, (coroutine_t &), (coroutine_t))
    49 
    50 forall(T &)
    51 void mark_exception(CoroutineCancelled(T) *) {}
     48EHM_VIRTUAL_TABLE(SomeCoroutineCancelled, std_coroutine_cancelled);
    5249
    5350forall(T &)
     
    7168
    7269        // TODO: Remove explitate vtable set once trac#186 is fixed.
    73         CoroutineCancelled(T) except;
    74         except.virtual_table = &get_exception_vtable(&except);
     70        SomeCoroutineCancelled except;
     71        except.virtual_table = &std_coroutine_cancelled;
    7572        except.the_coroutine = &cor;
    7673        except.the_exception = except;
    77         throwResume except;
     74        // Why does this need a cast?
     75        throwResume (SomeCoroutineCancelled &)except;
    7876
    7977        except->virtual_table->free( except );
  • libcfa/src/concurrency/coroutine.hfa

    r56c8b86 rfe63ae6  
    2222//-----------------------------------------------------------------------------
    2323// Exception thrown from resume when a coroutine stack is cancelled.
    24 FORALL_DATA_EXCEPTION(CoroutineCancelled, (coroutine_t &), (coroutine_t)) (
     24EHM_EXCEPTION(SomeCoroutineCancelled)(
     25        void * the_coroutine;
     26        exception_t * the_exception;
     27);
     28
     29EHM_EXTERN_VTABLE(SomeCoroutineCancelled, std_coroutine_cancelled);
     30
     31EHM_FORALL_EXCEPTION(CoroutineCancelled, (coroutine_t &), (coroutine_t)) (
    2532        coroutine_t * the_coroutine;
    2633        exception_t * the_exception;
     
    3744// Anything that implements this trait can be resumed.
    3845// Anything that is resumed is a coroutine.
    39 trait is_coroutine(T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled, (T))) {
     46trait is_coroutine(T & | IS_RESUMPTION_EXCEPTION(SomeCoroutineCancelled)) {
    4047        void main(T & this);
    4148        $coroutine * get_coroutine(T & this);
  • libcfa/src/concurrency/kernel.cfa

    r56c8b86 rfe63ae6  
    359359                                #if !defined(__CFA_NO_STATISTICS__)
    360360                                        __tls_stats()->ready.threads.threads++;
     361                                        __push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", this );
    361362                                #endif
    362363                                // This is case 2, the racy case, someone tried to run this thread before it finished blocking
     
    376377        #if !defined(__CFA_NO_STATISTICS__)
    377378                __tls_stats()->ready.threads.threads--;
     379                __push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", this );
    378380        #endif
    379381
     
    455457                if( kernelTLS().this_stats ) {
    456458                        __tls_stats()->ready.threads.threads++;
     459                        __push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", kernelTLS().this_processor );
    457460                }
    458461                else {
    459462                        __atomic_fetch_add(&cl->stats->ready.threads.threads, 1, __ATOMIC_RELAXED);
     463                        __push_stat( cl->stats, cl->stats->ready.threads.threads, true, "Cluster", cl );
    460464                }
    461465        #endif
  • libcfa/src/concurrency/kernel/startup.cfa

    r56c8b86 rfe63ae6  
    268268                        __print_stats( st, mainProcessor->print_stats, "Processor ", mainProcessor->name, (void*)mainProcessor );
    269269                }
     270                #if defined(CFA_STATS_ARRAY)
     271                        __flush_stat( st, "Processor", mainProcessor );
     272                #endif
    270273        #endif
    271274
     
    348351                        __print_stats( &local_stats, proc->print_stats, "Processor ", proc->name, (void*)proc );
    349352                }
     353                #if defined(CFA_STATS_ARRAY)
     354                        __flush_stat( &local_stats, "Processor", proc );
     355                #endif
    350356        #endif
    351357
     
    615621                        __print_stats( this.stats, this.print_stats, "Cluster", this.name, (void*)&this );
    616622                }
     623                #if defined(CFA_STATS_ARRAY)
     624                        __flush_stat( this.stats, "Cluster", &this );
     625                #endif
    617626                free( this.stats );
    618627        #endif
  • libcfa/src/concurrency/stats.cfa

    r56c8b86 rfe63ae6  
    55#include <inttypes.h>
    66#include "bits/debug.hfa"
     7#include "bits/locks.hfa"
    78#include "stats.hfa"
    89
     
    4445                        stats->io.calls.errors.busy = 0;
    4546                        stats->io.poller.sleeps     = 0;
     47                #endif
     48
     49                #if defined(CFA_STATS_ARRAY)
     50                        stats->array.values = alloc(CFA_STATS_ARRAY);
     51                        stats->array.cnt = 0;
    4652                #endif
    4753        }
     
    151157                #endif
    152158        }
     159
     160        #if defined(CFA_STATS_ARRAY)
     161                extern "C" {
     162                        #include <stdio.h>
     163                        #include <errno.h>
     164                        #include <sys/stat.h>
     165                        #include <fcntl.h>
     166                }
     167
     168                void __flush_stat( struct __stats_t * this, const char * name, void * handle) {
     169                        int ret = mkdir(".cfadata", 0755);
     170                        if(ret < 0 && errno != EEXIST) abort("Failed to create directory .cfadata: %d\n", errno);
     171
     172                        char filename[100];
     173                        snprintf(filename, 100, ".cfadata/%s%p.data", name, handle);
     174
     175                        int fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0644);
     176                        if(fd < 0) abort("Failed to create file %s: %d\n", filename, errno);
     177
     178                        for(i; this->array.cnt) {
     179                                char line[100];
     180                                size_t n = snprintf(line, 100, "%llu, %lld\n", this->array.values[i].ts, this->array.values[i].value);
     181                                write(fd, line, n);
     182                        }
     183
     184                        this->array.cnt = 0;
     185                        close(fd);
     186                }
     187
     188                static __spinlock_t stats_lock;
     189
     190                void __push_stat( struct __stats_t * this, int64_t value, bool external, const char * name, void * handle ) {
     191                        if(external) lock(stats_lock __cfaabi_dbg_ctx2);
     192
     193                        if( this->array.cnt >= CFA_STATS_ARRAY ) __flush_stat( this, name, handle );
     194
     195                        size_t idx = this->array.cnt;
     196                        this->array.cnt++;
     197
     198                        if(external) unlock(stats_lock);
     199
     200                        this->array.values[idx].ts = rdtscl();
     201                        this->array.values[idx].value = value;
     202                }
     203        #endif
    153204#endif
  • libcfa/src/concurrency/stats.hfa

    r56c8b86 rfe63ae6  
    11#pragma once
     2
     3// #define CFA_STATS_ARRAY 10000
    24
    35#include <stdint.h>
     
    109111        #endif
    110112
     113        #if defined(CFA_STATS_ARRAY)
     114                struct __stats_elem_t {
     115                        long long int ts;
     116                        int64_t value;
     117                };
     118        #endif
     119
    111120        struct __attribute__((aligned(128))) __stats_t {
    112121                __stats_readQ_t ready;
     
    114123                        __stats_io_t    io;
    115124                #endif
     125
     126                #if defined(CFA_STATS_ARRAY)
     127                        struct {
     128                                __stats_elem_t * values;
     129                                volatile size_t cnt;
     130                        } array;
     131                #endif
     132
    116133        };
    117134
     
    119136        void __tally_stats( struct __stats_t *, struct __stats_t * );
    120137        void __print_stats( struct __stats_t *, int, const char *, const char *, void * );
     138        #if defined(CFA_STATS_ARRAY)
     139                void __push_stat ( struct __stats_t *, int64_t value, bool external, const char * name, void * handle);
     140                void __flush_stat( struct __stats_t *, const char *, void * );
     141        #else
     142                static inline void __push_stat ( struct __stats_t *, int64_t, bool, const char *, void * ) {}
     143                static inline void __flush_stat( struct __stats_t *, const char *, void * ) {}
     144        #endif
    121145#endif
    122146
  • libcfa/src/concurrency/thread.cfa

    r56c8b86 rfe63ae6  
    6262}
    6363
    64 FORALL_DATA_INSTANCE(ThreadCancelled, (thread_t &), (thread_t))
     64EHM_VIRTUAL_TABLE(SomeThreadCancelled, std_thread_cancelled);
    6565
    6666forall(T &)
     
    7373forall(T &)
    7474const char * msg(ThreadCancelled(T) *) {
    75         return "ThreadCancelled";
     75        return "ThreadCancelled(...)";
    7676}
    7777
    7878forall(T &)
    7979static void default_thread_cancel_handler(ThreadCancelled(T) & ) {
     80        // Improve this error message, can I do formatting?
    8081        abort( "Unhandled thread cancellation.\n" );
    8182}
    8283
    83 forall(T & | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)))
     84static void default_thread_cancel_handler(SomeThreadCancelled & ) {
     85        // Improve this error message, can I do formatting?
     86        abort( "Unhandled thread cancellation.\n" );
     87}
     88
     89forall(T & | is_thread(T) | IS_EXCEPTION(SomeThreadCancelled))
    8490void ?{}( thread_dtor_guard_t & this,
    85                 T & thrd, void(*cancelHandler)(ThreadCancelled(T) &)) {
    86         $monitor * m = get_monitor(thrd);
     91                T & thrd, void(*cancelHandler)(SomeThreadCancelled &)) {
     92        $monitor * m = get_monitor(thrd);
    8793        $thread * desc = get_thread(thrd);
    8894
    8995        // Setup the monitor guard
    9096        void (*dtor)(T& mutex this) = ^?{};
    91         bool join = cancelHandler != (void(*)(ThreadCancelled(T)&))0;
     97        bool join = cancelHandler != (void(*)(SomeThreadCancelled&))0;
    9298        (this.mg){&m, (void(*)())dtor, join};
    9399
     
    103109        }
    104110        desc->state = Cancelled;
    105         void(*defaultResumptionHandler)(ThreadCancelled(T) &) =
     111        void(*defaultResumptionHandler)(SomeThreadCancelled &) =
    106112                join ? cancelHandler : default_thread_cancel_handler;
    107113
    108         ThreadCancelled(T) except;
    109114        // TODO: Remove explitate vtable set once trac#186 is fixed.
    110         except.virtual_table = &get_exception_vtable(&except);
     115        SomeThreadCancelled except;
     116        except.virtual_table = &std_thread_cancelled;
    111117        except.the_thread = &thrd;
    112118        except.the_exception = __cfaehm_cancellation_exception( cancellation );
    113         throwResume except;
     119        // Why is this cast required?
     120        throwResume (SomeThreadCancelled &)except;
    114121
    115122        except.the_exception->virtual_table->free( except.the_exception );
     
    158165
    159166//-----------------------------------------------------------------------------
    160 forall(T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))
     167forall(T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(SomeThreadCancelled))
    161168T & join( T & this ) {
    162169        thread_dtor_guard_t guard = { this, defaultResumptionHandler };
  • libcfa/src/concurrency/thread.hfa

    r56c8b86 rfe63ae6  
    3232};
    3333
    34 FORALL_DATA_EXCEPTION(ThreadCancelled, (thread_t &), (thread_t)) (
     34EHM_EXCEPTION(SomeThreadCancelled) (
     35        void * the_thread;
     36        exception_t * the_exception;
     37);
     38
     39EHM_EXTERN_VTABLE(SomeThreadCancelled, std_thread_cancelled);
     40
     41EHM_FORALL_EXCEPTION(ThreadCancelled, (thread_t &), (thread_t)) (
    3542        thread_t * the_thread;
    3643        exception_t * the_exception;
     
    7986};
    8087
    81 forall( T & | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)) )
    82 void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(ThreadCancelled(T) &) );
     88forall( T & | is_thread(T) | IS_EXCEPTION(SomeThreadCancelled) )
     89void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(SomeThreadCancelled &) );
    8390void ^?{}( thread_dtor_guard_t & this );
    8491
     
    125132//----------
    126133// join
    127 forall( T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)) )
     134forall( T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(SomeThreadCancelled) )
    128135T & join( T & this );
    129136
  • libcfa/src/exception.c

    r56c8b86 rfe63ae6  
    1010// Created On       : Mon Jun 26 15:13:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct 27 16:27:00 2020
    13 // Update Count     : 35
     12// Last Modified On : Wed Feb 24 13:40:00 2021
     13// Update Count     : 36
    1414//
    1515
     
    2626#include "concurrency/invoke.h"
    2727#include "stdhdr/assert.h"
     28#include "virtual.h"
    2829
    2930#if defined( __ARM_ARCH )
     
    4647const _Unwind_Exception_Class __cfaehm_exception_class = 0x4c50575500414643;
    4748
    48 // Base exception vtable is abstract, you should not have base exceptions.
    49 struct __cfaehm_base_exception_t_vtable
    50                 ___cfaehm_base_exception_t_vtable_instance = {
    51         .parent = NULL,
    52         .size = 0,
    53         .copy = NULL,
    54         .free = NULL,
    55         .msg = NULL
     49// Base Exception type id:
     50struct __cfa__parent_vtable __cfatid_exception_t = {
     51        NULL,
    5652};
    5753
  • libcfa/src/exception.h

    r56c8b86 rfe63ae6  
    1010// Created On       : Mon Jun 26 15:11:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct 27 14:45:00 2020
    13 // Update Count     : 11
     12// Last Modified On : Thr Apr  8 15:20:00 2021
     13// Update Count     : 12
    1414//
    1515
     
    2929struct __cfaehm_base_exception_t;
    3030typedef struct __cfaehm_base_exception_t exception_t;
     31struct __cfa__parent_vtable;
    3132struct __cfaehm_base_exception_t_vtable {
    32         const struct __cfaehm_base_exception_t_vtable * parent;
     33        const struct __cfa__parent_vtable * __cfavir_typeid;
    3334        size_t size;
    3435        void (*copy)(struct __cfaehm_base_exception_t *this,
     
    4041        struct __cfaehm_base_exception_t_vtable const * virtual_table;
    4142};
    42 extern struct __cfaehm_base_exception_t_vtable
    43         ___cfaehm_base_exception_t_vtable_instance;
     43extern struct __cfa__parent_vtable __cfatid_exception_t;
    4444
    4545
     
    104104        /* The first field must be a pointer to a virtual table.
    105105         * That virtual table must be a decendent of the base exception virtual table.
     106         * The virtual table must point at the prober type-id.
     107         * None of these can be enforced in an assertion.
    106108         */
    107         virtualT const & get_exception_vtable(exceptT *);
    108         // Always returns the virtual table for this type (associated types hack).
    109109};
    110110
  • libcfa/src/exception.hfa

    r56c8b86 rfe63ae6  
    1010// Created On       : Thu Apr  7 10:25:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Aug  4 16:22:00 2020
    13 // Update Count     : 3
     12// Last Modified On : Thr Apr  8 15:16:00 2021
     13// Update Count     : 4
    1414//
    1515
     
    1818// -----------------------------------------------------------------------------------------------
    1919
    20 // TRIVIAL_EXCEPTION_DECLARATION(exception_name);
    21 // Declare a trivial exception, one that adds no fields or features.
    22 // This will make the exception visible and may go in a .hfa or .cfa file.
    23 #define TRIVIAL_EXCEPTION_DECLARATION(...) \
    24         _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__)
     20// EHM_EXCEPTION(exception_name)(fields...);
     21// Create an exception (a virtual structure that inherits from exception_t)
     22// with the given name and fields.
     23#define EHM_EXCEPTION(exception_name) \
     24        _EHM_TYPE_ID_STRUCT(exception_name, ); \
     25        _EHM_TYPE_ID_VALUE(exception_name, ); \
     26        _EHM_VIRTUAL_TABLE_STRUCT(exception_name, , ); \
     27        _EHM_EXCEPTION_STRUCT(exception_name, , )
    2528
    26 // TRIVIAL_EXCEPTION_INSTANCE(exception_name);
    27 // Create the trival exception. This must be used exactly once and should be used in a .cfa file,
    28 // as it creates the unique instance of the virtual table.
    29 #define TRIVIAL_EXCEPTION_INSTANCE(...) _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__)
     29// EHM_EXTERN_VTABLE(exception_name, table_name);
     30// Forward declare a virtual table called table_name for exception_name type.
     31#define EHM_EXTERN_VTABLE(exception_name, table_name) \
     32        _EHM_EXTERN_VTABLE(exception_name, , table_name)
    3033
    31 // TRIVIAL_EXCEPTION(exception_name[, parent_name]);
    32 // Does both of the above, a short hand if the exception is only used in one .cfa file.
    33 // For legacy reasons this is the only one that official supports having a parent other than the
    34 // base exception. This feature may be removed or changed.
    35 #define TRIVIAL_EXCEPTION(...) \
    36         _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__); \
    37         _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__)
     34// EHM_VIRTUAL_TABLE(exception_name, table_name);
     35// Define a virtual table called table_name for exception_name type.
     36#define EHM_VIRTUAL_TABLE(exception_name, table_name) \
     37        _EHM_DEFINE_COPY(exception_name, ) \
     38        _EHM_DEFINE_MSG(exception_name, ) \
     39        _EHM_VIRTUAL_TABLE(exception_name, , table_name)
    3840
    39 // FORALL_TRIVIAL_EXCEPTION(exception_name, (assertions...), (parameters...));
    40 // Forward declare a polymorphic but otherwise trivial exception type. You must provide the entire
    41 // assertion list (exactly what would go in the forall clause) and parameters list (only the
    42 // parameter names from the assertion list, same order and comma seperated). This should be
    43 // visible where ever use the exception. This just generates the polymorphic framework, see
    44 // POLY_VTABLE_DECLARATION to allow instantiations.
    45 #define FORALL_TRIVIAL_EXCEPTION(exception_name, assertions, parameters) \
    46         _FORALL_TRIVIAL_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
     41// EHM_FORALL_EXCEPTION(exception_name, (assertions), (parameters))(fields...);
     42// As EHM_EXCEPTION but for polymorphic types instead of monomorphic ones.
     43// The assertions list should include all polymorphic parameters and
     44// assertions inside a parentisized list. Parameters should include all the
     45// polymorphic parameter names inside a parentisized list (same order).
     46#define EHM_FORALL_EXCEPTION(exception_name, assertions, parameters) \
     47        _EHM_TYPE_ID_STRUCT(exception_name, forall assertions); \
     48        _EHM_VIRTUAL_TABLE_STRUCT(exception_name, forall assertions, parameters); \
     49        _EHM_EXCEPTION_STRUCT(exception_name, forall assertions, parameters)
    4750
    48 // FORALL_TRIVIAL_INSTANCE(exception_name, (assertions...), (parameters...))
    49 // Create the forall trivial exception. The assertion list and parameters must match.
    50 // There must be exactly one use of this in a program for each exception type. This just
    51 // generates the polymorphic framework, see POLY_VTABLE_INSTANCE to allow instantiations.
    52 #define FORALL_TRIVIAL_INSTANCE(exception_name, assertions, parameters) \
    53         _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters)
     51// EHM_FORALL_EXTERN_VTABLE(exception_name, (arguments), table_name);
     52// As EHM_EXTERN_VTABLE but for polymorphic types instead of monomorphic ones.
     53// Arguments should be the parentisized list of polymorphic arguments.
     54#define EHM_FORALL_EXTERN_VTABLE(exception_name, arguments, table_name) \
     55        _EHM_EXTERN_VTABLE(exception_name, arguments, table_name)
    5456
    55 // DATA_EXCEPTION(exception_name)(fields...);
    56 // Forward declare an exception that adds fields but no features. The added fields go in the
    57 // second argument list. The virtual table instance must be provided later (see VTABLE_INSTANCE).
    58 #define DATA_EXCEPTION(...) _EXC_DISPATCH(_DATA_EXCEPTION, __VA_ARGS__)
     57// EHM_FORALL_VIRTUAL_TABLE(exception_name, (arguments), table_name);
     58// As EHM_VIRTUAL_TABLE but for polymorphic types instead of monomorphic ones.
     59// Arguments should be the parentisized list of polymorphic arguments.
     60#define EHM_FORALL_VIRTUAL_TABLE(exception_name, arguments, table_name) \
     61        _EHM_TYPE_ID_VALUE(exception_name, arguments); \
     62        _EHM_DEFINE_COPY(exception_name, arguments) \
     63        _EHM_DEFINE_MSG(exception_name, arguments) \
     64        _EHM_VIRTUAL_TABLE(exception_name, arguments, table_name)
    5965
    60 // FORALL_DATA_EXCEPTION(exception_name, (assertions...), (parameters...))(fields...);
    61 // Define a polymorphic exception that adds fields but no additional features. The assertion list
    62 // and matching parameters must match. Then you can give the list of fields. This should be
    63 // visible where ever you use the exception. This just generates the polymorphic framework, see
    64 // POLY_VTABLE_DECLARATION to allow instantiations.
    65 #define FORALL_DATA_EXCEPTION(exception_name, assertions, parameters) \
    66         _FORALL_DATA_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
     66#define EHM_TYPE_ID(exception_name) _EHM_TYPE_ID_TYPE(exception_name)
    6767
    68 // FORALL_DATA_INSTANCE(exception_name, (assertions...), (parameters...))
    69 // Create a polymorphic data exception. The assertion list and parameters must match. This should
    70 // appear once in each program. This just generates the polymorphic framework, see
    71 // POLY_VTABLE_INSTANCE to allow instantiations.
    72 #define FORALL_DATA_INSTANCE(exception_name, assertions, parameters) \
    73         _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters)
    74 
    75 // VTABLE_DECLARATION(exception_name)([new_features...]);
    76 // Declare a virtual table type for an exception with exception_name. You may also add features
    77 // (fields on the virtual table) by including them in the second list.
    78 #define VTABLE_DECLARATION(...) _EXC_DISPATCH(_VTABLE_DECLARATION, __VA_ARGS__)
    79 
    80 // VTABLE_INSTANCE(exception_name)(msg [, others...]);
    81 // Create the instance of the virtual table. There must be exactly one instance of a virtual table
    82 // for each exception type. This fills in most of the fields of the virtual table (uses ?=? and
    83 // ^?{}) but you must provide the message function and any other fields added in the declaration.
    84 #define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__)
    85 
    86 // FORALL_VTABLE_DECLARATION(exception_name, (assertions...), (parameters...))([new_features...]);
    87 // Declare a polymorphic virtual table type for an exception with exception_name, the given
    88 // assertions and parameters. You may also add features (fields on the virtual table). This just
    89 // generates the polymorphic framework, see POLY_VTABLE_DECLARATION to allow instantiations.
    90 #define FORALL_VTABLE_DECLARATION(exception_name, assertions, parameters) \
    91         _FORALL_VTABLE_DECLARATION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
    92 
    93 // POLY_VTABLE_DECLARATION(exception_name, types...);
    94 // Declares that an instantiation for this exception exists for the given types. This should be
    95 // visible anywhere you use the instantiation of the exception is used.
    96 #define POLY_VTABLE_DECLARATION(exception_name, ...) \
    97         VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable(exception_name(__VA_ARGS__) *); \
    98         extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name)
    99 
    100 // POLY_VTABLE_INSTANCE(exception_name, types...)(msg [, others...]);
    101 // Creates an instantiation for the given exception for the given types. This should occur only
    102 // once in the entire program. You must fill in all features, message and any others given in the
    103 // initial declaration.
    104 #define POLY_VTABLE_INSTANCE(exception_name, ...) \
    105         _POLY_VTABLE_INSTANCE(exception_name, __cfaehm_base_exception_t, __VA_ARGS__)
    106 
    107 // VTABLE_TYPE(exception_name) | VTABLE_NAME(exception_name)
    108 // Get the name of the vtable type or the name of the vtable instance for an exception type.
    109 #define VTABLE_TYPE(exception_name) struct _GLUE2(exception_name,_vtable)
    110 #define VTABLE_NAME(exception_name) _GLUE3(_,exception_name,_vtable_instance)
    111 
    112 // VTABLE_FIELD(exception_name);
    113 // FORALL_VTABLE_FIELD(exception_name, (parameters-or-types));
    114 // The declaration of the virtual table field. Should be the first declaration in a virtual type.
    115 #define VTABLE_FIELD(exception_name) VTABLE_TYPE(exception_name) const * virtual_table
    116 #define FORALL_VTABLE_FIELD(exception_name, parameters) \
    117         VTABLE_TYPE(exception_name) parameters const * virtual_table
    118 
    119 // VTABLE_INIT(object_reference, exception_name);
    120 // Sets a virtual table field on an object to the virtual table instance for the type.
    121 #define VTABLE_INIT(this, exception_name) (this).virtual_table = &VTABLE_NAME(exception_name)
    122 
    123 // VTABLE_ASSERTION(exception_name, (parameters...))
    124 // The assertion that there is an instantiation of the vtable for the exception and types.
    125 #define VTABLE_ASSERTION(exception_name, parameters) \
    126         { VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); }
     68#define EHM_MATCH_ALL __cfa__parent_vtable
    12769
    12870// IS_EXCEPTION(exception_name [, (...parameters)])
     
    13577#define IS_TERMINATION_EXCEPTION(...) _IS_EXCEPTION(is_termination_exception, __VA_ARGS__, , ~)
    13678
    137 // All internal helper macros begin with an underscore.
    138 #define _CLOSE(...) __VA_ARGS__ }
    139 #define _GLUE2(left, right) left##right
    140 #define _GLUE3(left, middle, right) left##middle##right
    141 #define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,)
    142 #define _UNPACK(...) __VA_ARGS__
     79// Macros starting with a leading underscore are internal.
    14380
    144 #define _TRIVIAL_EXCEPTION_DECLARATION(exception_name, parent_name, ...) \
    145         _VTABLE_DECLARATION(exception_name, parent_name)(); \
    146         struct exception_name { \
    147                 VTABLE_FIELD(exception_name); \
    148         }; \
    149         void ?{}(exception_name & this); \
    150         const char * _GLUE2(exception_name,_msg)(exception_name * this)
     81// Create an exception type definition. must be tailing, can be polymorphic.
     82#define _EHM_EXCEPTION_STRUCT(exception_name, forall_clause, parameters) \
     83        forall_clause struct exception_name { \
     84                _EHM_VTABLE_TYPE(exception_name) parameters const * virtual_table; \
     85                _CLOSE
    15186
    152 #define _TRIVIAL_EXCEPTION_INSTANCE(exception_name, parent_name, ...) \
    153         void ?{}(exception_name & this) { \
    154                 VTABLE_INIT(this, exception_name); \
    155         } \
    156         const char * _GLUE2(exception_name,_msg)(exception_name * this) { \
    157                 return #exception_name; \
    158         } \
    159         _VTABLE_INSTANCE(exception_name, parent_name,)(_GLUE2(exception_name,_msg))
     87// Create a (possibly polymorphic) virtual table forward declaration.
     88#define _EHM_EXTERN_VTABLE(exception_name, arguments, table_name) \
     89        extern const _EHM_VTABLE_TYPE(exception_name) arguments table_name
    16090
    161 #define _FORALL_TRIVIAL_EXCEPTION(exception_name, parent_name, assertions, \
    162                 parameters, parent_parameters) \
    163         _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \
    164                 parameters, parent_parameters)(); \
    165         forall assertions struct exception_name { \
    166                 FORALL_VTABLE_FIELD(exception_name, parameters); \
    167         }; \
    168         _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters)
    169 
    170 #define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \
    171         forall(_UNPACK assertions | \
    172                 is_exception(exception_name parameters, VTABLE_TYPE(exception_name) parameters)) \
    173         void ?{}(exception_name parameters & this)
    174 
    175 #define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \
    176         _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \
    177                 (this).virtual_table = &get_exception_vtable(&this); \
     91// Create a (possibly polymorphic) virtual table definition.
     92#define _EHM_VIRTUAL_TABLE(exception_type, arguments, table_name) \
     93        const _EHM_VTABLE_TYPE(exception_type) arguments table_name @= { \
     94                .__cfavir_typeid : &_EHM_TYPE_ID_NAME(exception_type), \
     95                .size : sizeof(struct exception_type arguments), \
     96                .copy : copy, \
     97                .^?{} : ^?{}, \
     98                .msg : msg, \
    17899        }
    179100
    180 #define _DATA_EXCEPTION(exception_name, parent_name, ...) \
    181         _VTABLE_DECLARATION(exception_name, parent_name)(); \
    182         struct exception_name { \
    183                 VTABLE_FIELD(exception_name); \
    184                 _CLOSE
     101// Create a (possibly polymorphic) copy function from an assignment operator.
     102#define _EHM_DEFINE_FORALL_COPY(exception_name, forall_clause, parameters) \
     103        forall_clause void copy(exception_name parameters * this, \
     104                        exception_name parameters * that) { \
     105                *this = *that; \
     106        }
    185107
    186 #define _FORALL_DATA_EXCEPTION(exception_name, parent_name, \
    187                 assertions, parameters, parent_parameters) \
    188         _FORALL_VTABLE_DECLARATION(exception_name, parent_name, \
    189                 assertions, parameters, parent_parameters)(); \
    190         _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters); \
    191         forall assertions struct exception_name { \
    192                 FORALL_VTABLE_FIELD(exception_name, parameters); \
    193                 _CLOSE
     108#define _EHM_DEFINE_COPY(exception_name, arguments) \
     109        void copy(exception_name arguments * this, exception_name arguments * that) { \
     110                *this = *that; \
     111        }
    194112
    195 #define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
    196         struct exception_name; \
    197         VTABLE_TYPE(exception_name); \
    198         VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *); \
    199         extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \
    200         VTABLE_TYPE(exception_name) { \
    201                 VTABLE_TYPE(parent_name) const * parent; \
    202                 size_t size; \
    203                 void (*copy)(exception_name * this, exception_name * other); \
    204                 void (*^?{})(exception_name & this); \
    205                 const char * (*msg)(exception_name * this); \
    206                 _CLOSE
     113// Create a (possibly polymorphic) msg function
     114#define _EHM_DEFINE_FORALL_MSG(exception_name, forall_clause, parameters) \
     115        forall_clause const char * msg(exception_name parameters * this) { \
     116                return #exception_name #parameters; \
     117        }
    207118
    208 #define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
    209         VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *) { \
    210                 return VTABLE_NAME(exception_name); \
    211         } \
    212         void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \
    213                 *this = *other; \
    214         } \
    215         VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name) @= { \
    216                 &VTABLE_NAME(parent_name), sizeof(exception_name), \
    217                 _GLUE2(exception_name,_copy), ^?{}, \
    218                 _CLOSE
     119#define _EHM_DEFINE_MSG(exception_name, arguments) \
     120        const char * msg(exception_name arguments * this) { \
     121                return #exception_name #arguments; \
     122        }
    219123
    220 #define _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \
    221                 parameters, parent_parameters) \
    222         forall assertions struct exception_name; \
    223         forall assertions VTABLE_TYPE(exception_name) { \
    224                 VTABLE_TYPE(parent_name) parent_parameters const * parent; \
     124// Produces the C compatable name of the virtual table type for a virtual type.
     125#define _EHM_VTABLE_TYPE(type_name) struct _GLUE2(type_name,_vtable)
     126
     127// Create the vtable type for exception name.
     128#define _EHM_VIRTUAL_TABLE_STRUCT(exception_name, forall_clause, parameters) \
     129        forall_clause struct exception_name; \
     130        forall_clause _EHM_VTABLE_TYPE(exception_name) { \
     131                _EHM_TYPE_ID_TYPE(exception_name) parameters const * __cfavir_typeid; \
    225132                size_t size; \
    226133                void (*copy)(exception_name parameters * this, exception_name parameters * other); \
    227134                void (*^?{})(exception_name parameters & this); \
    228135                const char * (*msg)(exception_name parameters * this); \
    229                 _CLOSE
     136        }
    230137
    231 #define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \
    232         extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name); \
    233         VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable( \
    234                         exception_name(__VA_ARGS__) *) { \
    235                 return VTABLE_NAME(exception_name); \
    236         } \
    237         void _GLUE2(exception_name,_copy)( \
    238                         exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \
    239                 *this = *other; \
    240         } \
    241         VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name) @= { \
    242                 &VTABLE_NAME(parent_name), sizeof(exception_name(__VA_ARGS__)), \
    243                 _GLUE2(exception_name,_copy), ^?{}, \
    244                 _CLOSE
     138// Define the function required to satify the trait for exceptions.
     139#define _EHM_TRAIT_FUNCTION(exception_name, forall_clause, parameters) \
     140        forall_clause inline void mark_exception( \
     141                exception_name parameters const &, \
     142                _EHM_VTABLE_TYPE(exception_name) parameters const &) {} \
     143
     144#define _EHM_TRAIT_FUNCTION2(exception_name, forall_clause, parameters) \
     145        forall_clause _EHM_VTABLE_TYPE(exception_name) parameters const & \
     146                        get_exception_vtable(exception_name parameters const & this)
     147
     148#define __EHM_TRAIT_FUNCTION(exception_name, forall_clause, parameters) \
     149        forall_clause inline _EHM_VTABLE_TYPE(exception_name) parameters const & \
     150                        get_exception_vtable(exception_name parameters const & this) { \
     151                /* This comes before the structure definition, but we know the offset. */ \
     152                /* return (_EHM_VTABLE_TYPE(exception_name) parameters const &)this; */ \
     153                assert(false); \
     154        }
     155
     156// Generates a new type-id structure. This is used to mangle the name of the
     157// type-id instance so it also includes polymorphic information. Must be the
     158// direct decendent of exception_t.
     159// The second field is used to recover type information about the exception.
     160#define _EHM_TYPE_ID_STRUCT(exception_name, forall_clause) \
     161        forall_clause _EHM_TYPE_ID_TYPE(exception_name) { \
     162                __cfa__parent_vtable const * parent; \
     163        }
     164
     165// Generate a new type-id value.
     166#define _EHM_TYPE_ID_VALUE(exception_name, arguments) \
     167        __attribute__(( section(".gnu.linkonce." "__cfatid_" #exception_name) )) \
     168        _EHM_TYPE_ID_TYPE(exception_name) arguments const \
     169                        _EHM_TYPE_ID_NAME(exception_name) = { \
     170                &__cfatid_exception_t, \
     171        }
     172
     173// _EHM_TYPE_ID_STRUCT and _EHM_TYPE_ID_VALUE are the two that would need to
     174// be updated to extend the hierarchy if we are still using macros when that
     175// is added.
     176
     177// Produce the C compatable name of the type-id type for an exception type.
     178#define _EHM_TYPE_ID_TYPE(exception_name) \
     179        struct _GLUE2(__cfatid_struct_, exception_name)
     180
     181// Produce the name of the instance of the type-id for an exception type.
     182#define _EHM_TYPE_ID_NAME(exception_name) _GLUE2(__cfatid_,exception_name)
    245183
    246184#define _IS_EXCEPTION(kind, exception_name, parameters, ...) \
    247         kind(exception_name parameters, VTABLE_TYPE(exception_name) parameters)
     185        kind(exception_name parameters, _EHM_VTABLE_TYPE(exception_name) parameters)
     186
     187// Internal helper macros:
     188#define _CLOSE(...) __VA_ARGS__ }
     189#define _GLUE2(left, right) left##right
  • libcfa/src/fstream.cfa

    r56c8b86 rfe63ae6  
    321321
    322322
     323EHM_VIRTUAL_TABLE(Open_Failure, Open_Failure_main_table);
    323324void ?{}( Open_Failure & this, ofstream & ostream ) {
    324         VTABLE_INIT(this, Open_Failure);
     325        this.virtual_table = &Open_Failure_main_table;
    325326        this.ostream = &ostream;
    326327        this.tag = 1;
    327328}
    328329void ?{}( Open_Failure & this, ifstream & istream ) {
    329         VTABLE_INIT(this, Open_Failure);
     330        this.virtual_table = &Open_Failure_main_table;
    330331        this.istream = &istream;
    331332        this.tag = 0;
    332333}
    333 const char * Open_Failure_msg(Open_Failure * this) {
    334         return "Open_Failure";
    335 }
    336 VTABLE_INSTANCE(Open_Failure)(Open_Failure_msg);
    337334void throwOpen_Failure( ofstream & ostream ) {
    338335        Open_Failure exc = { ostream };
  • libcfa/src/fstream.hfa

    r56c8b86 rfe63ae6  
    133133
    134134
    135 DATA_EXCEPTION(Open_Failure)(
     135EHM_EXCEPTION(Open_Failure)(
    136136        union {
    137137                ofstream * ostream;
  • libcfa/src/virtual.c

    r56c8b86 rfe63ae6  
    1515
    1616#include "virtual.h"
     17#include "assert.h"
    1718
    1819int __cfa__is_parent( struct __cfa__parent_vtable const * parent,
    1920        struct __cfa__parent_vtable const * child ) {
     21        assert( child );
    2022        do {
    2123                if ( parent == child )
     
    2830void * __cfa__virtual_cast( struct __cfa__parent_vtable const * parent,
    2931        struct __cfa__parent_vtable const * const * child ) {
     32        assert( child );
    3033        return (__cfa__is_parent(parent, *child)) ? (void *)child : (void *)0;
    3134}
  • src/AST/Expr.cpp

    r56c8b86 rfe63ae6  
    260260}
    261261
     262ConstantExpr * ConstantExpr::from_string( const CodeLocation & loc, const std::string & str ) {
     263        const Type * charType = new BasicType( BasicType::Char );
     264        // Adjust the length of the string for the terminator.
     265        const Expr * strSize = from_ulong( loc, str.size() + 1 );
     266        const Type * strType = new ArrayType( charType, strSize, FixedLen, StaticDim );
     267        const std::string strValue = "\"" + str + "\"";
     268        return new ConstantExpr( loc, strType, strValue, std::nullopt );
     269}
     270
    262271ConstantExpr * ConstantExpr::null( const CodeLocation & loc, const Type * ptrType ) {
    263272        return new ConstantExpr{
  • src/AST/Expr.hpp

    r56c8b86 rfe63ae6  
    438438        long long int intValue() const;
    439439
    440         /// generates a boolean constant of the given bool
     440        /// Generates a boolean constant of the given bool.
    441441        static ConstantExpr * from_bool( const CodeLocation & loc, bool b );
    442         /// generates an integer constant of the given int
     442        /// Generates an integer constant of the given int.
    443443        static ConstantExpr * from_int( const CodeLocation & loc, int i );
    444         /// generates an integer constant of the given unsigned long int
     444        /// Generates an integer constant of the given unsigned long int.
    445445        static ConstantExpr * from_ulong( const CodeLocation & loc, unsigned long i );
    446         /// generates a null pointer value for the given type. void * if omitted.
     446        /// Generates a string constant from the given string (char type, unquoted string).
     447        static ConstantExpr * from_string( const CodeLocation & loc, const std::string & string );
     448        /// Generates a null pointer value for the given type. void * if omitted.
    447449        static ConstantExpr * null( const CodeLocation & loc, const Type * ptrType = nullptr );
    448450
  • src/Concurrency/Keywords.cc

    r56c8b86 rfe63ae6  
    4242
    4343namespace Concurrency {
     44        inline static std::string getTypeIdName( std::string const & exception_name ) {
     45                return exception_name.empty() ? std::string() : Virtual::typeIdType( exception_name );
     46        }
    4447        inline static std::string getVTableName( std::string const & exception_name ) {
    45                 return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name);
     48                return exception_name.empty() ? std::string() : Virtual::vtableTypeName( exception_name );
    4649        }
    4750
     
    7578                  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
    7679                  context_error( context_error ), exception_name( exception_name ),
     80                  typeid_name( getTypeIdName( exception_name ) ),
    7781                  vtable_name( getVTableName( exception_name ) ),
    7882                  needs_main( needs_main ), cast_target( cast_target ) {}
     
    8488
    8589                void handle( StructDecl * );
     90                void addTypeId( StructDecl * );
    8691                void addVtableForward( StructDecl * );
    8792                FunctionDecl * forwardDeclare( StructDecl * );
     
    99104                const std::string context_error;
    100105                const std::string exception_name;
     106                const std::string typeid_name;
    101107                const std::string vtable_name;
    102108                bool needs_main;
     
    106112                FunctionDecl * dtor_decl = nullptr;
    107113                StructDecl * except_decl = nullptr;
     114                StructDecl * typeid_decl = nullptr;
    108115                StructDecl * vtable_decl = nullptr;
    109116        };
     
    392399                else if ( !except_decl && exception_name == decl->name && decl->body ) {
    393400                        except_decl = decl;
     401                }
     402                else if ( !typeid_decl && typeid_name == decl->name && decl->body ) {
     403                        typeid_decl = decl;
    394404                }
    395405                else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
     
    448458                if( !dtor_decl ) SemanticError( decl, context_error );
    449459
    450                 addVtableForward( decl );
     460                if ( !exception_name.empty() ) {
     461                        if( !typeid_decl ) SemanticError( decl, context_error );
     462                        if( !vtable_decl ) SemanticError( decl, context_error );
     463
     464                        addTypeId( decl );
     465                        addVtableForward( decl );
     466                }
    451467                FunctionDecl * func = forwardDeclare( decl );
    452468                ObjectDecl * field = addField( decl );
     
    454470        }
    455471
     472        void ConcurrentSueKeyword::addTypeId( StructDecl * decl ) {
     473                assert( typeid_decl );
     474                StructInstType typeid_type( Type::Const, typeid_decl );
     475                typeid_type.parameters.push_back( new TypeExpr(
     476                        new StructInstType( noQualifiers, decl )
     477                        ) );
     478                declsToAddBefore.push_back( Virtual::makeTypeIdInstance( &typeid_type ) );
     479        }
     480
    456481        void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
    457                 if ( vtable_decl ) {
    458                         std::list< Expression * > poly_args = {
    459                                 new TypeExpr( new StructInstType( noQualifiers, decl ) ),
    460                         };
    461                         declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
    462                                 vtable_decl->makeInst( poly_args ),
    463                                 except_decl->makeInst( poly_args )
    464                         ) );
    465                         declsToAddBefore.push_back( Virtual::makeVtableForward(
    466                                 vtable_decl->makeInst( move( poly_args ) ) ) );
    467                 // Its only an error if we want a vtable and don't have one.
    468                 } else if ( ! vtable_name.empty() ) {
    469                         SemanticError( decl, context_error );
    470                 }
     482                assert( vtable_decl );
     483                std::list< Expression * > poly_args = {
     484                        new TypeExpr( new StructInstType( noQualifiers, decl ) ),
     485                };
     486                declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
     487                        vtable_decl->makeInst( poly_args ),
     488                        except_decl->makeInst( poly_args )
     489                ) );
     490                declsToAddBefore.push_back( Virtual::makeVtableForward(
     491                        vtable_decl->makeInst( move( poly_args ) ) ) );
    471492        }
    472493
  • src/SynTree/Constant.cc

    r56c8b86 rfe63ae6  
    4242}
    4343
     44Constant Constant::from_string( const std::string & str ) {
     45        Type * charType = new BasicType( noQualifiers, BasicType::Char );
     46        // Adjust the length of the string for the terminator.
     47        Expression * strSize = new ConstantExpr( Constant::from_ulong( str.size() + 1 ) );
     48        Type * strType = new ArrayType( noQualifiers, charType, strSize, false, false );
     49        const std::string strValue = "\"" + str + "\"";
     50        return Constant( strType, strValue, std::nullopt );
     51}
     52
    4453Constant Constant::null( Type * ptrtype ) {
    4554        if ( nullptr == ptrtype ) {
  • src/SynTree/Constant.h

    r56c8b86 rfe63ae6  
    4747        /// generates an integer constant of the given unsigned long int
    4848        static Constant from_ulong( unsigned long i );
     49        /// generates a string constant from the given string (char type, unquoted string)
     50        static Constant from_string( const std::string & string );
    4951
    5052        /// generates a null pointer value for the given type. void * if omitted.
  • src/Virtual/ExpandCasts.cc

    r56c8b86 rfe63ae6  
    3232namespace Virtual {
    3333
     34static bool is_prefix( const std::string & prefix, const std::string& entire ) {
     35        size_t const p_size = prefix.size();
     36        return (p_size < entire.size() && prefix == entire.substr(0, p_size));
     37}
     38
     39static bool is_type_id_object( const ObjectDecl * objectDecl ) {
     40        const std::string & objectName = objectDecl->name;
     41        return is_prefix( "__cfatid_", objectName );
     42}
     43
    3444        // Indented until the new ast code gets added.
    3545
     
    6676        };
    6777
    68         /* Currently virtual depends on the rather brittle name matching between
    69          * a (strict/explicate) virtual type, its vtable type and the vtable
    70          * instance.
    71          * A stronger implementation, would probably keep track of those triads
    72          * and use that information to create better error messages.
    73          */
    74 
    75         namespace {
    76 
    77         std::string get_vtable_name( std::string const & name ) {
    78                 return name + "_vtable";
    79         }
    80 
    81         std::string get_vtable_inst_name( std::string const & name ) {
    82                 return std::string("_") + get_vtable_name( name ) + "_instance";
    83         }
    84 
    85         std::string get_vtable_name_root( std::string const & name ) {
    86                 return name.substr(0, name.size() - 7 );
    87         }
    88 
    89         std::string get_vtable_inst_name_root( std::string const & name ) {
    90                 return get_vtable_name_root( name.substr(1, name.size() - 10 ) );
    91         }
    92 
    93         bool is_vtable_inst_name( std::string const & name ) {
    94                 return 17 < name.size() &&
    95                         name == get_vtable_inst_name( get_vtable_inst_name_root( name ) );
    96         }
    97 
    98         } // namespace
    99 
    10078        class VirtualCastCore {
    101                 Type * pointer_to_pvt(int level_of_indirection) {
     79                CastExpr * cast_to_type_id( Expression * expr, int level_of_indirection ) {
    10280                        Type * type = new StructInstType(
    10381                                Type::Qualifiers( Type::Const ), pvt_decl );
     
    10583                                type = new PointerType( noQualifiers, type );
    10684                        }
    107                         return type;
     85                        return new CastExpr( expr, type );
    10886                }
    10987
     
    141119
    142120        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    143                 if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
    144                         if ( ObjectDecl * existing = indexer.insert( objectDecl ) ) {
    145                                 std::string msg = "Repeated instance of virtual table, original found at: ";
    146                                 msg += existing->location.filename;
    147                                 msg += ":" + toString( existing->location.first_line );
    148                                 SemanticError( objectDecl->location, msg );
    149                         }
     121                if ( is_type_id_object( objectDecl ) ) {
     122                        // Multiple definitions should be fine because of linkonce.
     123                        indexer.insert( objectDecl );
    150124                }
    151125        }
     
    170144        }
    171145
    172         /// Get the virtual table type used in a virtual cast.
    173         Type * getVirtualTableType( const VirtualCastExpr * castExpr ) {
    174                 const Type * objectType;
    175                 if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) {
    176                         objectType = target->base;
    177                 } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) {
    178                         objectType = target->base;
     146        /// Get the base type from a pointer or reference.
     147        const Type * getBaseType( const Type * type ) {
     148                if ( auto target = dynamic_cast<const PointerType *>( type ) ) {
     149                        return target->base;
     150                } else if ( auto target = dynamic_cast<const ReferenceType *>( type ) ) {
     151                        return target->base;
    179152                } else {
    180                         castError( castExpr, "Virtual cast type must be a pointer or reference type." );
    181                 }
    182                 assert( objectType );
    183 
    184                 const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType );
    185                 if ( nullptr == structType ) {
    186                         castError( castExpr, "Virtual cast type must refer to a structure type." );
    187                 }
    188                 const StructDecl * structDecl = structType->baseStruct;
    189                 assert( structDecl );
    190 
    191                 const ObjectDecl * fieldDecl = nullptr;
    192                 if ( 0 < structDecl->members.size() ) {
    193                         const Declaration * memberDecl = structDecl->members.front();
     153                        return nullptr;
     154                }
     155        }
     156
     157        /* Attempt to follow the "head" field of the structure to get the...
     158         * Returns nullptr on error, otherwise owner must free returned node.
     159         */
     160        StructInstType * followHeadPointerType(
     161                        const StructInstType * oldType,
     162                        const std::string& fieldName,
     163                        const CodeLocation& errorLocation ) {
     164
     165                // First section of the function is all about trying to fill this variable in.
     166                StructInstType * newType = nullptr;
     167                {
     168                        const StructDecl * oldDecl = oldType->baseStruct;
     169                        assert( oldDecl );
     170
     171                        // Helper function for throwing semantic errors.
     172                        auto throwError = [&fieldName, &errorLocation, &oldDecl](const std::string& message) {
     173                                const std::string& context = "While following head pointer of " +
     174                                        oldDecl->name + " named '" + fieldName + "': ";
     175                                SemanticError( errorLocation, context + message );
     176                        };
     177
     178                        if ( oldDecl->members.empty() ) {
     179                                throwError( "Type has no fields." );
     180                        }
     181                        const Declaration * memberDecl = oldDecl->members.front();
    194182                        assert( memberDecl );
    195                         fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
    196                         if ( fieldDecl && fieldDecl->name != "virtual_table" ) {
    197                                 fieldDecl = nullptr;
    198                         }
    199                 }
    200                 if ( nullptr == fieldDecl ) {
    201                         castError( castExpr, "Virtual cast type must have a leading virtual_table field." );
    202                 }
    203                 const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type );
    204                 if ( nullptr == fieldType ) {
    205                         castError( castExpr, "Virtual cast type virtual_table field is not a pointer." );
    206                 }
    207                 assert( fieldType->base );
    208                 auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base );
    209                 assert( virtualStructType );
    210 
    211                 // Here is the type, but if it is polymorphic it will have lost information.
    212                 // (Always a clone so that it may always be deleted.)
    213                 StructInstType * virtualType = virtualStructType->clone();
    214                 if ( ! structType->parameters.empty() ) {
    215                         deleteAll( virtualType->parameters );
    216                         virtualType->parameters.clear();
    217                         cloneAll( structType->parameters, virtualType->parameters );
    218                 }
    219                 return virtualType;
     183                        const ObjectDecl * fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
     184                        assert( fieldDecl );
     185                        if ( fieldName != fieldDecl->name ) {
     186                                throwError( "Head field did not have expected name." );
     187                        }
     188
     189                        const Type * fieldType = fieldDecl->type;
     190                        if ( nullptr == fieldType ) {
     191                                throwError( "Could not get head field." );
     192                        }
     193                        const PointerType * ptrType = dynamic_cast<const PointerType *>( fieldType );
     194                        if ( nullptr == ptrType ) {
     195                                throwError( "First field is not a pointer type." );
     196                        }
     197                        assert( ptrType->base );
     198                        newType = dynamic_cast<StructInstType *>( ptrType->base );
     199                        if ( nullptr == newType ) {
     200                                throwError( "First field does not point to a structure type." );
     201                        }
     202                }
     203
     204                // Now we can look into copying it.
     205                newType = newType->clone();
     206                if ( ! oldType->parameters.empty() ) {
     207                        deleteAll( newType->parameters );
     208                        newType->parameters.clear();
     209                        cloneAll( oldType->parameters, newType->parameters );
     210                }
     211                return newType;
     212        }
     213
     214        /// Get the type-id type from a virtual type.
     215        StructInstType * getTypeIdType( const Type * type, const CodeLocation& errorLocation ) {
     216                const StructInstType * typeInst = dynamic_cast<const StructInstType *>( type );
     217                if ( nullptr == typeInst ) {
     218                        return nullptr;
     219                }
     220                StructInstType * tableInst =
     221                        followHeadPointerType( typeInst, "virtual_table", errorLocation );
     222                if ( nullptr == tableInst ) {
     223                        return nullptr;
     224                }
     225                StructInstType * typeIdInst =
     226                        followHeadPointerType( tableInst, "__cfavir_typeid", errorLocation );
     227                delete tableInst;
     228                return typeIdInst;
    220229        }
    221230
     
    228237                assert( pvt_decl );
    229238
    230                 const Type * vtable_type = getVirtualTableType( castExpr );
    231                 ObjectDecl * table = indexer.lookup( vtable_type );
    232                 if ( nullptr == table ) {
    233                         SemanticError( castLocation( castExpr ),
    234                                 "Could not find virtual table instance." );
     239                const Type * base_type = getBaseType( castExpr->result );
     240                if ( nullptr == base_type ) {
     241                        castError( castExpr, "Virtual cast target must be a pointer or reference type." );
     242                }
     243                const Type * type_id_type = getTypeIdType( base_type, castLocation( castExpr ) );
     244                if ( nullptr == type_id_type ) {
     245                        castError( castExpr, "Ill formed virtual cast target type." );
     246                }
     247                ObjectDecl * type_id = indexer.lookup( type_id_type );
     248                delete type_id_type;
     249                if ( nullptr == type_id ) {
     250                        castError( castExpr, "Virtual cast does not target a virtual type." );
    235251                }
    236252
    237253                Expression * result = new CastExpr(
    238254                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    239                                         new CastExpr(
    240                                                 new AddressExpr( new VariableExpr( table ) ),
    241                                                 pointer_to_pvt(1)
    242                                         ),
    243                                         new CastExpr(
    244                                                 castExpr->get_arg(),
    245                                                 pointer_to_pvt(2)
    246                                         )
     255                                cast_to_type_id( new AddressExpr( new VariableExpr( type_id ) ), 1 ),
     256                                cast_to_type_id( castExpr->get_arg(), 2 ),
    247257                        } ),
    248258                        castExpr->get_result()->clone()
     
    252262                castExpr->set_result( nullptr );
    253263                delete castExpr;
    254                 delete vtable_type;
    255264                return result;
    256265        }
  • src/Virtual/Tables.cc

    r56c8b86 rfe63ae6  
    1010// Created On       : Mon Aug 31 11:11:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Sep  3 14:56:00 2020
    13 // Update Count     : 0
     12// Last Modified On : Thr Apr  8 15:51:00 2021
     13// Update Count     : 1
    1414//
    1515
     
    2222namespace Virtual {
    2323
     24std::string typeIdType( std::string const & type_name ) {
     25        return "__cfatid_struct_" + type_name;
     26}
     27
     28std::string typeIdName( std::string const & type_name ) {
     29        return "__cfatid_" + type_name;
     30}
     31
     32static std::string typeIdTypeToInstance( std::string const & type_name ) {
     33        return typeIdName(type_name.substr(16));
     34}
     35
    2436std::string vtableTypeName( std::string const & name ) {
    2537        return name + "_vtable";
     38}
     39
     40std::string baseTypeName( std::string const & vtable_type_name ) {
     41        return vtable_type_name.substr(0, vtable_type_name.size() - 7);
    2642}
    2743
     
    8197                                inits.push_back(
    8298                                                new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
     99                        } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
     100                                std::string const & baseType = baseTypeName( vtableType->name );
     101                                std::string const & typeId = typeIdName( baseType );
     102                                inits.push_back( new SingleInit( new AddressExpr( new NameExpr( typeId ) ) ) );
    83103                        } else if ( std::string( "size" ) == field->name ) {
    84104                                inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
     
    147167}
    148168
     169ObjectDecl * makeTypeIdForward() {
     170        return nullptr;
    149171}
     172
     173Attribute * linkonce( const std::string & subsection ) {
     174        const std::string section = ".gnu.linkonce." + subsection;
     175        return new Attribute( "section", {
     176                new ConstantExpr( Constant::from_string( section ) ),
     177        } );
     178}
     179
     180ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
     181        assert( typeIdType );
     182        StructInstType * type = typeIdType->clone();
     183        type->tq.is_const = true;
     184        std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
     185        return new ObjectDecl(
     186                typeid_name,
     187                noStorageClasses,
     188                LinkageSpec::Cforall,
     189                /* bitfieldWidth */ nullptr,
     190                type,
     191                new ListInit( { new SingleInit(
     192                        new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
     193                        ) } ),
     194                { linkonce( typeid_name ) },
     195                noFuncSpecifiers
     196        );
     197}
     198
     199}
  • src/Virtual/Tables.h

    r56c8b86 rfe63ae6  
    1010// Created On       : Mon Aug 31 11:07:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Sep  1 14:29:00 2020
    13 // Update Count     : 0
     12// Last Modified On : Thr Apr  8 15:55:00 2021
     13// Update Count     : 1
    1414//
    1515
     
    2222namespace Virtual {
    2323
     24std::string typeIdType( std::string const & type_name );
     25std::string typeIdName( std::string const & type_name );
    2426std::string vtableTypeName( std::string const & type_name );
    2527std::string instanceName( std::string const & vtable_name );
     
    5052 */
    5153
     54ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType );
     55/* Build an instance of the type-id from the type of the type-id.
     56 * TODO: Should take the parent type. Currently locked to the exception_t.
     57 */
     58
    5259}
  • tests/exceptions/.expect/resume-threads.txt

    r56c8b86 rfe63ae6  
    66
    77catch-all
    8 
    9 throwing child exception
    10 inner parent match
    118
    129caught yin as yin
  • tests/exceptions/.expect/resume.txt

    r56c8b86 rfe63ae6  
    66
    77catch-all
    8 
    9 throwing child exception
    10 inner parent match
    118
    129caught yin as yin
  • tests/exceptions/.expect/terminate-threads.txt

    r56c8b86 rfe63ae6  
    55
    66catch-all
    7 
    8 throwing child exception
    9 inner parent match
    107
    118caught yin as yin
  • tests/exceptions/.expect/terminate.txt

    r56c8b86 rfe63ae6  
    55
    66catch-all
    7 
    8 throwing child exception
    9 inner parent match
    107
    118caught yin as yin
  • tests/exceptions/cancel/coroutine.cfa

    r56c8b86 rfe63ae6  
    44#include <exception.hfa>
    55
    6 TRIVIAL_EXCEPTION(internal_error);
     6EHM_EXCEPTION(internal_error)();
     7EHM_VIRTUAL_TABLE(internal_error, internal_vt);
    78
    89coroutine WillCancel {};
     
    1415void main(WillCancel & wc) {
    1516        printf("1");
    16         cancel_stack((internal_error){});
     17        cancel_stack((internal_error){&internal_vt});
    1718        printf("!");
    1819}
     
    2425                resume(cancel);
    2526                printf("4");
    26         } catchResume (CoroutineCancelled(WillCancel) * error) {
     27        } catchResume (SomeCoroutineCancelled * error) {
    2728                printf("2");
    2829                if ((virtual internal_error *)error->the_exception) {
  • tests/exceptions/cancel/thread.cfa

    r56c8b86 rfe63ae6  
    44#include <exception.hfa>
    55
    6 TRIVIAL_EXCEPTION(internal_error);
     6EHM_EXCEPTION(internal_error)();
     7EHM_VIRTUAL_TABLE(internal_error, internal_vt);
    78
    89thread WillCancel {};
     
    1415void main(WillCancel &) {
    1516        printf("1");
    16         cancel_stack((internal_error){});
     17        cancel_stack((internal_error){&internal_vt});
    1718        printf("!");
    1819}
     
    2526                join(cancel);
    2627                printf("4");
    27         } catchResume (ThreadCancelled(WillCancel) * error) {
     28        } catchResume (SomeThreadCancelled * error) {
    2829                printf("2");
    2930                if ((virtual internal_error *)error->the_exception) {
     
    4243                }
    4344                printf("4");
    44         } catchResume (ThreadCancelled(WillCancel) * error) {
     45        } catchResume (SomeThreadCancelled * error) {
    4546                printf("2");
    4647                if ((virtual internal_error *)error->the_exception) {
  • tests/exceptions/conditional.cfa

    r56c8b86 rfe63ae6  
    66#include <exception.hfa>
    77
    8 VTABLE_DECLARATION(num_error)(
    9         int (*code)(num_error *this);
     8EHM_EXCEPTION(num_error)(
     9        int num;
    1010);
    1111
    12 struct num_error {
    13         VTABLE_FIELD(num_error);
    14     char * msg;
    15     int num;
    16 };
    17 
    18 const char * num_error_msg(num_error * this) {
    19     if ( ! this->msg ) {
    20         static const char * base = "Num Error with code: X";
    21         this->msg = (char *)malloc(22);
    22         for (int i = 0 ; (this->msg[i] = base[i]) ; ++i);
    23     }
    24     this->msg[21] = '0' + this->num;
    25     return this->msg;
    26 }
    27 void ?{}(num_error & this, int num) {
    28         VTABLE_INIT(this, num_error);
    29     this.msg = 0;
    30     this.num = num;
    31 }
    32 void ?{}(num_error & this, num_error & other) {
    33     this.virtual_table = other.virtual_table;
    34     this.msg = 0;
    35     this.num = other.num;
    36 }
    37 void ^?{}(num_error & this) {
    38     if( this.msg ) free( this.msg );
    39 }
    40 int num_error_code( num_error * this ) {
    41     return this->num;
    42 }
    43 
    44 VTABLE_INSTANCE(num_error)(
    45         num_error_msg,
    46         num_error_code,
    47 );
     12EHM_VIRTUAL_TABLE(num_error, num_error_vt);
    4813
    4914void caught_num_error(int expect, num_error * actual) {
     
    5217
    5318int main(int argc, char * argv[]) {
    54         num_error exc = 2;
     19        num_error exc = {&num_error_vt, 2};
    5520
    5621        try {
    5722                throw exc;
    58         } catch (num_error * error ; 3 == error->virtual_table->code( error )) {
     23        } catch (num_error * error ; 3 == error->num ) {
    5924                caught_num_error(3, error);
    60         } catch (num_error * error ; 2 == error->virtual_table->code( error )) {
     25        } catch (num_error * error ; 2 == error->num ) {
    6126                caught_num_error(2, error);
    6227        }
     
    6429        try {
    6530                throwResume exc;
    66         } catchResume (num_error * error ; 3 == error->virtual_table->code( error )) {
     31        } catchResume (num_error * error ; 3 == error->num ) {
    6732                caught_num_error(3, error);
    68         } catchResume (num_error * error ; 2 == error->virtual_table->code( error )) {
     33        } catchResume (num_error * error ; 2 == error->num ) {
    6934                caught_num_error(2, error);
    7035        }
  • tests/exceptions/data-except.cfa

    r56c8b86 rfe63ae6  
    33#include <exception.hfa>
    44
    5 DATA_EXCEPTION(paired)(
     5EHM_EXCEPTION(paired)(
    66        int first;
    77        int second;
    88);
    99
    10 void ?{}(paired & this, int first, int second) {
    11         VTABLE_INIT(this, paired);
    12         this.first = first;
    13         this.second = second;
    14 }
     10EHM_VIRTUAL_TABLE(paired, paired_vt);
    1511
    16 const char * paired_msg(paired * this) {
    17         return "paired";
    18 }
    19 
    20 VTABLE_INSTANCE(paired)(paired_msg);
    21 
    22 void throwPaired(int first, int second) {
    23         paired exc = {first, second};
     12const char * virtual_msg(paired * this) {
     13        return this->virtual_table->msg(this);
    2414}
    2515
    2616int main(int argc, char * argv[]) {
    27         paired except = {3, 13};
     17        paired except = {&paired_vt, 3, 13};
    2818
    2919        try {
    3020                throw except;
    3121        } catch (paired * exc) {
    32                 printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second);
     22                printf("%s(%d, %d)\n", virtual_msg(exc), exc->first, exc->second);
    3323                ++exc->first;
    3424        }
    3525
    36         printf("%s(%d, %d)\n", paired_msg(&except), except.first, except.second);
     26        printf("%s(%d, %d)\n", virtual_msg(&except), except.first, except.second);
    3727
    3828        try {
    3929                throwResume except;
    4030        } catchResume (paired * exc) {
    41                 printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second);
     31                printf("%s(%d, %d)\n", virtual_msg(exc), exc->first, exc->second);
    4232                ++exc->first;
    4333        }
    4434
    45         printf("%s(%d, %d)\n", paired_msg(&except), except.first, except.second);
     35        printf("%s(%d, %d)\n", virtual_msg(&except), except.first, except.second);
    4636}
  • tests/exceptions/defaults.cfa

    r56c8b86 rfe63ae6  
    44#include <exception.hfa>
    55
    6 DATA_EXCEPTION(log_message)(
     6EHM_EXCEPTION(log_message)(
    77        char * msg;
    88);
    99
    10 void ?{}(log_message & this, char * msg) {
    11         VTABLE_INIT(this, log_message);
    12         this.msg = msg;
    13 }
    14 
    15 const char * get_log_message(log_message * this) {
     10_EHM_DEFINE_COPY(log_message, )
     11const char * msg(log_message * this) {
    1612        return this->msg;
    1713}
    18 
    19 VTABLE_INSTANCE(log_message)(get_log_message);
     14_EHM_VIRTUAL_TABLE(log_message, , log_vt);
    2015
    2116// Logging messages don't have to be handled.
     
    2823        // We can catch log:
    2924        try {
    30                 throwResume (log_message){"Should be printed.\n"};
     25                throwResume (log_message){&log_vt, "Should be printed.\n"};
    3126        } catchResume (log_message * this) {
    3227                printf("%s", this->virtual_table->msg(this));
    3328        }
    3429        // But we don't have to:
    35         throwResume (log_message){"Should not be printed.\n"};
     30        throwResume (log_message){&log_vt, "Should not be printed.\n"};
    3631}
    3732
    3833// I don't have a good use case for doing the same with termination.
    39 TRIVIAL_EXCEPTION(jump);
     34EHM_EXCEPTION(jump)();
    4035void defaultTerminationHandler(jump &) {
    4136        printf("jump default handler.\n");
    4237}
    4338
     39EHM_VIRTUAL_TABLE(jump, jump_vt);
     40
    4441void jump_test(void) {
    4542        try {
    46                 throw (jump){};
     43                throw (jump){&jump_vt};
    4744        } catch (jump * this) {
    4845                printf("jump catch handler.\n");
    4946        }
    50         throw (jump){};
     47        throw (jump){&jump_vt};
    5148}
    5249
    53 TRIVIAL_EXCEPTION(first);
    54 TRIVIAL_EXCEPTION(unhandled_exception);
     50EHM_EXCEPTION(first)();
     51EHM_VIRTUAL_TABLE(first, first_vt);
     52
     53EHM_EXCEPTION(unhandled_exception)();
     54EHM_VIRTUAL_TABLE(unhandled_exception, unhandled_vt);
    5555
    5656void unhandled_test(void) {
    5757        forall(T &, V & | is_exception(T, V))
    5858        void defaultTerminationHandler(T &) {
    59                 throw (unhandled_exception){};
     59                throw (unhandled_exception){&unhandled_vt};
    6060        }
    6161        void defaultTerminationHandler(unhandled_exception &) {
     
    6363        }
    6464        try {
    65                 throw (first){};
     65                throw (first){&first_vt};
    6666        } catch (unhandled_exception * t) {
    6767                printf("Catch unhandled_exception.\n");
     
    6969}
    7070
    71 TRIVIAL_EXCEPTION(second);
     71EHM_EXCEPTION(second)();
     72EHM_VIRTUAL_TABLE(second, second_vt);
    7273
    7374void cross_test(void) {
    7475        void defaultTerminationHandler(first &) {
    7576                printf("cross terminate default\n");
    76                 throw (second){};
     77                throw (second){&second_vt};
    7778        }
    7879        void defaultResumptionHandler(first &) {
    7980                printf("cross resume default\n");
    80                 throwResume (second){};
     81                throwResume (second){&second_vt};
    8182        }
    8283        try {
    8384                printf("cross terminate throw\n");
    84                 throw (first){};
     85                throw (first){&first_vt};
    8586        } catch (second *) {
    8687                printf("cross terminate catch\n");
     
    8889        try {
    8990                printf("cross resume throw\n");
    90                 throwResume (first){};
     91                throwResume (first){&first_vt};
    9192        } catchResume (second *) {
    9293                printf("cross resume catch\n");
  • tests/exceptions/finally.cfa

    r56c8b86 rfe63ae6  
    44#include "except-io.hfa"
    55
    6 TRIVIAL_EXCEPTION(myth);
     6EHM_EXCEPTION(myth)();
     7
     8EHM_VIRTUAL_TABLE(myth, myth_vt);
    79
    810int main(int argc, char * argv[]) {
    9         myth exc;
     11        myth exc = {&myth_vt};
    1012
    1113        try {
  • tests/exceptions/interact.cfa

    r56c8b86 rfe63ae6  
    44#include "except-io.hfa"
    55
    6 TRIVIAL_EXCEPTION(star);
    7 TRIVIAL_EXCEPTION(moon);
     6EHM_EXCEPTION(star)();
     7EHM_EXCEPTION(moon)();
     8
     9EHM_VIRTUAL_TABLE(star, star_vt);
     10EHM_VIRTUAL_TABLE(moon, moon_vt);
    811
    912int main(int argc, char * argv[]) {
    1013        // Resume falls back to terminate.
    1114        try {
    12                 throwResume (star){};
     15                throwResume (star){&star_vt};
    1316        } catch (star *) {
    1417                printf("caught as termination\n");
     
    1720        try {
    1821                loud_region a = "try block with resume throw";
    19                 throwResume (star){};
     22                throwResume (star){&star_vt};
    2023        } catch (star *) {
    2124                printf("caught as termination\n");
     
    2932        try {
    3033                try {
    31                         throw (star){};
     34                        throw (star){&star_vt};
    3235                } catchResume (star *) {
    3336                        printf("resume catch on terminate\n");
     
    4346        try {
    4447                try {
    45                         throwResume (star){};
     48                        throwResume (star){&star_vt};
    4649                } catch (star *) {
    4750                        printf("terminate catch on resume\n");
     
    5861                try {
    5962                        try {
    60                                 throw (star){};
     63                                throw (star){&star_vt};
    6164                        } catchResume (star *) {
    6265                                printf("inner resume catch (error)\n");
     
    7578                try {
    7679                        try {
    77                                 throwResume (star){};
     80                                throwResume (star){&star_vt};
    7881                        } catch (star *) {
    7982                                printf("inner termination catch\n");
     
    9497                                try {
    9598                                        printf("throwing resume moon\n");
    96                                         throwResume (moon){};
     99                                        throwResume (moon){&moon_vt};
    97100                                } catch (star *) {
    98101                                        printf("termination catch\n");
    99102                                }
    100103                                printf("throwing resume star\n");
    101                                 throwResume (star){};
     104                                throwResume (star){&star_vt};
    102105                        } catchResume (star *) {
    103106                                printf("resumption star catch\n");
     
    105108                } catchResume (moon *) {
    106109                        printf("resumption moon catch, will terminate\n");
    107                         throw (star){};
     110                        throw (star){&star_vt};
    108111                }
    109112        } catchResume (star *) {
  • tests/exceptions/polymorphic.cfa

    r56c8b86 rfe63ae6  
    33#include <exception.hfa>
    44
    5 FORALL_TRIVIAL_EXCEPTION(proxy, (T), (T));
    6 FORALL_TRIVIAL_INSTANCE(proxy, (U), (U))
     5EHM_FORALL_EXCEPTION(proxy, (T&), (T))();
    76
    8 const char * msg(proxy(int) * this) { return "proxy(int)"; }
    9 const char * msg(proxy(char) * this) { return "proxy(char)"; }
    10 POLY_VTABLE_INSTANCE(proxy, int)(msg);
    11 POLY_VTABLE_INSTANCE(proxy, char)(msg);
     7EHM_FORALL_VIRTUAL_TABLE(proxy, (int), proxy_int);
     8EHM_FORALL_VIRTUAL_TABLE(proxy, (char), proxy_char);
    129
    1310void proxy_test(void) {
     11        proxy(int) an_int = {&proxy_int};
     12        proxy(char) a_char = {&proxy_char};
     13
    1414    try {
    15                 throw (proxy(int)){};
     15                throw an_int;
    1616        } catch (proxy(int) *) {
    1717                printf("terminate catch\n");
     
    1919
    2020        try {
    21                 throwResume (proxy(char)){};
     21                throwResume a_char;
    2222        } catchResume (proxy(char) *) {
    2323                printf("resume catch\n");
     
    2525
    2626        try {
    27                 throw (proxy(char)){};
     27                throw a_char;
    2828        } catch (proxy(int) *) {
    2929                printf("caught proxy(int)\n");
     
    3333}
    3434
    35 FORALL_DATA_EXCEPTION(cell, (T), (T))(
     35EHM_FORALL_EXCEPTION(cell, (T), (T))(
    3636        T data;
    3737);
    3838
    39 FORALL_DATA_INSTANCE(cell, (T), (T))
    40 
    41 const char * msg(cell(int) * this) { return "cell(int)"; }
    42 const char * msg(cell(char) * this) { return "cell(char)"; }
    43 const char * msg(cell(bool) * this) { return "cell(bool)"; }
    44 POLY_VTABLE_INSTANCE(cell, int)(msg);
    45 POLY_VTABLE_INSTANCE(cell, char)(msg);
    46 POLY_VTABLE_INSTANCE(cell, bool)(msg);
     39EHM_FORALL_VIRTUAL_TABLE(cell, (int), int_cell);
     40EHM_FORALL_VIRTUAL_TABLE(cell, (char), char_cell);
     41EHM_FORALL_VIRTUAL_TABLE(cell, (bool), bool_cell);
    4742
    4843void cell_test(void) {
    4944        try {
    50                 cell(int) except;
    51                 except.data = -7;
     45                cell(int) except = {&int_cell, -7};
    5246                throw except;
    5347        } catch (cell(int) * error) {
     
    5650
    5751        try {
    58                 cell(bool) ball;
    59                 ball.data = false;
     52                cell(bool) ball = {&bool_cell, false};
    6053                throwResume ball;
    6154                printf("%i\n", ball.data);
  • tests/exceptions/resume.cfa

    r56c8b86 rfe63ae6  
    44#include "except-io.hfa"
    55
    6 TRIVIAL_EXCEPTION(yin);
    7 TRIVIAL_EXCEPTION(yang);
    8 TRIVIAL_EXCEPTION(zen);
    9 TRIVIAL_EXCEPTION(moment_of, zen);
     6EHM_EXCEPTION(yin)();
     7EHM_EXCEPTION(yang)();
     8EHM_EXCEPTION(zen)();
     9
     10EHM_VIRTUAL_TABLE(yin, yin_vt);
     11EHM_VIRTUAL_TABLE(yang, yang_vt);
     12EHM_VIRTUAL_TABLE(zen, zen_vt);
    1013
    1114void in_void(void);
    1215
    1316int main(int argc, char * argv[]) {
     17        yin a_yin = {&yin_vt};
     18        yang a_yang = {&yang_vt};
     19        zen a_zen = {&zen_vt};
     20
    1421        // The simple throw catchResume test.
    1522        try {
    1623                loud_exit a = "simple try clause";
    1724                printf("simple throw\n");
    18                 throwResume (zen){};
     25                throwResume a_zen;
    1926                printf("end of try clause\n");
    2027        } catchResume (zen * error) {
     
    2633        // Throw catch-all test.
    2734        try {
    28                 throwResume (zen){};
     35                throwResume a_zen;
    2936        } catchResume (exception_t * error) {
    3037                printf("catch-all\n");
    31         }
    32         printf("\n");
    33 
    34         // Catch a parent of the given exception.
    35         try {
    36                 printf("throwing child exception\n");
    37                 throwResume (moment_of){};
    38         } catchResume (zen *) {
    39                 printf("inner parent match\n");
    40         } catchResume (moment_of *) {
    41                 printf("outer exact match\n");
    4238        }
    4339        printf("\n");
     
    4642        try {
    4743                try {
    48                         throwResume (yin){};
     44                        throwResume a_yin;
    4945                } catchResume (zen *) {
    5046                        printf("caught yin as zen\n");
     
    6258                        loud_exit a = "rethrow inner try";
    6359                        printf("rethrow inner try\n");
    64                         throwResume (zen){};
     60                        throwResume a_zen;
    6561                } catchResume (zen *) {
    6662                        loud_exit a = "rethrowing catch clause";
     
    7773        try {
    7874                try {
    79                         throwResume (yin){};
     75                        throwResume a_yin;
    8076                } catchResume (yin *) {
    8177                        printf("caught yin, will throw yang\n");
    82                         throwResume (yang){};
     78                        throwResume a_yang;
    8379                } catchResume (yang *) {
    8480                        printf("caught exception from same try\n");
     
    9389                try {
    9490                        printf("throwing first exception\n");
    95                         throwResume (yin){};
     91                        throwResume a_yin;
    9692                } catchResume (yin *) {
    9793                        printf("caught first exception\n");
    9894                        try {
    9995                                printf("throwing second exception\n");
    100                                 throwResume (yang){};
     96                                throwResume a_yang;
    10197                        } catchResume (yang *) {
    10298                                printf("caught second exception\n");
     
    114110        try {
    115111                try {
    116                         throwResume (zen){};
    117                         throwResume (zen){};
     112                        throwResume a_zen;
     113                        throwResume a_zen;
    118114                } catchResume (zen *) {
    119115                        printf("inner catch\n");
    120116                }
    121                 throwResume (zen){};
     117                throwResume a_zen;
    122118        } catchResume (zen *) {
    123119                printf("outer catch\n");
     
    130126// Do a throw and rethrow in a void function.
    131127void in_void(void) {
     128    zen a_zen = {&zen_vt};
    132129        try {
    133130                try {
    134131                        printf("throw\n");
    135                         throwResume (zen){};
     132                        throwResume a_zen;
    136133                } catchResume (zen *) {
    137134                        printf("rethrow\n");
  • tests/exceptions/terminate.cfa

    r56c8b86 rfe63ae6  
    44#include "except-io.hfa"
    55
    6 TRIVIAL_EXCEPTION(yin);
    7 TRIVIAL_EXCEPTION(yang);
    8 TRIVIAL_EXCEPTION(zen);
    9 TRIVIAL_EXCEPTION(moment_of, zen);
     6EHM_EXCEPTION(yin)();
     7EHM_EXCEPTION(yang)();
     8EHM_EXCEPTION(zen)();
     9
     10EHM_VIRTUAL_TABLE(yin, yin_vt);
     11EHM_VIRTUAL_TABLE(yang, yang_vt);
     12EHM_VIRTUAL_TABLE(zen, zen_vt);
    1013
    1114void in_void(void);
    1215
    1316int main(int argc, char * argv[]) {
     17        yin a_yin = {&yin_vt};
     18        yang a_yang = {&yang_vt};
     19        zen a_zen = {&zen_vt};
     20
    1421        // The simple throw catch test.
    1522        try {
    1623                loud_exit a = "simple try clause";
    1724                printf("simple throw\n");
    18                 throw (zen){};
     25                throw a_zen;
    1926                printf("end of try clause\n");
    2027        } catch (zen * error) {
     
    2633        // Throw catch-all test.
    2734        try {
    28                 throw (zen){};
     35                throw a_zen;
    2936        } catch (exception_t * error) {
    3037                printf("catch-all\n");
    31         }
    32         printf("\n");
    33 
    34         // Catch a parent of the given exception.
    35         try {
    36                 printf("throwing child exception\n");
    37                 throw (moment_of){};
    38         } catch (zen *) {
    39                 printf("inner parent match\n");
    40         } catch (moment_of *) {
    41                 printf("outer exact match\n");
    4238        }
    4339        printf("\n");
     
    4642        try {
    4743                try {
    48                         throw (yin){};
     44                        throw a_yin;
    4945                } catch (zen *) {
    5046                        printf("caught yin as zen\n");
     
    6258                        loud_exit a = "rethrow inner try";
    6359                        printf("rethrow inner try\n");
    64                         throw (zen){};
     60                        throw a_zen;
    6561                } catch (zen *) {
    6662                        loud_exit a = "rethrowing catch clause";
     
    7773        try {
    7874                try {
    79                         throw (yin){};
     75                        throw a_yin;
    8076                } catch (yin *) {
    8177                        printf("caught yin, will throw yang\n");
    82                         throw (yang){};
     78                        throw a_yang;
    8379                } catch (yang *) {
    8480                        printf("caught exception from same try\n");
     
    9389                try {
    9490                        printf("throwing first exception\n");
    95                         throw (yin){};
     91                        throw a_yin;
    9692                } catch (yin *) {
    9793                        printf("caught first exception\n");
    9894                        try {
    9995                                printf("throwing second exception\n");
    100                                 throw (yang){};
     96                                throw a_yang;
    10197                        } catch (yang *) {
    10298                                printf("caught second exception\n");
     
    114110        try {
    115111                try {
    116                         throw (zen){};
    117                         throw (zen){};
     112                        throw a_zen;
     113                        throw a_zen;
    118114                } catch (zen *) {
    119115                        printf("inner catch\n");
    120116                }
    121                 throw (zen){};
     117                throw a_zen;
    122118        } catch (zen *) {
    123119                printf("outer catch\n");
     
    130126// Do a throw and rethrow in a void function.
    131127void in_void(void) {
     128        zen a_zen = {&zen_vt};
    132129        try {
    133130                try {
    134131                        printf("throw\n");
    135                         throw (zen){};
     132                        throw a_zen;
    136133                } catch (zen *) {
    137134                        printf("rethrow\n");
  • tests/exceptions/trash.cfa

    r56c8b86 rfe63ae6  
    33#include <exception.hfa>
    44
    5 TRIVIAL_EXCEPTION(yin);
    6 TRIVIAL_EXCEPTION(yang);
     5EHM_EXCEPTION(yin)();
     6EHM_EXCEPTION(yang)();
     7
     8EHM_VIRTUAL_TABLE(yin, yin_vt);
     9EHM_VIRTUAL_TABLE(yang, yang_vt);
    710
    811int main(int argc, char * argv[]) {
    912        try {
    1013                try {
    11                         throw (yin){};
     14                        throw (yin){&yin_vt};
    1215                } finally {
    1316                        try {
    14                                 throw (yang){};
     17                                throw (yang){&yang_vt};
    1518                        } catch (yin *) {
    1619                                printf("inner yin\n");
  • tests/exceptions/type-check.cfa

    r56c8b86 rfe63ae6  
    33#include <exception.hfa>
    44
    5 TRIVIAL_EXCEPTION(truth);
     5EHM_EXCEPTION(truth)();
    66
    77int main(int argc, char * argv[]) {
  • tests/exceptions/virtual-cast.cfa

    r56c8b86 rfe63ae6  
    1212#include <assert.h>
    1313
     14
     15
     16// Hand defined alpha virtual type:
     17struct __cfatid_struct_alpha {
     18        __cfa__parent_vtable const * parent;
     19};
     20
     21__attribute__(( section(".gnu.linkonce.__cfatid_alpha") ))
     22struct __cfatid_struct_alpha __cfatid_alpha = {
     23        (__cfa__parent_vtable *)0,
     24};
     25
    1426struct alpha_vtable {
    15         alpha_vtable const * const parent;
     27        struct __cfatid_struct_alpha const * const __cfavir_typeid;
    1628        char (*code)(void);
    1729};
     
    2739
    2840
     41// Hand defined beta virtual type:
     42struct __cfatid_struct_beta {
     43        __cfatid_struct_alpha const * parent;
     44};
     45
     46__attribute__(( section(".gnu.linkonce.__cfatid_beta") ))
     47struct __cfatid_struct_beta __cfatid_beta = {
     48        &__cfatid_alpha,
     49};
     50
    2951struct beta_vtable {
    30         alpha_vtable const * const parent;
     52        struct __cfatid_struct_beta const * const __cfavir_typeid;
    3153        char (*code)(void);
    3254};
     
    4264
    4365
     66// Hand defined gamma virtual type:
     67struct __cfatid_struct_gamma {
     68        __cfatid_struct_beta const * parent;
     69};
     70
     71__attribute__(( section(".gnu.linkonce.__cfatid_gamma") ))
     72struct __cfatid_struct_gamma __cfatid_gamma = {
     73        &__cfatid_beta,
     74};
     75
    4476struct gamma_vtable {
    45         beta_vtable const * const parent;
     77        struct __cfatid_struct_gamma const * const __cfavir_typeid;
    4678        char (*code)(void);
    4779};
     
    5789
    5890extern "C" {
    59         alpha_vtable _alpha_vtable_instance = { 0, ret_a };
    60         beta_vtable _beta_vtable_instance = { &_alpha_vtable_instance, ret_b };
    61         gamma_vtable _gamma_vtable_instance = { &_beta_vtable_instance, ret_g };
     91        alpha_vtable _alpha_vtable_instance = { &__cfatid_alpha, ret_a };
     92        beta_vtable _beta_vtable_instance = { &__cfatid_beta, ret_b };
     93        gamma_vtable _gamma_vtable_instance = { &__cfatid_gamma, ret_g };
    6294}
    6395
  • tests/exceptions/virtual-poly.cfa

    r56c8b86 rfe63ae6  
    88#include <assert.h>
    99
     10
     11struct __cfatid_struct_mono_base {
     12    __cfa__parent_vtable const * parent;
     13};
     14
     15__attribute__(( section(".gnu.linkonce.__cfatid_mono_base") ))
     16struct __cfatid_struct_mono_base __cfatid_mono_base = {
     17    (__cfa__parent_vtable *)0,
     18};
     19
    1020struct mono_base_vtable {
    11         mono_base_vtable const * const parent;
     21        __cfatid_struct_mono_base const * const __cfavir_typeid;
    1222};
    1323
     
    1727
    1828forall(T)
     29struct __cfatid_struct_mono_child {
     30    __cfatid_struct_mono_base const * parent;
     31};
     32
     33forall(T)
    1934struct mono_child_vtable {
    20         mono_base_vtable const * const parent;
     35        __cfatid_struct_mono_child(T) const * const __cfavir_typeid;
    2136};
    2237
     
    2641};
    2742
    28 mono_base_vtable _mono_base_vtable_instance @= { 0 };
     43__cfatid_struct_mono_child(int) __cfatid_mono_child @= {
     44        &__cfatid_mono_base,
     45};
     46
    2947mono_child_vtable(int) _mono_child_vtable_instance @= {
    30         &_mono_base_vtable_instance
     48        &__cfatid_mono_child,
    3149};
    3250
     
    3755}
    3856
     57
     58forall(U)
     59struct __cfatid_struct_poly_base {
     60    __cfa__parent_vtable const * parent;
     61};
     62
    3963forall(U)
    4064struct poly_base_vtable {
    41         poly_base_vtable(U) const * const parent;
     65        __cfatid_struct_poly_base(U) const * const __cfavir_typeid;
    4266};
    4367
     
    4872
    4973forall(V)
     74struct __cfatid_struct_poly_child {
     75    __cfatid_struct_poly_base(V) const * parent;
     76};
     77
     78forall(V)
    5079struct poly_child_vtable {
    51         poly_base_vtable(V) const * const parent;
     80        __cfatid_struct_poly_child(V) const * const __cfavir_typeid;
    5281};
    5382
     
    5786};
    5887
    59 poly_base_vtable(int) _poly_base_vtable_instance @= { 0 };
     88__cfatid_struct_poly_base(int) __cfatid_poly_base @= {
     89        (__cfa__parent_vtable *)0,
     90};
     91__cfatid_struct_poly_child(int) __cfatid_poly_child = {
     92    &__cfatid_poly_base,
     93};
    6094poly_child_vtable(int) _poly_child_vtable_instance @= {
    61         &_poly_base_vtable_instance
     95        &__cfatid_poly_child,
    6296};
    63 /* Resolver bug keeps me from adding these.
    64 poly_base_vtable(char) _poly_base_vtable_instance @= { 0 };
    65 poly_child_vtable(char) _poly_child_vtable_instance @= {
    66         &_poly_base_vtable_instance
    67 };
    68 */
    6997
    7098void poly_poly_test() {
     
    77105        mono_poly_test();
    78106        poly_poly_test();
    79         printf( "done\n" );                             // non-empty .expect file
     107        printf( "done\n" );
    80108}
  • tests/linking/exception-nothreads.cfa

    r56c8b86 rfe63ae6  
    1717#include <exception.hfa>
    1818
    19 TRIVIAL_EXCEPTION(ping);
     19EHM_EXCEPTION(ping)();
     20EHM_VIRTUAL_TABLE(ping, ping_vt);
    2021
    2122int main(void) {
    2223        try {
    23                 throwResume (ping){};
     24                throwResume (ping){&ping_vt};
    2425        } catchResume (ping *) {
    2526                printf("%s threads\n", threading_enabled() ? "with" : "no");
  • tests/linking/exception-withthreads.cfa

    r56c8b86 rfe63ae6  
    1818#include "../exceptions/with-threads.hfa"
    1919
    20 TRIVIAL_EXCEPTION(ping);
     20EHM_EXCEPTION(ping)();
     21EHM_VIRTUAL_TABLE(ping, ping_vt);
    2122
    2223int main(void) {
    2324        try {
    24                 throwResume (ping){};
     25                throwResume (ping){&ping_vt};
    2526        } catchResume (ping *) {
    2627                printf("%s threads\n", threading_enabled() ? "with" : "no");
  • tests/quasiKeyword.cfa

    r56c8b86 rfe63ae6  
    1414#include <exception.hfa>
    1515
    16 TRIVIAL_EXCEPTION( E );
     16EHM_EXCEPTION( E )();
    1717
    1818void catch( int i ) {}
Note: See TracChangeset for help on using the changeset viewer.