Changeset 0e4df2e


Ignore:
Timestamp:
May 22, 2020, 11:49:29 AM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
95cb63b
Parents:
2802824 (diff), 99fea48 (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' into relaxed_ready

Files:
3 added
24 edited

Legend:

Unmodified
Added
Removed
  • driver/cfa.cc

    r2802824 r0e4df2e  
    1010// Created On       : Tue Aug 20 13:44:49 2002
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jan 31 16:48:03 2020
    13 // Update Count     : 421
     12// Last Modified On : Mon May 18 13:26:26 2020
     13// Update Count     : 424
    1414//
    1515
     
    301301        } // for
    302302
    303         #ifdef __x86_64__
    304         args[nargs++] = "-mcx16";                                                       // allow double-wide CAA
    305         #endif // __x86_64__
    306 
    307303        #ifdef __DEBUG_H__
    308304        cerr << "args:";
     
    419415                args[nargs++] = "-lcfa";
    420416                args[nargs++] = "-Wl,--pop-state";
     417                #ifdef __x86_64__
     418                args[nargs++] = "-mcx16";                                               // allow double-wide CAS
     419                args[nargs++] = "-latomic";
     420                #endif // __x86_64__
    421421                args[nargs++] = "-pthread";
    422422                args[nargs++] = "-ldl";
  • libcfa/src/Makefile.am

    r2802824 r0e4df2e  
    1111## Created On       : Sun May 31 08:54:01 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Mon Mar 16 18:07:59 2020
    14 ## Update Count     : 242
     13## Last Modified On : Sun May 17 21:10:26 2020
     14## Update Count     : 243
    1515###############################################################################
    1616
     
    3939#----------------------------------------------------------------------------------------------------------------
    4040if BUILDLIB
    41 headers_nosrc = bitmanip.hfa math.hfa gmp.hfa time_t.hfa bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa containers/list.hfa
     41headers_nosrc = bitmanip.hfa math.hfa gmp.hfa time_t.hfa clock.hfa \
     42                bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa containers/list.hfa
    4243headers = fstream.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa time.hfa stdlib.hfa common.hfa \
    43           containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
     44                containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/stackLockFree.hfa containers/vector.hfa
    4445
    4546libsrc = startup.cfa interpose.cfa bits/debug.cfa assert.cfa exception.c virtual.c heap.cfa ${headers:.hfa=.cfa}
  • libcfa/src/Makefile.in

    r2802824 r0e4df2e  
    241241        containers/maybe.hfa containers/pair.hfa containers/result.hfa \
    242242        containers/vector.hfa bitmanip.hfa math.hfa gmp.hfa time_t.hfa \
    243         bits/align.hfa bits/containers.hfa bits/defs.hfa \
     243        clock.hfa bits/align.hfa bits/containers.hfa bits/defs.hfa \
    244244        bits/debug.hfa bits/locks.hfa containers/list.hfa \
    245245        concurrency/coroutine.hfa concurrency/thread.hfa \
     
    465465
    466466#----------------------------------------------------------------------------------------------------------------
    467 @BUILDLIB_TRUE@headers_nosrc = bitmanip.hfa math.hfa gmp.hfa time_t.hfa bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa containers/list.hfa
     467@BUILDLIB_TRUE@headers_nosrc = bitmanip.hfa math.hfa gmp.hfa time_t.hfa clock.hfa \
     468@BUILDLIB_TRUE@         bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa containers/list.hfa
     469
    468470@BUILDLIB_FALSE@headers =
    469471@BUILDLIB_TRUE@headers = fstream.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa time.hfa stdlib.hfa common.hfa \
    470 @BUILDLIB_TRUE@   containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
     472@BUILDLIB_TRUE@         containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
    471473
    472474@BUILDLIB_FALSE@libsrc =
  • libcfa/src/concurrency/io.cfa

    r2802824 r0e4df2e  
    124124
    125125                // Like head/tail but not seen by the kernel
    126                 volatile uint32_t alloc;
    127126                volatile uint32_t * ready;
    128127                uint32_t ready_cnt;
     
    141140                        struct {
    142141                                struct {
    143                                         volatile unsigned long long int val;
     142                                        volatile unsigned long long int rdy;
     143                                        volatile unsigned long long int csm;
     144                                        volatile unsigned long long int avl;
    144145                                        volatile unsigned long long int cnt;
    145                                         volatile unsigned long long int block;
    146146                                } submit_avg;
    147147                                struct {
     
    150150                                        volatile unsigned long long int block;
    151151                                } look_avg;
     152                                struct {
     153                                        volatile unsigned long long int val;
     154                                        volatile unsigned long long int cnt;
     155                                        volatile unsigned long long int block;
     156                                } alloc_avg;
    152157                        } stats;
    153158                #endif
     
    279284                sq.dropped = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.dropped);
    280285                sq.array   = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.array);
    281                 sq.alloc = *sq.tail;
     286
     287                {
     288                        const uint32_t num = *sq.num;
     289                        for( i; num ) {
     290                                sq.sqes[i].user_data = 0ul64;
     291                        }
     292                }
    282293
    283294                if( io_flags & CFA_CLUSTER_IO_POLLER_THREAD_SUBMITS ) {
     
    322333                // Initialize statistics
    323334                #if !defined(__CFA_NO_STATISTICS__)
    324                         this.io->submit_q.stats.submit_avg.val   = 0;
    325                         this.io->submit_q.stats.submit_avg.cnt   = 0;
    326                         this.io->submit_q.stats.submit_avg.block = 0;
     335                        this.io->submit_q.stats.submit_avg.rdy = 0;
     336                        this.io->submit_q.stats.submit_avg.csm = 0;
     337                        this.io->submit_q.stats.submit_avg.avl = 0;
     338                        this.io->submit_q.stats.submit_avg.cnt = 0;
    327339                        this.io->submit_q.stats.look_avg.val   = 0;
    328340                        this.io->submit_q.stats.look_avg.cnt   = 0;
    329341                        this.io->submit_q.stats.look_avg.block = 0;
     342                        this.io->submit_q.stats.alloc_avg.val   = 0;
     343                        this.io->submit_q.stats.alloc_avg.cnt   = 0;
     344                        this.io->submit_q.stats.alloc_avg.block = 0;
    330345                        this.io->completion_q.stats.completed_avg.val = 0;
    331346                        this.io->completion_q.stats.completed_avg.slow_cnt = 0;
     
    384399                                        this.ready_queue.head = 1p;
    385400                                        thrd.next = 0p;
     401                                        __cfaabi_dbg_debug_do( thrd.unpark_stale = true );
    386402
    387403                                        // Fixup the thread state
     
    426442                        if(this.print_stats) {
    427443                                with(this.io->submit_q.stats, this.io->completion_q.stats) {
     444                                        double avgrdy = ((double)submit_avg.rdy) / submit_avg.cnt;
     445                                        double avgcsm = ((double)submit_avg.csm) / submit_avg.cnt;
     446                                        double avgavl = ((double)submit_avg.avl) / submit_avg.cnt;
     447
    428448                                        double lavgv = 0;
    429449                                        double lavgb = 0;
     
    433453                                        }
    434454
     455                                        double aavgv = 0;
     456                                        double aavgb = 0;
     457                                        if(alloc_avg.cnt != 0) {
     458                                                aavgv = ((double)alloc_avg.val  ) / alloc_avg.cnt;
     459                                                aavgb = ((double)alloc_avg.block) / alloc_avg.cnt;
     460                                        }
     461
    435462                                        __cfaabi_bits_print_safe( STDOUT_FILENO,
    436463                                                "----- I/O uRing Stats -----\n"
    437464                                                "- total submit calls     : %'15llu\n"
    438                                                 "- avg submit             : %'18.2lf\n"
    439                                                 "- pre-submit block %%     : %'18.2lf\n"
     465                                                "- avg ready entries      : %'18.2lf\n"
     466                                                "- avg submitted entries  : %'18.2lf\n"
     467                                                "- avg available entries  : %'18.2lf\n"
    440468                                                "- total ready search     : %'15llu\n"
    441469                                                "- avg ready search len   : %'18.2lf\n"
    442470                                                "- avg ready search block : %'18.2lf\n"
     471                                                "- total alloc search     : %'15llu\n"
     472                                                "- avg alloc search len   : %'18.2lf\n"
     473                                                "- avg alloc search block : %'18.2lf\n"
    443474                                                "- total wait calls       : %'15llu   (%'llu slow, %'llu fast)\n"
    444475                                                "- avg completion/wait    : %'18.2lf\n",
    445476                                                submit_avg.cnt,
    446                                                 ((double)submit_avg.val) / submit_avg.cnt,
    447                                                 (100.0 * submit_avg.block) / submit_avg.cnt,
     477                                                avgrdy,
     478                                                avgcsm,
     479                                                avgavl,
    448480                                                look_avg.cnt,
    449481                                                lavgv,
    450482                                                lavgb,
     483                                                alloc_avg.cnt,
     484                                                aavgv,
     485                                                aavgb,
    451486                                                completed_avg.slow_cnt + completed_avg.fast_cnt,
    452487                                                completed_avg.slow_cnt,  completed_avg.fast_cnt,
     
    494529
    495530                        // If the poller thread also submits, then we need to aggregate the submissions which are ready
    496                         uint32_t * tail = ring.submit_q.tail;
     531                        uint32_t tail = *ring.submit_q.tail;
    497532                        const uint32_t mask = *ring.submit_q.mask;
    498533
     
    506541
    507542                                // If we got a real submission, append it to the list
    508                                 ring.submit_q.array[ ((*tail) + to_submit) & mask ] = idx & mask;
     543                                ring.submit_q.array[ (tail + to_submit) & mask ] = idx & mask;
    509544                                to_submit++;
    510545                        }
    511546
    512547                        // Increment the tail based on how many we are ready to submit
    513                         __atomic_fetch_add(tail, to_submit, __ATOMIC_SEQ_CST);
    514 
    515                         // update statistics
    516                         #if !defined(__CFA_NO_STATISTICS__)
    517                                 ring.submit_q.stats.submit_avg.val += to_submit;
    518                                 ring.submit_q.stats.submit_avg.cnt += 1;
    519                         #endif
    520                 }
    521 
     548                        __atomic_fetch_add(ring.submit_q.tail, to_submit, __ATOMIC_SEQ_CST);
     549                }
     550
     551                const uint32_t smask = *ring.submit_q.mask;
     552                uint32_t shead = *ring.submit_q.head;
    522553                int ret = syscall( __NR_io_uring_enter, ring.fd, to_submit, waitcnt, IORING_ENTER_GETEVENTS, mask, _NSIG / 8);
    523554                if( ret < 0 ) {
     
    531562                }
    532563
     564                verify( (shead + ret) == *ring.submit_q.head );
     565
     566                // Release the consumed SQEs
     567                for( i; ret ) {
     568                        uint32_t idx = ring.submit_q.array[ (i + shead) & smask ];
     569                        ring.submit_q.sqes[ idx ].user_data = 0;
     570                }
     571
     572                uint32_t avail = 0;
     573                uint32_t sqe_num = *ring.submit_q.num;
     574                for(i; sqe_num) {
     575                        if( ring.submit_q.sqes[ i ].user_data == 0 ) avail++;
     576                }
     577
     578                // update statistics
     579                #if !defined(__CFA_NO_STATISTICS__)
     580                        ring.submit_q.stats.submit_avg.rdy += to_submit;
     581                        ring.submit_q.stats.submit_avg.csm += ret;
     582                        ring.submit_q.stats.submit_avg.avl += avail;
     583                        ring.submit_q.stats.submit_avg.cnt += 1;
     584                #endif
     585
    533586                // Drain the queue
    534587                unsigned head = *ring.completion_q.head;
    535                 unsigned tail = __atomic_load_n(ring.completion_q.tail, __ATOMIC_ACQUIRE);
     588                unsigned tail = *ring.completion_q.tail;
     589                const uint32_t mask = *ring.completion_q.mask;
     590
     591                // Memory barrier
     592                __atomic_thread_fence( __ATOMIC_SEQ_CST );
    536593
    537594                // Nothing was new return 0
     
    542599                uint32_t count = tail - head;
    543600                for(i; count) {
    544                         unsigned idx = (head + i) & (*ring.completion_q.mask);
     601                        unsigned idx = (head + i) & mask;
    545602                        struct io_uring_cqe & cqe = ring.completion_q.cqes[idx];
    546603
     
    556613
    557614                // Allow new submissions to happen
    558                 V(ring.submit, count);
     615                // V(ring.submit, count);
    559616
    560617                // Mark to the kernel that the cqe has been seen
    561618                // Ensure that the kernel only sees the new value of the head index after the CQEs have been read.
     619                __atomic_thread_fence( __ATOMIC_SEQ_CST );
    562620                __atomic_fetch_add( ring.completion_q.head, count, __ATOMIC_RELAXED );
    563621
     
    710768//
    711769
    712         static inline [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring ) {
    713                 // Wait for a spot to be available
    714                 __attribute__((unused)) bool blocked = P(ring.submit);
    715                 #if !defined(__CFA_NO_STATISTICS__)
    716                         __atomic_fetch_add( &ring.submit_q.stats.submit_avg.block, blocked ? 1ul64 : 0ul64, __ATOMIC_RELAXED );
    717                 #endif
    718 
    719                 // Allocate the sqe
    720                 uint32_t idx = __atomic_fetch_add(&ring.submit_q.alloc, 1ul32, __ATOMIC_SEQ_CST);
    721 
    722                 // Mask the idx now to allow make everything easier to check
    723                 idx &= *ring.submit_q.mask;
    724 
    725                 // Return the sqe
    726                 return [&ring.submit_q.sqes[ idx ], idx];
     770        static inline [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring, uint64_t data ) {
     771                verify( data != 0 );
     772
     773                // Prepare the data we need
     774                __attribute((unused)) int len   = 0;
     775                __attribute((unused)) int block = 0;
     776                uint32_t cnt = *ring.submit_q.num;
     777                uint32_t mask = *ring.submit_q.mask;
     778                uint32_t off = __tls_rand();
     779
     780                // Loop around looking for an available spot
     781                LOOKING: for() {
     782                        // Look through the list starting at some offset
     783                        for(i; cnt) {
     784                                uint64_t expected = 0;
     785                                uint32_t idx = (i + off) & mask;
     786                                struct io_uring_sqe * sqe = &ring.submit_q.sqes[idx];
     787                                volatile uint64_t * udata = &sqe->user_data;
     788
     789                                if( *udata == expected &&
     790                                        __atomic_compare_exchange_n( udata, &expected, data, true, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED ) )
     791                                {
     792                                        // update statistics
     793                                        #if !defined(__CFA_NO_STATISTICS__)
     794                                                __atomic_fetch_add( &ring.submit_q.stats.alloc_avg.val,   len,   __ATOMIC_RELAXED );
     795                                                __atomic_fetch_add( &ring.submit_q.stats.alloc_avg.block, block, __ATOMIC_RELAXED );
     796                                                __atomic_fetch_add( &ring.submit_q.stats.alloc_avg.cnt,   1,     __ATOMIC_RELAXED );
     797                                        #endif
     798
     799                                        // Success return the data
     800                                        return [sqe, idx];
     801                                }
     802                                verify(expected != data);
     803
     804                                len ++;
     805                        }
     806
     807                        block++;
     808                        yield();
     809                }
    727810        }
    728811
     
    742825                        __attribute((unused)) int len   = 0;
    743826                        __attribute((unused)) int block = 0;
    744                         uint32_t expected = -1ul32;
    745827                        uint32_t ready_mask = ring.submit_q.ready_cnt - 1;
    746828                        uint32_t off = __tls_rand();
     
    748830                                for(i; ring.submit_q.ready_cnt) {
    749831                                        uint32_t ii = (i + off) & ready_mask;
     832                                        uint32_t expected = -1ul32;
    750833                                        if( __atomic_compare_exchange_n( &ring.submit_q.ready[ii], &expected, idx, true, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED ) ) {
    751834                                                break LOOKING;
    752835                                        }
     836                                        verify(expected != idx);
    753837
    754838                                        len ++;
     
    792876                        // update statistics
    793877                        #if !defined(__CFA_NO_STATISTICS__)
    794                                 ring.submit_q.stats.submit_avg.val += 1;
     878                                ring.submit_q.stats.submit_avg.csm += 1;
    795879                                ring.submit_q.stats.submit_avg.cnt += 1;
    796880                        #endif
     
    831915
    832916        #define __submit_prelude \
    833                 struct __io_data & ring = *active_cluster()->io; \
     917                io_user_data data = { 0, active_thread() }; \
     918                struct __io_data & ring = *data.thrd->curr_cluster->io; \
    834919                struct io_uring_sqe * sqe; \
    835920                uint32_t idx; \
    836                 [sqe, idx] = __submit_alloc( ring );
     921                [sqe, idx] = __submit_alloc( ring, (uint64_t)&data );
    837922
    838923        #define __submit_wait \
    839                 io_user_data data = { 0, active_thread() }; \
    840924                /*__cfaabi_bits_print_safe( STDERR_FILENO, "Preparing user data %p for %p\n", &data, data.thrd );*/ \
    841                 sqe->user_data = (uint64_t)&data; \
     925                verify( sqe->user_data == (uint64_t)&data ); \
    842926                __submit( ring, idx ); \
    843927                park( __cfaabi_dbg_ctx ); \
  • libcfa/src/concurrency/kernel.cfa

    r2802824 r0e4df2e  
    648648
    649649        // record activity
     650        __cfaabi_dbg_debug_do( char * old_caller = thrd->unpark_caller; )
    650651        __cfaabi_dbg_record_thrd( *thrd, false, caller );
    651652
  • libcfa/src/containers/list.hfa

    r2802824 r0e4df2e  
    301301                $prev_link(list_pos) = (Telem*) 0p;
    302302        }
     303
     304        static inline bool ?`is_empty(dlist(Tnode, Telem) &list) {
     305                assert( &list != 0p );
     306                $dlinks(Telem) *listLinks = & list.$links;
     307                if (listLinks->next.is_terminator) {
     308                        assert(listLinks->prev.is_terminator);
     309                        assert(listLinks->next.terminator);
     310                        assert(listLinks->prev.terminator);
     311                        return true;
     312                } else {
     313                        assert(!listLinks->prev.is_terminator);
     314                        assert(listLinks->next.elem);
     315                        assert(listLinks->prev.elem);
     316                        return false;
     317                }
     318        }
     319
     320        static inline Telem & pop_first(dlist(Tnode, Telem) &list) {
     321                assert( &list != 0p );
     322                assert( !list`is_empty );
     323                $dlinks(Telem) *listLinks = & list.$links;
     324                Telem & first = *listLinks->next.elem;
     325                Tnode & list_pos_first  = $tempcv_e2n( first );
     326                remove(list_pos_first);
     327                return first;
     328        }
     329
     330        static inline Telem & pop_last(dlist(Tnode, Telem) &list) {
     331                assert( &list != 0p );
     332                assert( !list`is_empty );
     333                $dlinks(Telem) *listLinks = & list.$links;
     334                Telem & last = *listLinks->prev.elem;
     335                Tnode & list_pos_last  = $tempcv_e2n( last );
     336                remove(list_pos_last);
     337                return last;
     338        }
     339
    303340}
    304341
  • libcfa/src/exception.c

    r2802824 r0e4df2e  
    1010// Created On       : Mon Jun 26 15:13:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr 14 12:01:00 2020
    13 // Update Count     : 18
     12// Last Modified On : Thr May 21 12:18:00 2020
     13// Update Count     : 20
    1414//
    1515
     
    8080}
    8181
    82 void __cfaehm_throw_resume(exception_t * except) {
     82void __cfaehm_throw_resume(exception_t * except, void (*defaultHandler)(exception_t *)) {
    8383        struct exception_context_t * context = this_exception_context();
    8484
     
    9696        }
    9797
     98        // No handler found, fall back to the default operation.
    9899        __cfadbg_print_safe(exception, "Unhandled exception\n");
    99 
    100         // Fall back to termination:
    101         __cfaehm_throw_terminate(except);
    102         // TODO: Default handler for resumption.
     100        defaultHandler(except);
    103101}
    104102
     
    223221
    224222// Cancel the current stack, prefroming approprate clean-up and messaging.
    225 static __attribute__((noreturn)) void __cfaehm_cancel_stack(
    226                 exception_t * exception ) {
     223void __cfaehm_cancel_stack( exception_t * exception ) {
    227224        // TODO: Detect current stack and pick a particular stop-function.
    228225        _Unwind_Reason_Code ret;
     
    240237}
    241238
     239static void __cfaehm_cleanup_default( exception_t ** except ) {
     240        __cfaehm_delete_exception( *except );
     241        *except = NULL;
     242}
     243
    242244// The exception that is being thrown must already be stored.
    243 static __attribute__((noreturn)) void __cfaehm_begin_unwind(void) {
    244         if ( ! this_exception_context()->current_exception ) {
     245static void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) {
     246        struct exception_context_t * context = this_exception_context();
     247        struct _Unwind_Exception * storage = &this_exception_storage;
     248        if ( NULL == context->current_exception ) {
    245249                printf("UNWIND ERROR missing exception in begin unwind\n");
    246250                abort();
     
    248252
    249253        // Call stdlibc to raise the exception
    250         _Unwind_Reason_Code ret = _Unwind_RaiseException( &this_exception_storage );
     254        __cfadbg_print_safe(exception, "Begin unwinding (storage &p, context %p)\n", storage, context);
     255        _Unwind_Reason_Code ret = _Unwind_RaiseException( storage );
    251256
    252257        // If we reach here it means something happened. For resumption to work we need to find a way
     
    257262        // the whole stack.
    258263
     264        // We did not simply reach the end of the stack without finding a handler. This is an error.
     265        if ( ret != _URC_END_OF_STACK ) {
     266                printf("UNWIND ERROR %d after raise exception\n", ret);
     267                abort();
     268        }
     269
    259270        // No handler found, go to the default operation.
    260         // Currently this will always be a cancellation.
    261         if ( ret == _URC_END_OF_STACK ) {
    262                 __cfadbg_print_safe(exception, "Uncaught exception %p\n", &this_exception_storage);
    263 
    264                 __cfaehm_cancel_stack(this_exception_context()->current_exception);
    265         }
    266 
    267         // We did not simply reach the end of the stack without finding a handler. This is an error.
    268         printf("UNWIND ERROR %d after raise exception\n", ret);
     271        __cfadbg_print_safe(exception, "Uncaught exception %p\n", storage);
     272
     273        __attribute__((cleanup(__cfaehm_cleanup_default)))
     274        exception_t * exception = context->current_exception;
     275        defaultHandler( exception );
     276}
     277
     278void __cfaehm_throw_terminate( exception_t * val, void (*defaultHandler)(exception_t *) ) {
     279        __cfadbg_print_safe(exception, "Throwing termination exception\n");
     280
     281        __cfaehm_allocate_exception( val );
     282        __cfaehm_begin_unwind( defaultHandler );
     283}
     284
     285static __attribute__((noreturn)) void __cfaehm_rethrow_adapter( exception_t * except ) {
     286        // TODO: Print some error message.
     287        (void)except;
    269288        abort();
    270 }
    271 
    272 void __cfaehm_throw_terminate( exception_t * val ) {
    273         __cfadbg_print_safe(exception, "Throwing termination exception\n");
    274 
    275         __cfaehm_allocate_exception( val );
    276         __cfaehm_begin_unwind();
    277289}
    278290
     
    280292        __cfadbg_print_safe(exception, "Rethrowing termination exception\n");
    281293
    282         __cfaehm_begin_unwind();
     294        __cfaehm_begin_unwind( __cfaehm_rethrow_adapter );
     295        abort();
    283296}
    284297
  • libcfa/src/exception.h

    r2802824 r0e4df2e  
    1010// Created On       : Mon Jun 26 15:11:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Mar 27 10:16:00 2020
    13 // Update Count     : 9
     12// Last Modified On : Tue May 19 14:17:00 2020
     13// Update Count     : 10
    1414//
    1515
     
    3838
    3939
     40void __cfaehm_cancel_stack(exception_t * except) __attribute__((noreturn));
     41
    4042// Used in throw statement translation.
    41 void __cfaehm_throw_terminate(exception_t * except) __attribute__((noreturn));
     43void __cfaehm_throw_terminate(exception_t * except, void (*)(exception_t *));
    4244void __cfaehm_rethrow_terminate() __attribute__((noreturn));
    43 void __cfaehm_throw_resume(exception_t * except);
     45void __cfaehm_throw_resume(exception_t * except, void (*)(exception_t *));
    4446
    4547// Function catches termination exceptions.
     
    7072#ifdef __cforall
    7173}
     74
     75// Not all the built-ins can be expressed in C. These can't be
     76// implemented in the .c file either so they all have to be inline.
     77
     78trait is_exception(dtype T) {
     79        /* The first field must be a pointer to a virtual table.
     80         * That virtual table must be a decendent of the base exception virtual tab$
     81         */
     82        void mark_exception(T *);
     83        // This is never used and should be a no-op.
     84};
     85
     86trait is_termination_exception(dtype T | is_exception(T)) {
     87        void defaultTerminationHandler(T &);
     88};
     89
     90trait is_resumption_exception(dtype T | is_exception(T)) {
     91        void defaultResumptionHandler(T &);
     92};
     93
     94forall(dtype T | is_termination_exception(T))
     95static inline void $throw(T & except) {
     96        __cfaehm_throw_terminate(
     97                (exception_t *)&except,
     98                (void(*)(exception_t *))defaultTerminationHandler
     99        );
     100}
     101
     102forall(dtype T | is_resumption_exception(T))
     103static inline void $throwResume(T & except) {
     104        __cfaehm_throw_resume(
     105                (exception_t *)&except,
     106                (void(*)(exception_t *))defaultResumptionHandler
     107        );
     108}
     109
     110forall(dtype T | is_exception(T))
     111static inline void cancel_stack(T & except) __attribute__((noreturn)) {
     112        __cfaehm_cancel_stack( (exception_t *)&except );
     113}
     114
     115forall(dtype T | is_exception(T))
     116static inline void defaultTerminationHandler(T & except) {
     117        return cancel_stack( except );
     118}
     119
     120forall(dtype T | is_exception(T))
     121static inline void defaultResumptionHandler(T & except) {
     122        throw except;
     123}
     124
    72125#endif
  • libcfa/src/exception.hfa

    r2802824 r0e4df2e  
    1010// Created On       : Thu Apr  7 10:25:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Apr  7 10:25:00 2020
    13 // Update Count     : 0
     12// Last Modified On : Tue May 19 14:17:00 2020
     13// Update Count     : 2
    1414//
    1515
     
    6969#define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
    7070        struct exception_name; \
     71        void mark_exception(exception_name *); \
    7172        VTABLE_TYPE(exception_name); \
    7273        extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \
     
    8586#define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__)
    8687#define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
     88        void mark_exception(exception_name *) {} \
    8789        void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \
    8890                *this = *other; \
  • libcfa/src/executor.cfa

    r2802824 r0e4df2e  
    44// buffer.
    55
    6 #include <bits/containers.hfa>
     6#include <containers/list.hfa>
    77#include <thread.hfa>
    88#include <stdio.h>
    99
    10 forall( dtype T )
    11 monitor Buffer {                                        // unbounded buffer
    12     __queue_t( T ) queue;                               // unbounded list of work requests
    13     condition delay;
    14 }; // Buffer
    15 forall( dtype T | is_node(T) ) {
    16     void insert( Buffer( T ) & mutex buf, T * elem ) with(buf) {
    17         append( queue, elem );                          // insert element into buffer
    18         signal( delay );                                // restart
    19     } // insert
    20 
    21     T * remove( Buffer( T ) & mutex buf ) with(buf) {
    22         if ( queue.head != 0 ) wait( delay );                   // no request to process ? => wait
    23 //      return pop_head( queue );
    24     } // remove
    25 } // distribution
    26 
    2710struct WRequest {                                       // client request, no return
    2811    void (* action)( void );
    29     WRequest * next;                                    // intrusive queue field
     12    DLISTED_MGD_IMPL_IN(WRequest)
    3013}; // WRequest
     14DLISTED_MGD_IMPL_OUT(WRequest)
    3115
    32 WRequest *& get_next( WRequest & this ) { return this.next; }
    33 void ?{}( WRequest & req ) with(req) { action = 0; next = 0; }
    34 void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; next = 0; }
     16void ?{}( WRequest & req ) with(req) { action = 0; }
     17void ?{}( WRequest & req, void (* action)( void ) ) with(req) { req.action = action; }
    3518bool stop( WRequest & req ) { return req.action == 0; }
    3619void doit( WRequest & req ) { req.action(); }
     20
     21monitor WRBuffer {                                      // unbounded buffer
     22    dlist( WRequest, WRequest ) queue;                  // unbounded list of work requests
     23    condition delay;
     24}; // WRBuffer
     25
     26void insert( WRBuffer & mutex buf, WRequest * elem ) with(buf) {
     27    insert_last( queue, *elem );                        // insert element into buffer
     28    signal( delay );                                    // restart
     29} // insert
     30
     31WRequest * remove( WRBuffer & mutex buf ) with(buf) {
     32    if ( queue`is_empty ) wait( delay );                // no request to process ? => wait
     33    return & pop_first( queue );
     34} // remove
    3735
    3836// Each worker has its own work buffer to reduce contention between client and server. Hence, work requests arrive and
     
    4038
    4139thread Worker {
    42     Buffer( WRequest ) * requests;
     40    WRBuffer * requests;
    4341    unsigned int start, range;
    4442}; // Worker
     
    5452} // Worker::main
    5553
    56 void ?{}( Worker & worker, cluster * wc, Buffer( WRequest ) * requests, unsigned int start, unsigned int range ) {
     54void ?{}( Worker & worker, cluster * wc, WRBuffer * requests, unsigned int start, unsigned int range ) {
    5755    (*get_thread(worker)){ *wc };                       // create on given cluster
    5856    worker.[requests, start, range] = [requests, start, range];
     
    6260    cluster * cluster;                                  // if workers execute on separate cluster
    6361    processor ** processors;                            // array of virtual processors adding parallelism for workers
    64     Buffer( WRequest ) * requests;                      // list of work requests
     62    WRBuffer * requests;                                // list of work requests
    6563    Worker ** workers;                                  // array of workers executing work requests
    6664    unsigned int nprocessors, nworkers, nmailboxes;     // number of mailboxes/workers/processor tasks
     
    7977    cluster = sepClus ? new( "Executor" ) : active_cluster();
    8078    processors = (processor **)anew( nprocessors );
    81     requests = anew( nmailboxes );
     79    requests = (WRBuffer *)anew( nmailboxes );
    8280    workers = (Worker **)anew( nworkers );
    8381
     
    141139        for ( i; 3000 ) {
    142140            send( exector, workie );
    143             if ( i % 100 ) yield();
     141            if ( i % 100 == 0 ) {
     142//              fprintf( stderr, "%d\n", i );
     143                yield();
     144            }
    144145        } // for
    145146    }
  • libcfa/src/heap.cfa

    r2802824 r0e4df2e  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May  6 17:29:26 2020
    13 // Update Count     : 727
     12// Last Modified On : Sun May 17 20:58:17 2020
     13// Update Count     : 762
    1414//
    1515
     
    128128#define LOCKFREE 1
    129129#define BUCKETLOCK SPINLOCK
    130 #if BUCKETLOCK == LOCKFREE
    131 #include <uStackLF.h>
     130#if BUCKETLOCK == SPINLOCK
     131#elif BUCKETLOCK == LOCKFREE
     132#include <stackLockFree.hfa>
     133#else
     134        #error undefined lock type for bucket lock
    132135#endif // LOCKFREE
    133136
     
    137140
    138141struct HeapManager {
    139 //      struct FreeHeader;                                                                      // forward declaration
    140 
    141142        struct Storage {
    142143                struct Header {                                                                 // header
     
    146147                                                struct {                                                // 4-byte word => 8-byte header, 8-byte word => 16-byte header
    147148                                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    148                                                         uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     149                                                        uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    149150                                                        #endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
    150151
    151152                                                        union {
    152 //                                                              FreeHeader * home;              // allocated block points back to home locations (must overlay alignment)
     153                                                                // FreeHeader * home;           // allocated block points back to home locations (must overlay alignment)
    153154                                                                // 2nd low-order bit => zero filled
    154155                                                                void * home;                    // allocated block points back to home locations (must overlay alignment)
    155156                                                                size_t blockSize;               // size for munmap (must overlay alignment)
    156                                                                 #if BUCKLOCK == SPINLOCK
     157                                                                #if BUCKETLOCK == SPINLOCK
    157158                                                                Storage * next;                 // freed block points next freed block of same size
    158159                                                                #endif // SPINLOCK
    159160                                                        };
     161                                                        size_t size;                            // allocation size in bytes
    160162
    161163                                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    162                                                         uint32_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
     164                                                        uint64_t padding;                       // unused, force home/blocksize to overlay alignment in fake header
    163165                                                        #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4
    164166                                                };
    165                                                 // future code
    166                                                 #if BUCKLOCK == LOCKFREE
    167                                                 Stack<Storage>::Link next;              // freed block points next freed block of same size (double-wide)
     167                                                #if BUCKETLOCK == LOCKFREE
     168                                                Link(Storage) next;                             // freed block points next freed block of same size (double-wide)
    168169                                                #endif // LOCKFREE
    169170                                        };
    170171                                } real; // RealHeader
     172
    171173                                struct FakeHeader {
    172174                                        #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    173                                         // 1st low-order bit => fake header & alignment
    174                                         uint32_t alignment;
     175                                        uint32_t alignment;                                     // 1st low-order bit => fake header & alignment
    175176                                        #endif // __ORDER_LITTLE_ENDIAN__
    176177
     
    182183                                } fake; // FakeHeader
    183184                        } kind; // Kind
    184                         size_t size;                                                            // allocation size in bytes
    185185                } header; // Header
    186186                char pad[libAlign() - sizeof( Header )];
     
    191191
    192192        struct FreeHeader {
    193                 #if BUCKLOCK == SPINLOCK
     193                #if BUCKETLOCK == SPINLOCK
    194194                __spinlock_t lock;                                                              // must be first field for alignment
    195195                Storage * freeList;
    196                 #elif BUCKLOCK == LOCKFREE
    197                 // future code
    198                 StackLF<Storage> freeList;
    199196                #else
    200                         #error undefined lock type for bucket lock
    201                 #endif // SPINLOCK
     197                StackLF(Storage) freeList;
     198                #endif // BUCKETLOCK
    202199                size_t blockSize;                                                               // size of allocations on this list
    203200        }; // FreeHeader
     
    211208        size_t heapRemaining;                                                           // amount of storage not allocated in the current chunk
    212209}; // HeapManager
     210
     211#if BUCKETLOCK == LOCKFREE
     212static inline Link(HeapManager.Storage) * getNext( HeapManager.Storage * this ) { return &this->header.kind.real.next; }
     213static inline void ?{}( HeapManager.FreeHeader & ) {}
     214static inline void ^?{}( HeapManager.FreeHeader & ) {}
     215#endif // LOCKFREE
    213216
    214217static inline size_t getKey( const HeapManager.FreeHeader & freeheader ) { return freeheader.blockSize; }
     
    251254static bool heapBoot = 0;                                                               // detect recursion during boot
    252255#endif // __CFA_DEBUG__
     256
     257// The constructor for heapManager is called explicitly in memory_startup.
    253258static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    254259
     
    354359
    355360
    356 // static inline void noMemory() {
    357 //      abort( "Heap memory exhausted at %zu bytes.\n"
    358 //                 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
    359 //                 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
    360 // } // noMemory
    361 
    362 
    363361// thunk problem
    364362size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
     
    406404
    407405
     406// static inline void noMemory() {
     407//      abort( "Heap memory exhausted at %zu bytes.\n"
     408//                 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
     409//                 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
     410// } // noMemory
     411
     412
    408413static inline void checkAlign( size_t alignment ) {
    409414        if ( alignment < libAlign() || ! libPow2( alignment ) ) {
     
    433438
    434439
    435 static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
     440static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem,
     441                                                        size_t & size, size_t & alignment ) with( heapManager ) {
    436442        header = headerAddr( addr );
    437443
     
    465471
    466472
    467 static inline void * extend( size_t size ) with ( heapManager ) {
     473static inline void * extend( size_t size ) with( heapManager ) {
    468474        lock( extlock __cfaabi_dbg_ctx2 );
    469475        ptrdiff_t rem = heapRemaining - size;
     
    496502
    497503
    498 static inline void * doMalloc( size_t size ) with ( heapManager ) {
     504static inline void * doMalloc( size_t size ) with( heapManager ) {
    499505        HeapManager.Storage * block;                                            // pointer to new block of storage
    500506
     
    529535                // Spin until the lock is acquired for this particular size of block.
    530536
    531                 #if defined( SPINLOCK )
     537                #if BUCKETLOCK == SPINLOCK
    532538                lock( freeElem->lock __cfaabi_dbg_ctx2 );
    533539                block = freeElem->freeList;                                             // remove node from stack
    534540                #else
    535                 block = freeElem->freeList.pop();
    536                 #endif // SPINLOCK
     541                block = pop( freeElem->freeList );
     542                #endif // BUCKETLOCK
    537543                if ( unlikely( block == 0p ) ) {                                // no free block ?
    538                         #if defined( SPINLOCK )
     544                        #if BUCKETLOCK == SPINLOCK
    539545                        unlock( freeElem->lock );
    540                         #endif // SPINLOCK
     546                        #endif // BUCKETLOCK
    541547
    542548                        // Freelist for that size was empty, so carve it out of the heap if there's enough left, or get some more
     
    544550
    545551                        block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call
    546   if ( unlikely( block == 0p ) ) return 0p;
    547                 #if defined( SPINLOCK )
     552        if ( unlikely( block == 0p ) ) return 0p;
     553                #if BUCKETLOCK == SPINLOCK
    548554                } else {
    549555                        freeElem->freeList = block->header.kind.real.next;
    550556                        unlock( freeElem->lock );
    551                 #endif // SPINLOCK
     557                #endif // BUCKETLOCK
    552558                } // if
    553559
     
    572578        } // if
    573579
    574         block->header.size = size;                                                      // store allocation size
     580        block->header.kind.real.size = size;                            // store allocation size
    575581        void * addr = &(block->data);                                           // adjust off header to user bytes
    576582
     
    591597
    592598
    593 static inline void doFree( void * addr ) with ( heapManager ) {
     599static inline void doFree( void * addr ) with( heapManager ) {
    594600        #ifdef __CFA_DEBUG__
    595601        if ( unlikely( heapManager.heapBegin == 0p ) ) {
     
    623629                free_storage += size;
    624630                #endif // __STATISTICS__
    625                 #if defined( SPINLOCK )
     631                #if BUCKETLOCK == SPINLOCK
    626632                lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
    627633                header->kind.real.next = freeElem->freeList;    // push on stack
     
    629635                unlock( freeElem->lock );                                               // release spin lock
    630636                #else
    631                 freeElem->freeList.push( *(HeapManager.Storage *)header );
    632                 #endif // SPINLOCK
     637                push( freeElem->freeList, *(HeapManager.Storage *)header );
     638                #endif // BUCKETLOCK
    633639        } // if
    634640
     
    645651
    646652
    647 size_t prtFree( HeapManager & manager ) with ( manager ) {
     653size_t prtFree( HeapManager & manager ) with( manager ) {
    648654        size_t total = 0;
    649655        #ifdef __STATISTICS__
     
    657663                #endif // __STATISTICS__
    658664
    659                 #if defined( SPINLOCK )
     665                #if BUCKETLOCK == SPINLOCK
    660666                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
    661667                #else
    662                 for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {
    663                 #endif // SPINLOCK
     668                for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; /* p = getNext( p )->top */) {
     669                        typeof(p) temp = getNext( p )->top;                     // FIX ME: direct assignent fails, initialization works
     670                        p = temp;
     671                #endif // BUCKETLOCK
    664672                        total += size;
    665673                        #ifdef __STATISTICS__
     
    681689
    682690
    683 static void ?{}( HeapManager & manager ) with ( manager ) {
     691static void ?{}( HeapManager & manager ) with( manager ) {
    684692        pageSize = sysconf( _SC_PAGESIZE );
    685693
     
    10951103                        header = realHeader( header );                          // backup from fake to real header
    10961104                } // if
    1097                 return header->size;
     1105                return header->kind.real.size;
    10981106        } // malloc_size
    10991107
     
    11051113                        header = realHeader( header );                          // backup from fake to real header
    11061114                } // if
    1107                 size_t ret = header->size;
    1108                 header->size = size;
     1115                size_t ret = header->kind.real.size;
     1116                header->kind.real.size = size;
    11091117                return ret;
    11101118        } // $malloc_size_set
  • libcfa/src/stdlib.hfa

    r2802824 r0e4df2e  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 16 22:44:05 2020
    13 // Update Count     : 432
     12// Last Modified On : Wed May 13 17:23:51 2020
     13// Update Count     : 435
    1414//
    1515
     
    2323// Reduce includes by explicitly defining these routines.
    2424extern "C" {
     25        void * aalloc( size_t dim, size_t elemSize );           // CFA heap
     26        void * resize( void * oaddr, size_t size );                     // CFA heap
    2527        void * memalign( size_t align, size_t size );           // malloc.h
     28        void * amemalign( size_t align, size_t dim, size_t elemSize ); // CFA heap
     29        void * cmemalign( size_t align, size_t noOfElems, size_t elemSize ); // CFA heap
     30        size_t malloc_size( void * addr );                                      // CFA heap
    2631        size_t malloc_usable_size( void * ptr );                        // malloc.h
    27         size_t malloc_size( void * addr );                                      // CFA heap
    28         void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ); // CFA heap
    2932        void * memset( void * dest, int fill, size_t size ); // string.h
    3033        void * memcpy( void * dest, const void * src, size_t size ); // string.h
    31         void * resize( void * oaddr, size_t size );                     // CFA heap
    3234} // extern "C"
    3335
     
    5254        } // malloc
    5355
     56        T * aalloc( size_t dim ) {
     57                if ( _Alignof(T) <= libAlign() ) return (T *)(void *)aalloc( dim, (size_t)sizeof(T) ); // CFA aalloc
     58                else return (T *)amemalign( _Alignof(T), dim, sizeof(T) );
     59        } // aalloc
     60
    5461        T * calloc( size_t dim ) {
    5562                if ( _Alignof(T) <= libAlign() )return (T *)(void *)calloc( dim, sizeof(T) ); // C calloc
     
    5764        } // calloc
    5865
     66        T * resize( T * ptr, size_t size ) {                            // CFA realloc, eliminate return-type cast
     67                return (T *)(void *)resize( (void *)ptr, size ); // C realloc
     68        } // resize
     69
    5970        T * realloc( T * ptr, size_t size ) {                           // CFA realloc, eliminate return-type cast
    6071                return (T *)(void *)realloc( (void *)ptr, size ); // C realloc
     
    6576        } // memalign
    6677
     78        T * amemalign( size_t align, size_t dim ) {
     79                return (T *)amemalign( align, dim, sizeof(T) ); // CFA amemalign
     80        } // amemalign
     81
    6782        T * cmemalign( size_t align, size_t dim  ) {
    6883                return (T *)cmemalign( align, dim, sizeof(T) ); // CFA cmemalign
     
    86101
    87102        T * alloc( size_t dim ) {
    88                 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( dim * (size_t)sizeof(T) );
    89                 else return (T *)memalign( _Alignof(T), dim * sizeof(T) );
     103                return aalloc( dim );
    90104        } // alloc
    91105
     
    106120                        return (T *)(void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    107121                } else {
    108                         struct __Unknown {};
    109                         return alloc( (__Unknown *)ptr, dim );          // reuse, cheat making T/S different types
     122                        return resize( ptr, dim * sizeof(T) );          // resize
    110123                } // if
    111124        } // alloc
     
    148161        } // alloc_align
    149162
    150         T * alloc_align( T ptr[], size_t align ) {                      // aligned realloc array
     163        T * alloc_align( T * ptr, size_t align ) {                      // aligned realloc array
    151164                return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
    152165        } // alloc_align
  • src/ControlStruct/ExceptTranslate.cc

    r2802824 r0e4df2e  
    1010// Created On       : Wed Jun 14 16:49:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Mar 27 11:58:00 2020
    13 // Update Count     : 13
     12// Last Modified On : Thr May 21 13:18:00 2020
     13// Update Count     : 15
    1414//
    1515
     
    6464        }
    6565
    66         class ExceptionMutatorCore : public WithGuards {
    67                 enum Context { NoHandler, TerHandler, ResHandler };
    68 
    69                 // Also need to handle goto, break & continue.
    70                 // They need to be cut off in a ResHandler, until we enter another
    71                 // loop, switch or the goto stays within the function.
    72 
    73                 Context cur_context;
    74 
    75                 // The current (innermost) termination handler exception declaration.
    76                 ObjectDecl * handler_except_decl;
    77 
     66        class ThrowMutatorCore : public WithGuards {
     67                ObjectDecl * terminate_handler_except;
     68                enum Context { NoHandler, TerHandler, ResHandler } cur_context;
     69
     70                // The helper functions for code/syntree generation.
     71                Statement * create_either_throw(
     72                        ThrowStmt * throwStmt, const char * throwFunc );
     73                Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
     74                Statement * create_resume_rethrow( ThrowStmt * throwStmt );
     75
     76        public:
     77                ThrowMutatorCore() :
     78                        terminate_handler_except( nullptr ),
     79                        cur_context( NoHandler )
     80                {}
     81
     82                void premutate( CatchStmt *catchStmt );
     83                Statement * postmutate( ThrowStmt *throwStmt );
     84        };
     85
     86        // ThrowStmt Mutation Helpers
     87
     88        Statement * ThrowMutatorCore::create_either_throw(
     89                        ThrowStmt * throwStmt, const char * throwFunc ) {
     90                // `throwFunc`( `throwStmt->get_name()` );
     91                UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
     92                call->get_args().push_back( throwStmt->get_expr() );
     93                throwStmt->set_expr( nullptr );
     94                delete throwStmt;
     95                return new ExprStmt( call );
     96        }
     97
     98        Statement * ThrowMutatorCore::create_terminate_rethrow(
     99                        ThrowStmt *throwStmt ) {
     100                // { `terminate_handler_except` = 0p; __rethrow_terminate(); }
     101                assert( nullptr == throwStmt->get_expr() );
     102                assert( terminate_handler_except );
     103
     104                CompoundStmt * result = new CompoundStmt();
     105                result->labels =  throwStmt->labels;
     106                result->push_back( new ExprStmt( UntypedExpr::createAssign(
     107                        nameOf( terminate_handler_except ),
     108                        new ConstantExpr( Constant::null(
     109                                //new PointerType(
     110                                //      noQualifiers,
     111                                        terminate_handler_except->get_type()->clone()
     112                                //      )
     113                                ) )
     114                        ) ) );
     115                result->push_back( new ExprStmt(
     116                        new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
     117                        ) );
     118                delete throwStmt;
     119                return result;
     120        }
     121
     122        Statement * ThrowMutatorCore::create_resume_rethrow(
     123                        ThrowStmt *throwStmt ) {
     124                // return false;
     125                Statement * result = new ReturnStmt(
     126                        new ConstantExpr( Constant::from_bool( false ) )
     127                        );
     128                result->labels = throwStmt->labels;
     129                delete throwStmt;
     130                return result;
     131        }
     132
     133        // Visiting/Mutating Functions
     134
     135        void ThrowMutatorCore::premutate( CatchStmt *catchStmt ) {
     136                // Validate the statement's form.
     137                ObjectDecl * decl = dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
     138                // Also checking the type would be nice.
     139                if ( decl ) {
     140                        // Pass.
     141                } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
     142                        SemanticError(catchStmt->location, "catch must have exception type");
     143                } else {
     144                        SemanticError(catchStmt->location, "catchResume must have exception type");
     145                }
     146
     147                // Track the handler context.
     148                GuardValue( cur_context );
     149                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
     150                        cur_context = TerHandler;
     151
     152                        GuardValue( terminate_handler_except );
     153                        terminate_handler_except = decl;
     154                } else {
     155                        cur_context = ResHandler;
     156                }
     157        }
     158
     159        Statement * ThrowMutatorCore::postmutate( ThrowStmt *throwStmt ) {
     160                // Ignoring throwStmt->get_target() for now.
     161                if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
     162                        if ( throwStmt->get_expr() ) {
     163                                return create_either_throw( throwStmt, "$throw" );
     164                        } else if ( TerHandler == cur_context ) {
     165                                return create_terminate_rethrow( throwStmt );
     166                        } else {
     167                                abort("Invalid throw in %s at %i\n",
     168                                        throwStmt->location.filename.c_str(),
     169                                        throwStmt->location.first_line);
     170                        }
     171                } else {
     172                        if ( throwStmt->get_expr() ) {
     173                                return create_either_throw( throwStmt, "$throwResume" );
     174                        } else if ( ResHandler == cur_context ) {
     175                                return create_resume_rethrow( throwStmt );
     176                        } else {
     177                                abort("Invalid throwResume in %s at %i\n",
     178                                        throwStmt->location.filename.c_str(),
     179                                        throwStmt->location.first_line);
     180                        }
     181                }
     182        }
     183
     184        class TryMutatorCore {
    78185                // The built in types used in translation.
    79186                StructDecl * except_decl;
     
    82189
    83190                // The many helper functions for code/syntree generation.
    84                 Statement * create_given_throw(
    85                         const char * throwFunc, ThrowStmt * throwStmt );
    86                 Statement * create_terminate_throw( ThrowStmt * throwStmt );
    87                 Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
    88                 Statement * create_resume_throw( ThrowStmt * throwStmt );
    89                 Statement * create_resume_rethrow( ThrowStmt * throwStmt );
    90191                CompoundStmt * take_try_block( TryStmt * tryStmt );
    91192                FunctionDecl * create_try_wrapper( CompoundStmt * body );
     
    121222
    122223        public:
    123                 ExceptionMutatorCore() :
    124                         cur_context( NoHandler ),
    125                         handler_except_decl( nullptr ),
     224                TryMutatorCore() :
    126225                        except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
    127226                        try_func_t( noQualifiers, false ),
     
    132231                {}
    133232
    134                 void premutate( CatchStmt *catchStmt );
    135233                void premutate( StructDecl *structDecl );
    136234                Statement * postmutate( ThrowStmt *throwStmt );
     
    138236        };
    139237
    140         void ExceptionMutatorCore::init_func_types() {
     238        void TryMutatorCore::init_func_types() {
    141239                assert( except_decl );
    142240
     
    196294        }
    197295
    198         // ThrowStmt Mutation Helpers
    199 
    200         Statement * ExceptionMutatorCore::create_given_throw(
    201                         const char * throwFunc, ThrowStmt * throwStmt ) {
    202                 // `throwFunc`( `throwStmt->get_name` );
    203                 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
    204                 call->get_args().push_back( throwStmt->get_expr() );
    205                 throwStmt->set_expr( nullptr );
    206                 delete throwStmt;
    207                 return new ExprStmt( call );
    208         }
    209 
    210         Statement * ExceptionMutatorCore::create_terminate_throw(
    211                         ThrowStmt *throwStmt ) {
    212                 // __throw_terminate( `throwStmt->get_name()` ); }
    213                 return create_given_throw( "__cfaehm_throw_terminate", throwStmt );
    214         }
    215 
    216         Statement * ExceptionMutatorCore::create_terminate_rethrow(
    217                         ThrowStmt *throwStmt ) {
    218                 // { `handler_except_decl` = NULL; __rethrow_terminate(); }
    219                 assert( nullptr == throwStmt->get_expr() );
    220                 assert( handler_except_decl );
    221 
    222                 CompoundStmt * result = new CompoundStmt();
    223                 result->labels =  throwStmt->labels;
    224                 result->push_back( new ExprStmt( UntypedExpr::createAssign(
    225                         nameOf( handler_except_decl ),
    226                         new ConstantExpr( Constant::null(
    227                                 new PointerType(
    228                                         noQualifiers,
    229                                         handler_except_decl->get_type()->clone()
    230                                         )
    231                                 ) )
    232                         ) ) );
    233                 result->push_back( new ExprStmt(
    234                         new UntypedExpr( new NameExpr( "__cfaehm_rethrow_terminate" ) )
    235                         ) );
    236                 delete throwStmt;
    237                 return result;
    238         }
    239 
    240         Statement * ExceptionMutatorCore::create_resume_throw(
    241                         ThrowStmt *throwStmt ) {
    242                 // __throw_resume( `throwStmt->get_name` );
    243                 return create_given_throw( "__cfaehm_throw_resume", throwStmt );
    244         }
    245 
    246         Statement * ExceptionMutatorCore::create_resume_rethrow(
    247                         ThrowStmt *throwStmt ) {
    248                 // return false;
    249                 Statement * result = new ReturnStmt(
    250                         new ConstantExpr( Constant::from_bool( false ) )
    251                         );
    252                 result->labels = throwStmt->labels;
    253                 delete throwStmt;
    254                 return result;
    255         }
    256 
    257296        // TryStmt Mutation Helpers
    258297
    259         CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
     298        CompoundStmt * TryMutatorCore::take_try_block( TryStmt *tryStmt ) {
    260299                CompoundStmt * block = tryStmt->get_block();
    261300                tryStmt->set_block( nullptr );
     
    263302        }
    264303
    265         FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
     304        FunctionDecl * TryMutatorCore::create_try_wrapper(
    266305                        CompoundStmt *body ) {
    267306
     
    270309        }
    271310
    272         FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
     311        FunctionDecl * TryMutatorCore::create_terminate_catch(
    273312                        CatchList &handlers ) {
    274313                std::list<CaseStmt *> handler_wrappers;
     
    350389        // Create a single check from a moddified handler.
    351390        // except_obj is referenced, modded_handler will be freed.
    352         CompoundStmt * ExceptionMutatorCore::create_single_matcher(
     391        CompoundStmt * TryMutatorCore::create_single_matcher(
    353392                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
    354393                // {
     
    388427        }
    389428
    390         FunctionDecl * ExceptionMutatorCore::create_terminate_match(
     429        FunctionDecl * TryMutatorCore::create_terminate_match(
    391430                        CatchList &handlers ) {
    392431                // int match(exception * except) {
     
    425464        }
    426465
    427         CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
     466        CompoundStmt * TryMutatorCore::create_terminate_caller(
    428467                        FunctionDecl * try_wrapper,
    429468                        FunctionDecl * terminate_catch,
     
    443482        }
    444483
    445         FunctionDecl * ExceptionMutatorCore::create_resume_handler(
     484        FunctionDecl * TryMutatorCore::create_resume_handler(
    446485                        CatchList &handlers ) {
    447486                // bool handle(exception * except) {
     
    480519        }
    481520
    482         CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
     521        CompoundStmt * TryMutatorCore::create_resume_wrapper(
    483522                        Statement * wraps,
    484523                        FunctionDecl * resume_handler ) {
     
    524563        }
    525564
    526         FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
     565        FunctionDecl * TryMutatorCore::create_finally_wrapper(
    527566                        TryStmt * tryStmt ) {
    528                 // void finally() { <finally code> }
     567                // void finally() { `finally->block` }
    529568                FinallyStmt * finally = tryStmt->get_finally();
    530569                CompoundStmt * body = finally->get_block();
     
    537576        }
    538577
    539         ObjectDecl * ExceptionMutatorCore::create_finally_hook(
     578        ObjectDecl * TryMutatorCore::create_finally_hook(
    540579                        FunctionDecl * finally_wrapper ) {
    541580                // struct __cfaehm_cleanup_hook __finally_hook
    542                 //      __attribute__((cleanup( finally_wrapper )));
     581                //      __attribute__((cleanup( `finally_wrapper` )));
    543582
    544583                // Make Cleanup Attribute.
     
    565604
    566605        // Visiting/Mutating Functions
    567         void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
    568                 // Validate the Statement's form.
    569                 ObjectDecl * decl =
    570                         dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
    571                 if ( decl && true /* check decl->get_type() */ ) {
    572                         // Pass.
    573                 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    574                         SemanticError(catchStmt->location, "catch must have exception type");
    575                 } else {
    576                         SemanticError(catchStmt->location, "catchResume must have exception type");
    577                 }
    578 
    579                 // Track the handler context.
    580                 GuardValue( cur_context );
    581                 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
    582                         cur_context = TerHandler;
    583 
    584                         GuardValue( handler_except_decl );
    585                         handler_except_decl = decl;
    586                 } else {
    587                         cur_context = ResHandler;
    588                 }
    589         }
    590 
    591         void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
     606        void TryMutatorCore::premutate( StructDecl *structDecl ) {
    592607                if ( !structDecl->has_body() ) {
    593608                        // Skip children?
     
    604619                        hook_decl = structDecl;
    605620                }
    606                 // Later we might get the exception type as well.
    607         }
    608 
    609         Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
    610                 assert( except_decl );
    611 
    612                 // Ignoring throwStmt->get_target() for now.
    613                 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
    614                         if ( throwStmt->get_expr() ) {
    615                                 return create_terminate_throw( throwStmt );
    616                         } else if ( TerHandler == cur_context ) {
    617                                 return create_terminate_rethrow( throwStmt );
    618                         } else {
    619                                 abort("Invalid throw in %s at %i\n",
    620                                         throwStmt->location.filename.c_str(),
    621                                         throwStmt->location.first_line);
    622                         }
    623                 } else {
    624                         if ( throwStmt->get_expr() ) {
    625                                 return create_resume_throw( throwStmt );
    626                         } else if ( ResHandler == cur_context ) {
    627                                 return create_resume_rethrow( throwStmt );
    628                         } else {
    629                                 abort("Invalid throwResume in %s at %i\n",
    630                                         throwStmt->location.filename.c_str(),
    631                                         throwStmt->location.first_line);
    632                         }
    633                 }
    634         }
    635 
    636         Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
     621        }
     622
     623        Statement * TryMutatorCore::postmutate( ThrowStmt * ) {
     624                // All throws should be removed by this point.
     625                assert( false );
     626        }
     627
     628        Statement * TryMutatorCore::postmutate( TryStmt *tryStmt ) {
    637629                assert( except_decl );
    638630                assert( node_decl );
     
    688680        }
    689681
    690         void translateEHM( std::list< Declaration *> & translationUnit ) {
    691                 PassVisitor<ExceptionMutatorCore> translator;
     682        void translateThrows( std::list< Declaration *> & translationUnit ) {
     683                PassVisitor<ThrowMutatorCore> translator;
    692684                mutateAll( translationUnit, translator );
    693685        }
     686
     687        void translateTries( std::list< Declaration *> & translationUnit ) {
     688                PassVisitor<TryMutatorCore> translator;
     689                mutateAll( translationUnit, translator );
     690        }
    694691}
  • src/ControlStruct/ExceptTranslate.h

    r2802824 r0e4df2e  
    99// Author           : Andrew Beach
    1010// Created On       : Tus Jun 06 10:13:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:19:23 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tus May 19 11:47:00 2020
     13// Update Count     : 5
    1414//
    1515
     
    2121
    2222namespace ControlStruct {
    23         void translateEHM( std::list< Declaration *> & translationUnit );
    24         // Converts exception handling structures into their underlying C code.  Translation does use the exception
    25         // handling header, make sure it is visible wherever translation occurs.
     23        void translateThrows( std::list< Declaration *> & translationUnit );
     24        /* Replaces all throw & throwResume statements with function calls.
     25         * These still need to be resolved, so call this before the reslover.
     26         */
     27
     28        void translateTries( std::list< Declaration *> & translationUnit );
     29        /* Replaces all try blocks (and their many clauses) with function definitions and calls.
     30         * This uses the exception built-ins to produce typed output and should take place after
     31         * the resolver.
     32         */
    2633}
    2734
  • src/main.cc

    r2802824 r0e4df2e  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb  8 08:33:50 2020
    13 // Update Count     : 633
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue May 19 12:03:00 2020
     13// Update Count     : 634
    1414//
    1515
     
    312312                } // if
    313313
     314                PASS( "Translate Throws", ControlStruct::translateThrows( translationUnit ) );
    314315                PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
    315316                PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
     
    354355                PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    355356
    356                 PASS( "Translate EHM" , ControlStruct::translateEHM( translationUnit ) );
     357                PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
    357358
    358359                PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
  • tests/errors/.expect/completeType.txt

    r2802824 r0e4df2e  
    132132?=?: pointer to function
    133133        ... with parameters
    134           reference to instance of type _104_0_T (not function type)
    135           instance of type _104_0_T (not function type)
     134          reference to instance of type _108_0_T (not function type)
     135          instance of type _108_0_T (not function type)
    136136        ... returning
    137           _retval__operator_assign: instance of type _104_0_T (not function type)
     137          _retval__operator_assign: instance of type _108_0_T (not function type)
    138138          ... with attributes:
    139139            Attribute with name: unused
  • tests/exceptions/conditional.cfa

    r2802824 r0e4df2e  
    5656
    5757        try {
    58                 throw &exc;
     58                throw exc;
    5959        } catch (num_error * error ; 3 == error->virtual_table->code( error )) {
    6060                caught_num_error(3, error);
     
    6464
    6565        try {
    66                 throwResume &exc;
     66                throwResume exc;
    6767        } catchResume (num_error * error ; 3 == error->virtual_table->code( error )) {
    6868                caught_num_error(3, error);
  • tests/exceptions/data-except.cfa

    r2802824 r0e4df2e  
    2828
    2929        try {
    30                 throw &except;
     30                throw except;
    3131        } catch (paired * exc) {
    3232                printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second);
     
    3737
    3838        try {
    39                 throwResume &except;
     39                throwResume except;
    4040        } catchResume (paired * exc) {
    4141                printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second);
  • tests/exceptions/finally.cfa

    r2802824 r0e4df2e  
    1212                try {
    1313                        printf("termination throw\n");
    14                         throw &exc;
     14                        throw exc;
    1515                } finally {
    1616                        loud_exit a = "termination inner finally";
     
    2828                try {
    2929                        printf("resumption throw\n");
    30                         throwResume &exc;
     30                        throwResume exc;
    3131                } finally {
    3232                        loud_exit a = "resumption inner finally";
  • tests/exceptions/interact.cfa

    r2802824 r0e4df2e  
    1010        // Resume falls back to terminate.
    1111        try {
    12                 throwResume &(star){};
     12                throwResume (star){};
    1313        } catch (star *) {
    1414                printf("caught as termination\n");
     
    1717        try {
    1818                loud_region a = "try block with resume throw";
    19                 throwResume &(star){};
     19                throwResume (star){};
    2020        } catch (star *) {
    2121                printf("caught as termination\n");
     
    2929        try {
    3030                try {
    31                         throw &(star){};
     31                        throw (star){};
    3232                } catchResume (star *) {
    3333                        printf("resume catch on terminate\n");
     
    4343        try {
    4444                try {
    45                         throwResume &(star){};
     45                        throwResume (star){};
    4646                } catch (star *) {
    4747                        printf("terminate catch on resume\n");
     
    5858                try {
    5959                        try {
    60                                 throw &(star){};
     60                                throw (star){};
    6161                        } catchResume (star *) {
    6262                                printf("inner resume catch (error)\n");
     
    6464                } catch (star * error) {
    6565                        printf("termination catch, will resume\n");
    66                         throwResume error;
     66                        throwResume *error;
    6767                }
    6868        } catchResume (star *) {
     
    7575                try {
    7676                        try {
    77                                 throwResume &(star){};
     77                                throwResume (star){};
    7878                        } catch (star *) {
    7979                                printf("inner termination catch\n");
     
    8181                } catchResume (star * error) {
    8282                        printf("resumption catch, will terminate\n");
    83                         throw error;
     83                        throw *error;
    8484                }
    8585        } catch (star *) {
     
    9494                                try {
    9595                                        printf("throwing resume moon\n");
    96                                         throwResume &(moon){};
     96                                        throwResume (moon){};
    9797                                } catch (star *) {
    9898                                        printf("termination catch\n");
    9999                                }
    100100                                printf("throwing resume star\n");
    101                                 throwResume &(star){};
     101                                throwResume (star){};
    102102                        } catchResume (star *) {
    103103                                printf("resumption star catch\n");
     
    105105                } catchResume (moon *) {
    106106                        printf("resumption moon catch, will terminate\n");
    107                         throw &(star){};
     107                        throw (star){};
    108108                }
    109109        } catchResume (star *) {
  • tests/exceptions/resume.cfa

    r2802824 r0e4df2e  
    1414                loud_exit a = "simple try clause";
    1515                printf("simple throw\n");
    16                 throwResume &(zen){};
     16                throwResume (zen){};
    1717                printf("end of try clause\n");
    1818        } catchResume (zen * error) {
     
    2424        // Throw catch-all test.
    2525        try {
    26                 throwResume &(zen){};
     26                throwResume (zen){};
    2727        } catchResume (exception_t * error) {
    2828                printf("catch-all\n");
     
    3333        try {
    3434                printf("throwing child exception\n");
    35                 throwResume &(moment_of){};
     35                throwResume (moment_of){};
    3636        } catchResume (zen *) {
    3737                printf("inner parent match\n");
     
    4444        try {
    4545                try {
    46                         throwResume &(yin){};
     46                        throwResume (yin){};
    4747                } catchResume (zen *) {
    4848                        printf("caught yin as zen\n");
     
    6060                        loud_exit a = "rethrow inner try";
    6161                        printf("rethrow inner try\n");
    62                         throwResume &(zen){};
     62                        throwResume (zen){};
    6363                } catchResume (zen *) {
    6464                        loud_exit a = "rethrowing catch clause";
     
    7575        try {
    7676                try {
    77                         throwResume &(yin){};
     77                        throwResume (yin){};
    7878                } catchResume (yin *) {
    7979                        printf("caught yin, will throw yang\n");
    80                         throwResume &(yang){};
     80                        throwResume (yang){};
    8181                } catchResume (yang *) {
    8282                        printf("caught exception from same try\n");
     
    9191                try {
    9292                        printf("throwing first exception\n");
    93                         throwResume &(yin){};
     93                        throwResume (yin){};
    9494                } catchResume (yin *) {
    9595                        printf("caught first exception\n");
    9696                        try {
    9797                                printf("throwing second exception\n");
    98                                 throwResume &(yang){};
     98                                throwResume (yang){};
    9999                        } catchResume (yang *) {
    100100                                printf("caught second exception\n");
     
    112112        try {
    113113                try {
    114                         throwResume &(zen){};
    115                         throwResume &(zen){};
     114                        throwResume (zen){};
     115                        throwResume (zen){};
    116116                } catchResume (zen *) {
    117117                        printf("inner catch\n");
    118118                }
    119                 throwResume &(zen){};
     119                throwResume (zen){};
    120120        } catchResume (zen *) {
    121121                printf("outer catch\n");
  • tests/exceptions/terminate.cfa

    r2802824 r0e4df2e  
    1414                loud_exit a = "simple try clause";
    1515                printf("simple throw\n");
    16                 throw &(zen){};
     16                throw (zen){};
    1717                printf("end of try clause\n");
    1818        } catch (zen * error) {
     
    2424        // Throw catch-all test.
    2525        try {
    26                 throw &(zen){};
     26                throw (zen){};
    2727        } catch (exception_t * error) {
    2828                printf("catch-all\n");
     
    3333        try {
    3434                printf("throwing child exception\n");
    35                 throw &(moment_of){};
     35                throw (moment_of){};
    3636        } catch (zen *) {
    3737                printf("inner parent match\n");
     
    4444        try {
    4545                try {
    46                         throw &(yin){};
     46                        throw (yin){};
    4747                } catch (zen *) {
    4848                        printf("caught yin as zen\n");
     
    6060                        loud_exit a = "rethrow inner try";
    6161                        printf("rethrow inner try\n");
    62                         throw &(zen){};
     62                        throw (zen){};
    6363                } catch (zen *) {
    6464                        loud_exit a = "rethrowing catch clause";
     
    7575        try {
    7676                try {
    77                         throw &(yin){};
     77                        throw (yin){};
    7878                } catch (yin *) {
    7979                        printf("caught yin, will throw yang\n");
    80                         throw &(yang){};
     80                        throw (yang){};
    8181                } catch (yang *) {
    8282                        printf("caught exception from same try\n");
     
    9191                try {
    9292                        printf("throwing first exception\n");
    93                         throw &(yin){};
     93                        throw (yin){};
    9494                } catch (yin *) {
    9595                        printf("caught first exception\n");
    9696                        try {
    9797                                printf("throwing second exception\n");
    98                                 throw &(yang){};
     98                                throw (yang){};
    9999                        } catch (yang *) {
    100100                                printf("caught second exception\n");
     
    112112        try {
    113113                try {
    114                         throw &(zen){};
    115                         throw &(zen){};
     114                        throw (zen){};
     115                        throw (zen){};
    116116                } catch (zen *) {
    117117                        printf("inner catch\n");
    118118                }
    119                 throw &(zen){};
     119                throw (zen){};
    120120        } catch (zen *) {
    121121                printf("outer catch\n");
  • tests/list/.expect/dlist-insert-remove.txt

    r2802824 r0e4df2e  
    146414640.7
    14651465-
     1466
     1467~~~~~~~~~~ End removal tests on Headed List: First ~~~~~~~~~~
     1468
     1469~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1470Test 16-i.  Modifying Freds on MINE
     1471~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1472==== fred by MINE before
     14731.7
     14742.7
     14753.7
     1476-
     14771.7
     1478-
     14793.7
     1480-
     14813.7
     14822.7
     14831.7
     1484-
     1485==== fred by YOURS before
     14861.7
     14872.7
     14883.7
     1489-
     14901.7
     1491-
     14923.7
     1493-
     14943.7
     14952.7
     14961.7
     1497-
     1498==== fred by MINE after
     14992.7
     15003.7
     1501-
     15022.7
     1503-
     15043.7
     1505-
     15063.7
     15072.7
     1508-
     1509==== fred by YOURS after
     15101.7
     15112.7
     15123.7
     1513-
     15141.7
     1515-
     15163.7
     1517-
     15183.7
     15192.7
     15201.7
     1521-
     1522==== fred by MINE after
     15231.7
     1524-
     15251.7
     1526-
     1527-
     1528-
     1529~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1530Test 16-ii.  Modifying Freds on YOURS
     1531~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1532==== fred by MINE before
     15331.7
     15342.7
     15353.7
     1536-
     15371.7
     1538-
     15393.7
     1540-
     15413.7
     15422.7
     15431.7
     1544-
     1545==== fred by YOURS before
     15461.7
     15472.7
     15483.7
     1549-
     15501.7
     1551-
     15523.7
     1553-
     15543.7
     15552.7
     15561.7
     1557-
     1558==== fred by MINE after
     15591.7
     15602.7
     15613.7
     1562-
     15631.7
     1564-
     15653.7
     1566-
     15673.7
     15682.7
     15691.7
     1570-
     1571==== fred by YOURS after
     15722.7
     15733.7
     1574-
     15752.7
     1576-
     15773.7
     1578-
     15793.7
     15802.7
     1581-
     1582==== fred by YOURS after
     15831.7
     1584-
     15851.7
     1586-
     1587-
     1588-
     1589~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1590Test 16-iii.  Modifying Maries
     1591~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1592==== mary before
     15931.7
     15942.7
     15953.7
     1596-
     15971.7
     1598-
     15993.7
     1600-
     16013.7
     16022.7
     16031.7
     1604-
     1605==== mary after
     16062.7
     16073.7
     1608-
     16092.7
     1610-
     16113.7
     1612-
     16133.7
     16142.7
     1615-
     1616==== mary after
     16171.7
     1618-
     16191.7
     1620-
     1621-
     1622-
     1623
     1624~~~~~~~~~~ End removal tests on Headed List: Last ~~~~~~~~~~
     1625
     1626~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1627Test 17-i.  Modifying Freds on MINE
     1628~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1629==== fred by MINE before
     16301.7
     16312.7
     16323.7
     1633-
     16341.7
     1635-
     16363.7
     1637-
     16383.7
     16392.7
     16401.7
     1641-
     1642==== fred by YOURS before
     16431.7
     16442.7
     16453.7
     1646-
     16471.7
     1648-
     16493.7
     1650-
     16513.7
     16522.7
     16531.7
     1654-
     1655==== fred by MINE after
     16561.7
     16572.7
     1658-
     16591.7
     1660-
     16612.7
     1662-
     16632.7
     16641.7
     1665-
     1666==== fred by YOURS after
     16671.7
     16682.7
     16693.7
     1670-
     16711.7
     1672-
     16733.7
     1674-
     16753.7
     16762.7
     16771.7
     1678-
     1679==== fred by MINE after
     16803.7
     1681-
     16823.7
     1683-
     1684-
     1685-
     1686~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1687Test 17-ii.  Modifying Freds on YOURS
     1688~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1689==== fred by MINE before
     16901.7
     16912.7
     16923.7
     1693-
     16941.7
     1695-
     16963.7
     1697-
     16983.7
     16992.7
     17001.7
     1701-
     1702==== fred by YOURS before
     17031.7
     17042.7
     17053.7
     1706-
     17071.7
     1708-
     17093.7
     1710-
     17113.7
     17122.7
     17131.7
     1714-
     1715==== fred by MINE after
     17161.7
     17172.7
     17183.7
     1719-
     17201.7
     1721-
     17223.7
     1723-
     17243.7
     17252.7
     17261.7
     1727-
     1728==== fred by YOURS after
     17291.7
     17302.7
     1731-
     17321.7
     1733-
     17342.7
     1735-
     17362.7
     17371.7
     1738-
     1739==== fred by YOURS after
     17403.7
     1741-
     17423.7
     1743-
     1744-
     1745-
     1746~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1747Test 17-iii.  Modifying Maries
     1748~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     1749==== mary before
     17501.7
     17512.7
     17523.7
     1753-
     17541.7
     1755-
     17563.7
     1757-
     17583.7
     17592.7
     17601.7
     1761-
     1762==== mary after
     17631.7
     17642.7
     1765-
     17661.7
     1767-
     17682.7
     1769-
     17702.7
     17711.7
     1772-
     1773==== mary after
     17743.7
     1775-
     17763.7
     1777-
     1778-
     1779-
  • tests/list/dlist-insert-remove.cfa

    r2802824 r0e4df2e  
    11871187////////////////////////////////////////////////////////////
    11881188//
     1189// Section 4f
     1190//
     1191// Test cases of pop_first, pop_last
     1192//
     1193// Example of call-side user code
     1194//
     1195////////////////////////////////////////////////////////////
     1196
     1197// These cases assume element removal at first-last is correct
     1198
     1199void test__pop_first__fred_mine() {
     1200
     1201        fred f1 = {1.7};
     1202        fred f2 = {2.7};
     1203        fred f3 = {3.7};
     1204
     1205        dlist(fred_in_mine, fred) flm;
     1206        insert_last(flm, f1);
     1207        insert_last(flm, f2);
     1208        insert_last(flm, f3);
     1209
     1210        dlist(fred_in_yours, fred) fly;
     1211        insert_last(fly, f1);
     1212        insert_last(fly, f2);
     1213        insert_last(fly, f3);
     1214
     1215        printMyFreddies(flm`first, flm`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1216        printYourFreddies(fly`first, fly`last, 1);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1217
     1218        verify(validate(fly));
     1219        verify(validate(flm));
     1220
     1221        fred & popped = pop_first(flm);
     1222
     1223        verify(validate(fly));
     1224        verify(validate(flm));
     1225
     1226        printMyFreddies(flm`first, flm`last, 0);     // 2.7, 3.7;       2.7;  3.7;  3.7, 2.7      (modified)
     1227        printYourFreddies(fly`first, fly`last, 0);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7 (unmodified)
     1228
     1229        // observe f1 is now solo in mine; in yours, it was just traversed
     1230        printMyFreddies(f1, *0p, 0);    // 1.7; 1.7; ;
     1231
     1232        assert( &popped == & f1 );
     1233}
     1234
     1235void test__pop_first__fred_yours() {
     1236
     1237        fred f1 = {1.7};
     1238        fred f2 = {2.7};
     1239        fred f3 = {3.7};
     1240
     1241        dlist(fred_in_mine, fred) flm;
     1242        insert_last(flm, f1);
     1243        insert_last(flm, f2);
     1244        insert_last(flm, f3);
     1245
     1246        dlist(fred_in_yours, fred) fly;
     1247        insert_last(fly, f1);
     1248        insert_last(fly, f2);
     1249        insert_last(fly, f3);
     1250
     1251        printMyFreddies(flm`first, flm`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1252        printYourFreddies(fly`first, fly`last, 1);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1253
     1254        verify(validate(fly));
     1255        verify(validate(flm));
     1256
     1257        fred & popped = pop_first(fly);
     1258
     1259        verify(validate(fly));
     1260        verify(validate(flm));
     1261
     1262        printMyFreddies(flm`first, flm`last, 0);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7 (unmodified)
     1263        printYourFreddies(fly`first, fly`last, 0);   // 2.7, 3.7;       2.7;  3.7;  3.7, 2.7      (modified)
     1264
     1265        // observe f1 is now solo in yours; in mine, it was just traversed
     1266        printYourFreddies(f1, *0p, 0);    // 1.7; 1.7; ;
     1267
     1268        assert( &popped == &f1 );
     1269}
     1270
     1271void test__pop_first__maries() {
     1272
     1273        mary m1 = {1.7};
     1274        mary m2 = {2.7};
     1275        mary m3 = {3.7};
     1276
     1277        dlist(mary, mary) ml;
     1278        insert_last(ml, m1);
     1279        insert_last(ml, m2);
     1280        insert_last(ml, m3);
     1281
     1282        printMariatheotokos(ml`first, ml`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1283
     1284        verify(validate(ml));
     1285
     1286        mary & popped = pop_first(ml);
     1287
     1288        verify(validate(ml));
     1289
     1290        printMariatheotokos(ml`first, ml`last, 0);     // 2.7, 3.7;       2.7;  3.7;  3.7, 2.7      (modified)
     1291
     1292        // observe m1 is now solo
     1293        printMariatheotokos(m1, *0p, 0);               // 1.7; 1.7; ;
     1294
     1295        assert( &popped == &m1 );
     1296}
     1297
     1298void test__pop_last__fred_mine() {
     1299
     1300        fred f1 = {1.7};
     1301        fred f2 = {2.7};
     1302        fred f3 = {3.7};
     1303
     1304        dlist(fred_in_mine, fred) flm;
     1305        insert_last(flm, f1);
     1306        insert_last(flm, f2);
     1307        insert_last(flm, f3);
     1308
     1309        dlist(fred_in_yours, fred) fly;
     1310        insert_last(fly, f1);
     1311        insert_last(fly, f2);
     1312        insert_last(fly, f3);
     1313
     1314        printMyFreddies(flm`first, flm`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1315        printYourFreddies(fly`first, fly`last, 1);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1316
     1317        verify(validate(fly));
     1318        verify(validate(flm));
     1319
     1320        fred & popped = pop_last(flm);
     1321
     1322        verify(validate(fly));
     1323        verify(validate(flm));
     1324
     1325        printMyFreddies(flm`first, flm`last, 0);     // 1.7, 2.7;       1.7;  2.7;  2.7, 1.7      (modified)
     1326        printYourFreddies(fly`first, fly`last, 0);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7 (unmodified)
     1327
     1328        // observe f3 is now solo in mine; in yours, it was just traversed
     1329        printMyFreddies(f3, *0p, 0);    // 3.7; 3.7; ;
     1330
     1331        assert( &popped == & f3 );
     1332}
     1333
     1334void test__pop_last__fred_yours() {
     1335
     1336        fred f1 = {1.7};
     1337        fred f2 = {2.7};
     1338        fred f3 = {3.7};
     1339
     1340        dlist(fred_in_mine, fred) flm;
     1341        insert_last(flm, f1);
     1342        insert_last(flm, f2);
     1343        insert_last(flm, f3);
     1344
     1345        dlist(fred_in_yours, fred) fly;
     1346        insert_last(fly, f1);
     1347        insert_last(fly, f2);
     1348        insert_last(fly, f3);
     1349
     1350        printMyFreddies(flm`first, flm`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1351        printYourFreddies(fly`first, fly`last, 1);   // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1352
     1353        verify(validate(fly));
     1354        verify(validate(flm));
     1355
     1356        fred & popped = pop_last(fly);
     1357
     1358        verify(validate(fly));
     1359        verify(validate(flm));
     1360
     1361        printMyFreddies(flm`first, flm`last, 0);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7 (unmodified)
     1362        printYourFreddies(fly`first, fly`last, 0);   // 1.7, 2.7;       1.7;  2.7;  2.7, 1.7      (modified)
     1363
     1364        // observe f3 is now solo in yours; in mine, it was just traversed
     1365        printYourFreddies(f3, *0p, 0);    // 3.7; 3.7; ;
     1366
     1367        assert( &popped == & f3 );
     1368}
     1369
     1370void test__pop_last__maries() {
     1371
     1372        mary m1 = {1.7};
     1373        mary m2 = {2.7};
     1374        mary m3 = {3.7};
     1375
     1376        dlist(mary, mary) ml;
     1377        insert_last(ml, m1);
     1378        insert_last(ml, m2);
     1379        insert_last(ml, m3);
     1380
     1381        printMariatheotokos(ml`first, ml`last, 1);     // 1.7, 2.7, 3.7;  1.7;  3.7;  3.7, 2.7, 1.7
     1382
     1383        verify(validate(ml));
     1384
     1385        mary & popped = pop_last(ml);
     1386
     1387        verify(validate(ml));
     1388
     1389        printMariatheotokos(ml`first, ml`last, 0);     // 1.7, 1.7;       1.7;  2.7;  2.7, 1.7      (modified)
     1390
     1391        // observe m1 is now solo
     1392        printMariatheotokos(m3, *0p, 0);               // 3.7; 3.7; ;
     1393
     1394        assert( &popped == &m3 );
     1395}
     1396
     1397////////////////////////////////////////////////////////////
     1398//
    11891399// Section 5
    11901400//
     
    14221632        test__remove_of_sole__mary();
    14231633
     1634        sout | "";
     1635        sout | "~~~~~~~~~~ End removal tests on Headed List: First ~~~~~~~~~~";
     1636        sout | "";
     1637
     1638        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1639        sout | "Test 16-i.  Modifying Freds on MINE";
     1640        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1641        test__pop_first__fred_mine();
     1642
     1643        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1644        sout | "Test 16-ii.  Modifying Freds on YOURS";
     1645        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1646        test__pop_first__fred_yours();
     1647
     1648        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1649        sout | "Test 16-iii.  Modifying Maries";
     1650        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1651        test__pop_first__maries();
     1652
     1653        sout | "";
     1654        sout | "~~~~~~~~~~ End removal tests on Headed List: Last ~~~~~~~~~~";
     1655        sout | "";
     1656
     1657        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1658        sout | "Test 17-i.  Modifying Freds on MINE";
     1659        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1660        test__pop_last__fred_mine();
     1661
     1662        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1663        sout | "Test 17-ii.  Modifying Freds on YOURS";
     1664        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1665        test__pop_last__fred_yours();
     1666
     1667        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1668        sout | "Test 17-iii.  Modifying Maries";
     1669        sout | "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
     1670        test__pop_last__maries();
     1671
    14241672        return 0;
    14251673}
Note: See TracChangeset for help on using the changeset viewer.