Changeset 53449a4


Ignore:
Timestamp:
Dec 16, 2020, 4:01:57 PM (2 years ago)
Author:
Colby Alexander Parsons <caparsons@…>
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
8ba363e, c8025a21
Parents:
b3c8496 (diff), 3e5dd913 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
1 added
3 deleted
62 edited

Legend:

Unmodified
Added
Removed
  • Jenkins/FullBuild

    rb3c8496 r53449a4  
    88        def err = null
    99
     10        final scmVars = checkout scm
     11        final commitId = scmVars.GIT_COMMIT
     12
    1013        try {
    1114                //Wrap build to add timestamp to command line
     
    1316
    1417                        stage('Build') {
    15 
    16                                 results = [null, null]
    1718
    1819                                parallel (
     
    3132
    3233                        stage('Package') {
    33                                 build job: 'Cforall_Distribute_Ref', parameters: [string(name: 'GitRef', value: gitRefNewValue), string(name: 'Build', value: currentBuild.number)]
     34                                build job: 'Cforall_Distribute_Ref', parameters: [string(name: 'GitRef', value: commitId), string(name: 'Build', value: currentBuild.number.toString())]
    3435                        }
    3536                }
     
    102103}
    103104
    104 //Helper routine to collect information about the git history
    105 def collect_git_info() {
    106 
    107         //create the temporary output directory in case it doesn't already exist
    108         def out_dir = pwd tmp: true
    109         sh "mkdir -p ${out_dir}"
    110 
    111         //parse git logs to find what changed
    112         dir("../Cforall_Full_Build@script") {
    113                 sh "git reflog > ${out_dir}/GIT_COMMIT"
    114         }
    115         git_reflog = readFile("${out_dir}/GIT_COMMIT")
    116         gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1]
    117         gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2]
    118 }
    119 
    120105//===========================================================================================================
    121106//Routine responsible of sending the email notification once the build is completed
  • benchmark/io/http/main.cfa

    rb3c8496 r53449a4  
    7575        address.sin_port = htons( options.socket.port );
    7676
    77         ret = bind( server_fd, (struct sockaddr *)&address, sizeof(address) );
    78         if(ret < 0) {
    79                 abort( "bind error: (%d) %s\n", (int)errno, strerror(errno) );
     77        int waited = 0;
     78        for() {
     79                ret = bind( server_fd, (struct sockaddr *)&address, sizeof(address) );
     80                if(ret < 0) {
     81                        if(errno == 98) {
     82                                if(waited == 0) {
     83                                        printf("Waiting for port\n");
     84                                } else {
     85                                        printf("\r%d", waited);
     86                                        fflush(stdout);
     87                                }
     88                                waited ++;
     89                                sleep( 1`s );
     90                                continue;
     91                        }
     92                        abort( "bind error: (%d) %s\n", (int)errno, strerror(errno) );
     93                }
     94                break;
    8095        }
    8196
  • doc/theses/thierry_delisle_PhD/code/readQ_example/Makefile

    rb3c8496 r53449a4  
    1 all: gui-proto
     1all: gui-proto-pthread gui-proto-fibre gui-proto-cforall
     2
     3PRECIOUS: thrdlib/libthrd-pthread.so thrdlib/libthrd-fibre.so thrdlib/libthrd-cforall.so
    24
    35CXXFLAGS = -fpic -g -O0 -I.
    46
    5 gui-proto: proto-gui/main.o thrdlib/thread.o
    6         $(CXX) -pthread -ldl -o ${@} ${^} -ftls-model=initial-exec
     7thrdlib/libthrd-%.so:
     8        +${MAKE} -C thrdlib libthrd-$*.so
     9
     10gui-proto-%: proto-gui/main.o thrdlib/libthrd-%.so Makefile
     11        $(CXX) -Lthrdlib -Wl,--rpath,thrdlib -pthread -o $@ $< -lthrd-$*
     12
     13CFAINC=${HOME}/local/include/cfa-dev
     14CFALIB=${HOME}/local/lib/cfa-dev/x64-debug
     15CFAFLAGS=-z execstack -ftls-model=initial-exec -L${CFALIB} -Wl,-rpath,${CFALIB}
     16
     17gui-proto-cforall: proto-gui/main.o thrdlib/libthrd-cforall.so Makefile
     18        $(CXX) -Lthrdlib -Wl,--rpath,thrdlib ${CFAFLAGS} -pthread -o $@ $< -lthrd-cforall -Wl,--push-state,--no-as-needed -lcfathread -lcfa -ldl -lm -Wl,--pop-state
  • doc/theses/thierry_delisle_PhD/code/readQ_example/proto-gui/main.cpp

    rb3c8496 r53449a4  
    1111#include <getopt.h>
    1212using thrdlib::thread_t;
    13 
    14 
    15 extern __attribute__((aligned(128))) thread_local struct {
    16         void * volatile this_thread;
    17         void * volatile this_processor;
    18         void * volatile this_stats;
    19 
    20         struct {
    21                 volatile unsigned short disable_count;
    22                 volatile bool enabled;
    23                 volatile bool in_progress;
    24         } preemption_state;
    25 
    26         #if defined(__SIZEOF_INT128__)
    27                 __uint128_t rand_seed;
    28         #else
    29                 uint64_t rand_seed;
    30         #endif
    31         struct {
    32                 uint64_t fwd_seed;
    33                 uint64_t bck_seed;
    34         } ready_rng;
    35 } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));
    3613
    3714//--------------------
     
    148125}
    149126
     127typedef uint64_t __wyhash64_state_t;
     128static inline uint64_t __wyhash64( __wyhash64_state_t & state ) {
     129        state += 0x60bee2bee120fc15;
     130        __uint128_t tmp;
     131        tmp = (__uint128_t) state * 0xa3b195354a39b70d;
     132        uint64_t m1 = (tmp >> 64) ^ tmp;
     133        tmp = (__uint128_t)m1 * 0x1b03738712fad5c9;
     134        uint64_t m2 = (tmp >> 64) ^ tmp;
     135        return m2;
     136}
     137
    150138void Simulator( thread_t self ) {
    151139        for(unsigned i = 0; i < nproduce; i++) {
     
    156144                }
    157145
     146                __wyhash64_state_t state = 0;
     147
    158148                // Write the frame information
    159149                frame.number = i;
    160150                for( unsigned x = 0; x < fsize; x++ ) {
    161                         frame.data[x] = i;
     151                        frame.data[x] = __wyhash64(state);
    162152                }
    163153                std::cout << "Simulated " << i << std::endl;
     
    187177
    188178                std::cout << "Rendered " << i << std::endl;
    189                 assert(total == i * fsize);
     179                // assert(total == i * fsize);
    190180
    191181                // Release
     
    201191int main(int argc, char * argv[]) {
    202192        nframes  = 3;
    203         fsize    = 1000;
     193        fsize    = 3840 * 2160 * 4 * 4;
    204194        nproduce = 60;
    205 
    206         const char * framework;
    207195
    208196        for(;;) {
     
    222210                        // Exit Case
    223211                        case -1:
    224                                 /* paranoid */ assert(optind <= argc);
    225                                 if( optind == argc ) {
    226                                         std::cerr << "Must specify a framework" << std::endl;
    227                                         goto usage;
    228 
    229                                 }
    230                                 framework = argv[optind];
    231212                                goto run;
    232213                        case 'b':
     
    261242                                std::cerr << opt << std::endl;
    262243                        usage:
    263                                 std::cerr << "Usage: " << argv[0] << " [options] framework" << std::endl;
     244                                std::cerr << "Usage: " << argv[0] << " [options]" << std::endl;
    264245                                std::cerr << std::endl;
    265246                                std::cerr << "  -b, --buff=COUNT    Number of frames to buffer" << std::endl;
     
    270251        }
    271252        run:
    272         assert( framework );
    273 
    274253        frames.reset(new Frame[nframes]);
    275254        for(unsigned i = 0; i < nframes; i++) {
     
    280259        std::cout << "(Buffering " << nframes << ")" << std::endl;
    281260
    282         thrdlib::init( framework, 2 );
     261        thrdlib::init( 2 );
    283262
    284263        thread_t stats     = thrdlib::create( Stats );
  • doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/Makefile

    rb3c8496 r53449a4  
    1 all: fibre.so pthread.so cforall.so
     1all: fibre.so libthrd-pthread.so.so cforall.so
    22
    33clean:
    4         rm -rf fibre.so pthread.so
     4        rm -rf fibre.so libthrd-pthread.so.so cforall.so
    55
    66CXXFLAGS=-Wall -Wextra -O3 -g -fpic -std=c++17 -pthread -ftls-model=initial-exec
    77
    8 pthread.so: pthread.cpp Makefile
    9         $(CXX) $(CXXFLAGS) -shared -o ${@} ${<}
     8libthrd-pthread.so: thread.cpp thread.hpp Makefile
     9        $(CXX) $(CXXFLAGS) -shared -o $@ $< -DWITH_PTHREADS
    1010
    11 fibre.so: fibre.cpp Makefile
    12         $(CXX) $(CXXFLAGS) -shared -o ${@} ${<} -lfibre
     11libthrd-fibre.so: thread.cpp thread.hpp Makefile
     12        $(CXX) $(CXXFLAGS) -shared -o $@ $< -DWITH_LIBFIBRE -lfibre
    1313
    1414CFAINC=${HOME}/local/include/cfa-dev
     
    1616CFAFLAGS=-z execstack -I${CFAINC} -I${CFAINC}/concurrency -L${CFALIB} -Wl,-rpath,${CFALIB}
    1717
    18 cforall.so: cforall.cpp Makefile
    19         $(CXX) $(CXXFLAGS) $(CFAFLAGS) -shared -o ${@} ${<} -lcfathread -lcfa -ldl -lm
     18libthrd-cforall.so: thread.cpp thread.hpp Makefile
     19        $(CXX) $(CXXFLAGS) $(CFAFLAGS) -shared -o $@ $< -DWITH_CFORALL -Wl,--push-state,--no-as-needed -lcfathread -lcfa -ldl -lm -Wl,--pop-state
  • doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.hpp

    rb3c8496 r53449a4  
     1#pragma once
     2
    13#include <pthread.h>
    24#include <errno.h>
     
    9799        // Basic kernel features
    98100        void thrdlib_init( int ) {}
     101        void thrdlib_clean( void ) {}
    99102}
  • doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.cpp

    rb3c8496 r53449a4  
    1 #include "thread.hpp"
     1#if !defined(WITH_PTHREADS) && !defined(WITH_LIBFIBRE) && !defined(WITH_CFORALL)
     2#error must define WITH_PTHREADS, WITH_LIBFIBRE or WITH_CFORALL
     3#endif
    24
    3 #include <cstdarg>                                                                              // va_start, va_end
    4 #include <cstdio>
    5 #include <cstring>                                                                              // strlen
    6 extern "C" {
    7         #include <unistd.h>                                                                             // _exit, getpid
    8         #include <signal.h>
    9         #include <dlfcn.h>                                                                              // dlopen, dlsym
    10         #include <execinfo.h>                                                                   // backtrace, messages
    11 }
     5#ifdef WITH_PTHREADS
     6#include "pthread.hpp"
     7#endif
     8#ifdef WITH_LIBFIBRE
     9#include "fibre.hpp"
     10#endif
     11#ifdef WITH_CFORALL
     12#include "cforall.hpp"
     13#endif
    1214
    13 #include <iostream>
    14 #include <string>
     15namespace thrdlib {
     16        //--------------------
     17        // Basic thread support
     18        void * create( void (*main)( void * ) ) { return (thread_t)thrdlib_create(  (void (*)( thread_t )) main ); }
     19        void join  ( void * handle ) { thrdlib_join  ((thread_t)handle); }
     20        void park  ( void * handle ) { thrdlib_park  ((thread_t)handle); }
     21        void unpark( void * handle ) { thrdlib_unpark((thread_t)handle); }
     22        void yield( void )  { thrdlib_yield(); }
    1523
    16 using thrdlib::thread_t;
    17 
    18 thread_t (*thrdlib::create)( void (*main)( thread_t ) ) = nullptr;
    19 void (*thrdlib::join)( thread_t handle ) = nullptr;
    20 void (*thrdlib::park)( thread_t handle ) = nullptr;
    21 void (*thrdlib::unpark)( thread_t handle ) = nullptr;
    22 void (*thrdlib::yield)( void ) = nullptr;
    23 void (*lib_clean)(void) = nullptr;
    24 
    25 typedef void (*fptr_t)();
    26 static fptr_t open_symbol( void * library, const char * symbol, bool required ) {
    27         void * ptr = dlsym( library, symbol );
    28 
    29         const char * error = dlerror();
    30         if ( required && error ) {
    31                 std::cerr << "Fetching symbol '" << symbol << "' failed with error '" << error << "'\n";
    32                 std::abort();
    33         }
    34 
    35         return (fptr_t)ptr;
    36 }
    37 
    38 //--------------------
    39 // Basic kernel features
    40 void thrdlib::init( const char * name, int procs ) {
    41         std::string file = __FILE__;
    42         std::size_t found = file.find_last_of("/");
    43         std::string libname = file.substr(0,found+1) + name + ".so";
    44 
    45         std::cout << "Use framework " << name << "(" << libname << ")\n";
    46 
    47         void * library = dlopen( libname.c_str(), RTLD_NOW );
    48         if ( const char * error = dlerror() ) {
    49                 std::cerr << "Could not open library '" << libname << "' from name '" << name <<"'\n";
    50                 std::cerr << "Error was : '" << error << "'\n";
    51                 std::abort();
    52         }
    53 
    54         void (*lib_init)( int ) = (void (*)( int ))open_symbol( library, "thrdlib_init", false );
    55         lib_clean = open_symbol( library, "thrdlib_clean" , false );
    56 
    57         thrdlib::create = (typeof(thrdlib::create))open_symbol( library, "thrdlib_create", true  );
    58         thrdlib::join   = (typeof(thrdlib::join  ))open_symbol( library, "thrdlib_join"  , true  );
    59         thrdlib::park   = (typeof(thrdlib::park  ))open_symbol( library, "thrdlib_park"  , true  );
    60         thrdlib::unpark = (typeof(thrdlib::unpark))open_symbol( library, "thrdlib_unpark", true  );
    61         thrdlib::yield  = (typeof(thrdlib::yield ))open_symbol( library, "thrdlib_yield" , true  );
    62 
    63         lib_init( procs );
    64 }
    65 
    66 void thrdlib::clean( void ) {
    67         if(lib_clean) lib_clean();
    68 }
     24        //--------------------
     25        // Basic kernel features
     26        void init( int procs ) { thrdlib_init(procs); }
     27        void clean( void ) { thrdlib_clean(); }
     28};
  • doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/thread.hpp

    rb3c8496 r53449a4  
    66        //--------------------
    77        // Basic thread support
    8         extern thread_t (*create)( void (*main)( thread_t ) );
    9         extern void (*join)( thread_t handle );
    10         extern void (*park)( thread_t handle );
    11         extern void (*unpark)( thread_t handle );
    12         extern void (*yield)( void ) ;
     8        extern thread_t create( void (*main)( thread_t ) );
     9        extern void join( thread_t handle );
     10        extern void park( thread_t handle );
     11        extern void unpark( thread_t handle );
     12        extern void yield( void ) ;
    1313
    1414        //--------------------
    1515        // Basic kernel features
    16         extern void init( const char * name, int procs );
     16        extern void init( int procs );
    1717        extern void clean( void );
    1818};
  • libcfa/src/concurrency/coroutine.cfa

    rb3c8496 r53449a4  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct 23 23:05:24 2020
    13 // Update Count     : 22
     12// Last Modified On : Tue Dec 15 12:06:04 2020
     13// Update Count     : 23
    1414//
    1515
     
    2828#include "kernel_private.hfa"
    2929#include "exception.hfa"
     30#include "math.hfa"
     31
     32#define CFA_COROUTINE_USE_MMAP 0
    3033
    3134#define __CFA_INVOKE_PRIVATE__
     
    8588static const size_t MinStackSize = 1000;
    8689extern size_t __page_size;                              // architecture pagesize HACK, should go in proper runtime singleton
     90extern int __map_prot;
    8791
    8892void __stack_prepare( __stack_info_t * this, size_t create_size );
     93void __stack_clean  ( __stack_info_t * this );
    8994
    9095//-----------------------------------------------------------------------------
     
    107112        bool userStack = ((intptr_t)this.storage & 0x1) != 0;
    108113        if ( ! userStack && this.storage ) {
    109                 __attribute__((may_alias)) intptr_t * istorage = (intptr_t *)&this.storage;
    110                 *istorage &= (intptr_t)-1;
    111 
    112                 void * storage = this.storage->limit;
    113                 __cfaabi_dbg_debug_do(
    114                         storage = (char*)(storage) - __page_size;
    115                         if ( mprotect( storage, __page_size, PROT_READ | PROT_WRITE ) == -1 ) {
    116                                 abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
    117                         }
    118                 );
    119                 __cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage);
    120                 free( storage );
     114                __stack_clean( &this );
    121115        }
    122116}
     
    167161        assert(__page_size != 0l);
    168162        size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
     163        size = ceiling(size, __page_size);
    169164
    170165        // If we are running debug, we also need to allocate a guardpage to catch stack overflows.
    171166        void * storage;
    172         __cfaabi_dbg_debug_do(
    173                 storage = memalign( __page_size, size + __page_size );
    174         );
    175         __cfaabi_dbg_no_debug_do(
    176                 storage = (void*)malloc(size);
    177         );
    178 
     167        #if CFA_COROUTINE_USE_MMAP
     168                storage = mmap(0p, size + __page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
     169                if(storage == ((void*)-1)) {
     170                        abort( "coroutine stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) );
     171                }
     172                if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
     173                        abort( "coroutine stack creation : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
     174                } // if
     175                storage = (void *)(((intptr_t)storage) + __page_size);
     176        #else
     177                __cfaabi_dbg_debug_do(
     178                        storage = memalign( __page_size, size + __page_size );
     179                );
     180                __cfaabi_dbg_no_debug_do(
     181                        storage = (void*)malloc(size);
     182                );
     183
     184                __cfaabi_dbg_debug_do(
     185                        if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
     186                                abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) );
     187                        }
     188                        storage = (void *)(((intptr_t)storage) + __page_size);
     189                );
     190        #endif
    179191        __cfaabi_dbg_print_safe("Kernel : Created stack %p of size %zu\n", storage, size);
    180         __cfaabi_dbg_debug_do(
    181                 if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {
    182                         abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) );
    183                 }
    184                 storage = (void *)(((intptr_t)storage) + __page_size);
    185         );
    186192
    187193        verify( ((intptr_t)storage & (libAlign() - 1)) == 0ul );
    188194        return [storage, size];
     195}
     196
     197void __stack_clean  ( __stack_info_t * this ) {
     198        size_t size = ((intptr_t)this->storage->base) - ((intptr_t)this->storage->limit) + sizeof(__stack_t);
     199        void * storage = this->storage->limit;
     200
     201        #if CFA_COROUTINE_USE_MMAP
     202                storage = (void *)(((intptr_t)storage) - __page_size);
     203                if(munmap(storage, size + __page_size) == -1) {
     204                        abort( "coroutine stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) );
     205                }
     206        #else
     207                __cfaabi_dbg_debug_do(
     208                        storage = (char*)(storage) - __page_size;
     209                        if ( mprotect( storage, __page_size, __map_prot ) == -1 ) {
     210                                abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
     211                        }
     212                );
     213
     214                free( storage );
     215        #endif
     216        __cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage);
    189217}
    190218
     
    210238        assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %zd bytes for a stack.", size, MinStackSize );
    211239
    212         this->storage = (__stack_t *)((intptr_t)storage + size);
     240        this->storage = (__stack_t *)((intptr_t)storage + size - sizeof(__stack_t));
    213241        this->storage->limit = storage;
    214         this->storage->base  = (void*)((intptr_t)storage + size);
     242        this->storage->base  = (void*)((intptr_t)storage + size - sizeof(__stack_t));
    215243        this->storage->exception_context.top_resume = 0p;
    216244        this->storage->exception_context.current_exception = 0p;
  • libcfa/src/concurrency/coroutine.hfa

    rb3c8496 r53449a4  
    102102}
    103103
    104 extern void __stack_prepare   ( __stack_info_t * this, size_t size /* ignored if storage already allocated */);
     104extern void __stack_prepare( __stack_info_t * this, size_t size /* ignored if storage already allocated */);
     105extern void __stack_clean  ( __stack_info_t * this );
     106
    105107
    106108// Suspend implementation inlined for performance
     
    142144
    143145        if( unlikely(dst->context.SP == 0p) ) {
    144                 active_thread()->curr_cor = dst;
    145146                __stack_prepare(&dst->stack, 65000);
    146147                __cfactx_start(main, dst, cor, __cfactx_invoke_coroutine);
    147                 active_thread()->curr_cor = src;
    148148        }
    149149
  • libcfa/src/concurrency/io/setup.cfa

    rb3c8496 r53449a4  
    1717#define _GNU_SOURCE         /* See feature_test_macros(7) */
    1818
     19#if defined(__CFA_DEBUG__)
     20        // #define __CFA_DEBUG_PRINT_IO__
     21        // #define __CFA_DEBUG_PRINT_IO_CORE__
     22#endif
     23
    1924#include "io/types.hfa"
    2025#include "kernel.hfa"
     
    111116
    112117        void __kernel_io_startup(void) {
    113                 __cfaabi_dbg_print_safe( "Kernel : Creating EPOLL instance\n" );
     118                __cfadbg_print_safe(io_core, "Kernel : Creating EPOLL instance\n" );
    114119
    115120                iopoll.epollfd = epoll_create1(0);
     
    118123                }
    119124
    120                 __cfaabi_dbg_print_safe( "Kernel : Starting io poller thread\n" );
     125                __cfadbg_print_safe(io_core, "Kernel : Starting io poller thread\n" );
    121126
    122127                iopoll.run = true;
     
    132137                // Wait for the io poller thread to finish
    133138
    134                 pthread_join( iopoll.thrd, 0p );
    135                 free( iopoll.stack );
     139                __destroy_pthread( iopoll.thrd, iopoll.stack, 0p );
    136140
    137141                int ret = close(iopoll.epollfd);
     
    142146                // Io polling is now fully stopped
    143147
    144                 __cfaabi_dbg_print_safe( "Kernel : IO poller stopped\n" );
     148                __cfadbg_print_safe(io_core, "Kernel : IO poller stopped\n" );
    145149        }
    146150
     
    150154                id.id = doregister(&id);
    151155                __cfaabi_tls.this_proc_id = &id;
    152                 __cfaabi_dbg_print_safe( "Kernel : IO poller thread starting\n" );
     156                __cfadbg_print_safe(io_core, "Kernel : IO poller thread starting\n" );
    153157
    154158                // Block signals to control when they arrive
     
    185189                }
    186190
    187                 __cfaabi_dbg_print_safe( "Kernel : IO poller thread stopping\n" );
     191                __cfadbg_print_safe(io_core, "Kernel : IO poller thread stopping\n" );
    188192                unregister(&id);
    189193                return 0p;
  • libcfa/src/concurrency/kernel/startup.cfa

    rb3c8496 r53449a4  
    2929#include "kernel_private.hfa"
    3030#include "startup.hfa"          // STARTUP_PRIORITY_XXX
     31#include "math.hfa"
     32
     33#define CFA_PROCESSOR_USE_MMAP 0
    3134
    3235//-----------------------------------------------------------------------------
     
    114117}
    115118
    116 size_t __page_size = 0;
     119extern size_t __page_size;
    117120
    118121//-----------------------------------------------------------------------------
     
    158161        /* paranoid */ verify( ! __preemption_enabled() );
    159162        __cfadbg_print_safe(runtime_core, "Kernel : Starting\n");
    160 
    161         __page_size = sysconf( _SC_PAGESIZE );
    162163
    163164        __cfa_dbg_global_clusters.list{ __get };
     
    539540}
    540541
     542extern size_t __page_size;
    541543void ^?{}(processor & this) with( this ){
    542544        if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) {
     
    550552        }
    551553
    552         int err = pthread_join( kernel_thread, 0p );
    553         if( err != 0 ) abort("KERNEL ERROR: joining processor %p caused error %s\n", &this, strerror(err));
    554 
    555         free( this.stack );
     554        __destroy_pthread( kernel_thread, this.stack, 0p );
    556555
    557556        disable_interrupts();
     
    678677
    679678        void * stack;
    680         __cfaabi_dbg_debug_do(
    681                 stack = memalign( __page_size, stacksize + __page_size );
    682                 // pthread has no mechanism to create the guard page in user supplied stack.
     679        #if CFA_PROCESSOR_USE_MMAP
     680                stacksize = ceiling( stacksize, __page_size ) + __page_size;
     681                stack = mmap(0p, stacksize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
     682                if(stack == ((void*)-1)) {
     683                        abort( "pthread stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) );
     684                }
    683685                if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) {
    684                         abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
     686                        abort( "pthread stack creation : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
    685687                } // if
    686         );
    687         __cfaabi_dbg_no_debug_do(
    688                 stack = malloc( stacksize );
    689         );
     688        #else
     689                __cfaabi_dbg_debug_do(
     690                        stack = memalign( __page_size, stacksize + __page_size );
     691                        // pthread has no mechanism to create the guard page in user supplied stack.
     692                        if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) {
     693                                abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
     694                        } // if
     695                );
     696                __cfaabi_dbg_no_debug_do(
     697                        stack = malloc( stacksize );
     698                );
     699        #endif
     700
    690701
    691702        check( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
     
    694705        return stack;
    695706}
     707
     708void __destroy_pthread( pthread_t pthread, void * stack, void ** retval ) {
     709        int err = pthread_join( pthread, retval );
     710        if( err != 0 ) abort("KERNEL ERROR: joining pthread %p caused error %s\n", (void*)pthread, strerror(err));
     711
     712        #if CFA_PROCESSOR_USE_MMAP
     713                pthread_attr_t attr;
     714
     715                check( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
     716
     717                size_t stacksize;
     718                // default stack size, normally defined by shell limit
     719                check( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
     720                assert( stacksize >= PTHREAD_STACK_MIN );
     721                stacksize += __page_size;
     722
     723                if(munmap(stack, stacksize) == -1) {
     724                        abort( "pthread stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) );
     725                }
     726        #else
     727                free( stack );
     728        #endif
     729}
     730
    696731
    697732#if defined(__CFA_WITH_VERIFY__)
  • libcfa/src/concurrency/kernel_private.hfa

    rb3c8496 r53449a4  
    4949
    5050void * __create_pthread( pthread_t *, void * (*)(void *), void * );
     51void __destroy_pthread( pthread_t pthread, void * stack, void ** retval );
    5152
    5253
  • libcfa/src/concurrency/preemption.cfa

    rb3c8496 r53449a4  
    575575        // Wait for the preemption thread to finish
    576576
    577         pthread_join( alarm_thread, 0p );
    578         free( alarm_stack );
     577        __destroy_pthread( alarm_thread, alarm_stack, 0p );
    579578
    580579        // Preemption is now fully stopped
  • libcfa/src/heap.cfa

    rb3c8496 r53449a4  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep  7 22:17:46 2020
    13 // Update Count     : 957
     12// Last Modified On : Wed Dec 16 12:28:25 2020
     13// Update Count     : 1023
    1414//
    1515
    1616#include <unistd.h>                                                                             // sbrk, sysconf
     17#include <stdlib.h>                                                                             // EXIT_FAILURE
    1718#include <stdbool.h>                                                                    // true, false
    1819#include <stdio.h>                                                                              // snprintf, fileno
     
    7172        // Define the default extension heap amount in units of bytes. When the uC++ supplied heap reaches the brk address,
    7273        // the brk address is extended by the extension amount.
    73         __CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),
     74        __CFA_DEFAULT_HEAP_EXPANSION__ = (10 * 1024 * 1024),
    7475
    7576        // Define the mmap crossover point during allocation. Allocations less than this amount are allocated from buckets;
     
    115116
    116117// statically allocated variables => zero filled.
    117 static size_t pageSize;                                                                 // architecture pagesize
     118size_t __page_size;                                                                             // architecture pagesize
     119int __map_prot;                                                                                 // common mmap/mprotect protection
    118120static size_t heapExpand;                                                               // sbrk advance
    119121static size_t mmapStart;                                                                // cross over point for mmap
     
    249251#endif // FASTLOOKUP
    250252
    251 static int mmapFd = -1;                                                                 // fake or actual fd for anonymous file
     253static const off_t mmapFd = -1;                                                 // fake or actual fd for anonymous file
    252254#ifdef __CFA_DEBUG__
    253255static bool heapBoot = 0;                                                               // detect recursion during boot
     
    374376
    375377static inline bool setMmapStart( size_t value ) {               // true => mmapped, false => sbrk
    376   if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return false;
     378  if ( value < __page_size || bucketSizes[NoBucketSizes - 1] < value ) return false;
    377379        mmapStart = value;                                                                      // set global
    378380
     
    436438        header = headerAddr( addr );
    437439
    438   if ( unlikely( heapEnd < addr ) ) {                                   // mmapped ?
     440  if ( unlikely( addr < heapBegin || heapEnd < addr ) ) { // mmapped ?
    439441                fakeHeader( header, alignment );
    440442                size = header->kind.real.blockSize & -3;                // mmap size
     
    443445
    444446        #ifdef __CFA_DEBUG__
    445         checkHeader( addr < heapBegin, name, addr );            // bad low address ?
     447        checkHeader( header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
    446448        #endif // __CFA_DEBUG__
    447449
     
    464466} // headers
    465467
     468#ifdef __CFA_DEBUG__
     469#if __SIZEOF_POINTER__ == 4
     470#define MASK 0xdeadbeef
     471#else
     472#define MASK 0xdeadbeefdeadbeef
     473#endif
     474#define STRIDE size_t
     475
     476static void * Memset( void * addr, STRIDE size ) {              // debug only
     477        if ( size % sizeof(STRIDE) != 0 ) abort( "Memset() : internal error, size %zd not multiple of %zd.", size, sizeof(STRIDE) );
     478        if ( (STRIDE)addr % sizeof(STRIDE) != 0 ) abort( "Memset() : internal error, addr %p not multiple of %zd.", addr, sizeof(STRIDE) );
     479
     480        STRIDE * end = (STRIDE *)addr + size / sizeof(STRIDE);
     481        for ( STRIDE * p = (STRIDE *)addr; p < end; p += 1 ) *p = MASK;
     482        return addr;
     483} // Memset
     484#endif // __CFA_DEBUG__
     485
     486
    466487#define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes."
    467488
     
    472493                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    473494
    474                 size_t increase = ceiling2( size > heapExpand ? size : heapExpand, libAlign() );
     495                size_t increase = ceiling2( size > heapExpand ? size : heapExpand, __page_size );
     496                // Do not call abort or strerror( errno ) as they may call malloc.
    475497                if ( sbrk( increase ) == (void *)-1 ) {                 // failed, no memory ?
    476498                        unlock( extlock );
    477                         abort( NO_MEMORY_MSG, size );                           // give up
     499                        __cfaabi_bits_print_nolock( STDERR_FILENO, NO_MEMORY_MSG, size );
     500                        _exit( EXIT_FAILURE );
     501                } // if
     502                if ( mprotect( (char *)heapEnd + heapRemaining, increase, __map_prot ) ) {
     503                        unlock( extlock );
     504                        __cfaabi_bits_print_nolock( STDERR_FILENO, "extend() : internal error, mprotect failure, heapEnd:%p size:%zd, errno:%d.\n", heapEnd, increase, errno );
     505                        _exit( EXIT_FAILURE );
    478506                } // if
    479507                #ifdef __STATISTICS__
     
    483511                #ifdef __CFA_DEBUG__
    484512                // Set new memory to garbage so subsequent uninitialized usages might fail.
    485                 memset( (char *)heapEnd + heapRemaining, '\377', increase );
     513                memset( (char *)heapEnd + heapRemaining, '\xde', increase );
     514                //Memset( (char *)heapEnd + heapRemaining, increase );
    486515                #endif // __CFA_DEBUG__
    487516                rem = heapRemaining + increase - size;
     
    542571                block->header.kind.real.home = freeElem;                // pointer back to free list of apropriate size
    543572        } else {                                                                                        // large size => mmap
    544   if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p;
    545                 tsize = ceiling2( tsize, pageSize );                    // must be multiple of page size
     573  if ( unlikely( size > ULONG_MAX - __page_size ) ) return 0p;
     574                tsize = ceiling2( tsize, __page_size );                 // must be multiple of page size
    546575                #ifdef __STATISTICS__
    547576                __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );
     
    549578                #endif // __STATISTICS__
    550579
    551                 block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
     580                block = (HeapManager.Storage *)mmap( 0, tsize, __map_prot, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
    552581                if ( block == (HeapManager.Storage *)MAP_FAILED ) { // failed ?
    553582                        if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); // no memory
    554583                        // Do not call strerror( errno ) as it may call malloc.
    555                         abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu error:%d.", &heapManager, tsize, errno );
     584                        abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu errno:%d.", &heapManager, tsize, errno );
    556585                } //if
    557586                #ifdef __CFA_DEBUG__
    558587                // Set new memory to garbage so subsequent uninitialized usages might fail.
    559                 memset( block, '\377', tsize );
     588                memset( block, '\xde', tsize );
     589                //Memset( block, tsize );
    560590                #endif // __CFA_DEBUG__
    561591                block->header.kind.real.blockSize = tsize;              // storage size for munmap
     
    597627                #endif // __STATISTICS__
    598628                if ( munmap( header, size ) == -1 ) {
    599                         #ifdef __CFA_DEBUG__
    600629                        abort( "Attempt to deallocate storage %p not allocated or with corrupt header.\n"
    601630                                   "Possible cause is invalid pointer.",
    602631                                   addr );
    603                         #endif // __CFA_DEBUG__
    604632                } // if
    605633        } else {
    606634                #ifdef __CFA_DEBUG__
    607635                // Set free memory to garbage so subsequent usages might fail.
    608                 memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) );
     636                memset( ((HeapManager.Storage *)header)->data, '\xde', freeElem->blockSize - sizeof( HeapManager.Storage ) );
     637                //Memset( ((HeapManager.Storage *)header)->data, freeElem->blockSize - sizeof( HeapManager.Storage ) );
    609638                #endif // __CFA_DEBUG__
    610639
     
    648677                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
    649678                #else
    650                 // for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; p = (p)`next->top ) {
     679                        for(;;) {
     680//              for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; p = (p)`next->top ) {
    651681//              for ( HeapManager.Storage * p = top( freeLists[i].freeList ); p != 0p; /* p = getNext( p )->top */) {
    652                 for ( HeapManager.Storage * p ;; /* p = getNext( p )->top */) {
    653                         HeapManager.Storage * temp = p->header.kind.real.next.top; // FIX ME: direct assignent fails, initialization works`
     682//                      HeapManager.Storage * temp = p->header.kind.real.next.top; // FIX ME: direct assignent fails, initialization works`
    654683//                      typeof(p) temp = (( p )`next)->top;                     // FIX ME: direct assignent fails, initialization works`
    655684//                      p = temp;
     
    675704
    676705static void ?{}( HeapManager & manager ) with( manager ) {
    677         pageSize = sysconf( _SC_PAGESIZE );
     706        __page_size = sysconf( _SC_PAGESIZE );
     707        __map_prot = PROT_READ | PROT_WRITE | PROT_EXEC;
    678708
    679709        for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
     
    695725
    696726        char * end = (char *)sbrk( 0 );
    697         heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
     727        heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, __page_size ) - end ); // move start of heap to multiple of alignment
    698728} // HeapManager
    699729
     
    713743        #ifdef __CFA_DEBUG__
    714744        if ( heapBoot ) {                                                                       // check for recursion during system boot
    715                 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    716745                abort( "boot() : internal error, recursively invoked during system boot." );
    717746        } // if
     
    935964                        header->kind.real.size = size;                          // reset allocation size
    936965                        if ( unlikely( ozfill ) && size > osize ) {     // previous request zero fill and larger ?
    937                                 memset( (char *)oaddr + osize, (int)'\0', size - osize ); // initialize added storage
     966                                memset( (char *)oaddr + osize, '\0', size - osize ); // initialize added storage
    938967                        } // if
    939968                        return oaddr;
     
    960989                        header->kind.real.blockSize |= 2;                       // mark new request as zero filled
    961990                        if ( size > osize ) {                                           // previous request larger ?
    962                                 memset( (char *)naddr + osize, (int)'\0', size - osize ); // initialize added storage
     991                                memset( (char *)naddr + osize, '\0', size - osize ); // initialize added storage
    963992                        } // if
    964993                } // if
     
    9991028                return cmemalignNoStats( alignment, dim, elemSize );
    10001029        } // cmemalign
     1030
    10011031
    10021032        // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple
     
    10171047        } // posix_memalign
    10181048
     1049
    10191050        // Allocates size bytes and returns a pointer to the allocated memory. The memory address shall be a multiple of the
    10201051        // page size.  It is equivalent to memalign(sysconf(_SC_PAGESIZE),size).
    10211052        void * valloc( size_t size ) {
    1022                 return memalign( pageSize, size );
     1053                return memalign( __page_size, size );
    10231054        } // valloc
    10241055
     
    10261057        // Same as valloc but rounds size to multiple of page size.
    10271058        void * pvalloc( size_t size ) {
    1028                 return memalign( pageSize, ceiling2( size, pageSize ) );
     1059                return memalign( __page_size, ceiling2( size, __page_size ) );
    10291060        } // pvalloc
    10301061
     
    11651196                choose( option ) {
    11661197                  case M_TOP_PAD:
    1167                         heapExpand = ceiling2( value, pageSize ); return 1;
     1198                        heapExpand = ceiling2( value, __page_size ); return 1;
    11681199                  case M_MMAP_THRESHOLD:
    11691200                        if ( setMmapStart( value ) ) return 1;
     
    13271358                header->kind.real.blockSize |= 2;                               // mark new request as zero filled
    13281359                if ( size > osize ) {                                                   // previous request larger ?
    1329                         memset( (char *)naddr + osize, (int)'\0', size - osize ); // initialize added storage
     1360                        memset( (char *)naddr + osize, '\0', size - osize ); // initialize added storage
    13301361                } // if
    13311362        } // if
  • libcfa/src/stdlib.hfa

    rb3c8496 r53449a4  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Dec  8 18:27:22 2020
    13 // Update Count     : 524
     12// Last Modified On : Sat Dec 12 13:52:34 2020
     13// Update Count     : 536
    1414//
    1515
     
    4949
    5050static inline forall( dtype T | sized(T) ) {
    51         // Cforall safe equivalents, i.e., implicit size specification
     51        // CFA safe equivalents, i.e., implicit size specification
    5252
    5353        T * malloc( void ) {
     
    234234
    235235static inline forall( dtype T | sized(T) ) {
    236         // Cforall safe initialization/copy, i.e., implicit size specification, non-array types
     236        // CFA safe initialization/copy, i.e., implicit size specification, non-array types
    237237        T * memset( T * dest, char fill ) {
    238238                return (T *)memset( dest, fill, sizeof(T) );
     
    243243        } // memcpy
    244244
    245         // Cforall safe initialization/copy, i.e., implicit size specification, array types
     245        // CFA safe initialization/copy, i.e., implicit size specification, array types
    246246        T * amemset( T dest[], char fill, size_t dim ) {
    247247                return (T *)(void *)memset( dest, fill, dim * sizeof(T) ); // C memset
     
    253253} // distribution
    254254
    255 // Cforall deallocation for multiple objects
     255// CFA deallocation for multiple objects
     256static inline forall( dtype T )                                                 // FIX ME, problems with 0p in list
     257void free( T * ptr ) {
     258        free( (void *)ptr );                                                            // C free
     259} // free
    256260static inline forall( dtype T, ttype TT | { void free( TT ); } )
    257 void free( T * addr, TT rest ) {
    258         free( ( void *)addr );                                                          // use C free
     261void free( T * ptr, TT rest ) {
     262        free( ptr );
    259263        free( rest );
    260264} // free
    261265
    262 // Cforall allocation/deallocation and constructor/destructor, non-array types
     266// CFA allocation/deallocation and constructor/destructor, non-array types
    263267static inline forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } )
    264268T * new( TT p ) {
     
    272276                ^(*ptr){};                                                                              // run destructor
    273277        } // if
    274         free( ptr );
     278        free( ptr );                                                                            // always call free
    275279} // delete
    276 
    277280static inline forall( dtype T, ttype TT | { void ^?{}( T & ); void delete( TT ); } )
    278281void delete( T * ptr, TT rest ) {
     
    281284} // delete
    282285
    283 // Cforall allocation/deallocation and constructor/destructor, array types
     286// CFA allocation/deallocation and constructor/destructor, array types
    284287forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } ) T * anew( size_t dim, TT p );
    285288forall( dtype T | sized(T) | { void ^?{}( T & ); } ) void adelete( T arr[] );
  • src/AST/Convert.cpp

    rb3c8496 r53449a4  
    5555
    5656// these need to be accessed in new FixInit now
    57 ast::Type * sizeType = nullptr;
    58 ast::FunctionDecl * dereferenceOperator = nullptr;
    59 ast::StructDecl   * dtorStruct = nullptr;
    60 ast::FunctionDecl * dtorStructDestroy = nullptr;
     57ast::ptr<ast::Type> sizeType = nullptr;
     58const ast::FunctionDecl * dereferenceOperator = nullptr;
     59const ast::StructDecl   * dtorStruct = nullptr;
     60const ast::FunctionDecl * dtorStructDestroy = nullptr;
    6161
    6262}
     
    205205                ftype->parameters = get<DeclarationWithType>().acceptL(node->params);
    206206
    207                 ftype->forall = get<TypeDecl>().acceptL( node->type->forall );
     207                ftype->forall = get<TypeDecl>().acceptL( node->type_params );
     208                if (!node->assertions.empty()) {
     209                        assert(!ftype->forall.empty());
     210                        // find somewhere to place assertions back, for convenience it is the last slot
     211                        ftype->forall.back()->assertions = get<DeclarationWithType>().acceptL(node->assertions);
     212                }
    208213
    209214                visitType(node->type, ftype);
     
    233238        const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) {
    234239                // base comes from constructor
    235                 decl->parameters = get<TypeDecl>().acceptL( node->params );
    236240                decl->assertions = get<DeclarationWithType>().acceptL( node->assertions );
    237241                declPostamble( decl, node );
     
    603607
    604608                for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) {
    605                         rslt->add( src_i->first,
     609                        rslt->add( src_i->first.typeString(),
    606610                                   get<Type>().accept1(src_i->second) );
    607                 }
    608 
    609                 for (decltype(src->beginVar()) src_i = src->beginVar(); src_i != src->endVar(); src_i++) {
    610                         rslt->addVar( src_i->first,
    611                                       get<Expression>().accept1(src_i->second) );
    612611                }
    613612
     
    12131212                // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
    12141213                // ty->parameters = get<DeclarationWithType>().acceptL( node->params );
    1215                 ty->forall = get<TypeDecl>().acceptL( node->forall );
     1214
     1215                auto types = get<TypeInstType>().acceptL( node->forall );
     1216                for (auto t : types) {
     1217                        auto newT = new TypeDecl(*t->baseType);
     1218                        newT->name = t->name; // converted by typeString()
     1219                        for (auto asst : newT->assertions) delete asst;
     1220                        newT->assertions.clear();
     1221                        ty->forall.push_back(newT);
     1222                }
     1223                auto assts = get<VariableExpr>().acceptL( node->assertions );
     1224                if (!assts.empty()) {
     1225                        assert(!types.empty());
     1226                        for (auto asst : assts) {
     1227                                auto newDecl = new ObjectDecl(*strict_dynamic_cast<ObjectDecl*>(asst->var));
     1228                                delete newDecl->type;
     1229                                newDecl->type = asst->result->clone();
     1230                                newDecl->storageClasses.is_extern = true; // hack
     1231                                ty->forall.back()->assertions.push_back(newDecl);
     1232                        }
     1233                }
     1234
    12161235                return visitType( node, ty );
    12171236        }
    12181237
    12191238        const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) {
    1220                 ty->forall = get<TypeDecl>().acceptL( old->forall );
    12211239                ty->parameters = get<Expression>().acceptL( old->params );
    12221240                ty->hoistType = old->hoistType;
     
    13011319                        ty = new TypeInstType{
    13021320                                cv( node ),
    1303                                 node->name,
     1321                                node->typeString(),
    13041322                                get<TypeDecl>().accept1( node->base ),
    13051323                                get<Attribute>().acceptL( node->attributes )
     
    13081326                        ty = new TypeInstType{
    13091327                                cv( node ),
    1310                                 node->name,
     1328                                node->typeString(),
    13111329                                node->kind == ast::TypeDecl::Ftype,
    13121330                                get<Attribute>().acceptL( node->attributes )
     
    14331451        /// at conversion stage, all created nodes are guaranteed to be unique, therefore
    14341452        /// const_casting out of smart pointers is permitted.
    1435         std::unordered_map< const BaseSyntaxNode *, ast::ptr<ast::Node> > cache = {};
     1453        std::unordered_map< const BaseSyntaxNode *, ast::readonly<ast::Node> > cache = {};
    14361454
    14371455        // Local Utilities:
     
    15671585                // can function type have attributes? seems not to be the case.
    15681586                // visitType(old->type, ftype);
     1587
     1588                // collect assertions and put directly in FunctionDecl
     1589                std::vector<ast::ptr<ast::DeclWithType>> assertions;
     1590                for (auto & param: forall) {
     1591                        for (auto & asst: param->assertions) {
     1592                                assertf(asst->unique(), "newly converted decl must be unique");
     1593                                assertions.emplace_back(asst);
     1594                        }
     1595                        auto mut = param.get_and_mutate();
     1596                        assertf(mut == param, "newly converted decl must be unique");
     1597                        mut->assertions.clear();
     1598                }
    15691599
    15701600                auto decl = new ast::FunctionDecl{
     
    15861616                cache.emplace( old, decl );
    15871617
     1618                decl->assertions = std::move(assertions);
    15881619                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    15891620                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
     
    17041735                cache.emplace( old, decl );
    17051736                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
    1706                 decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
    17071737                decl->extension  = old->extension;
    17081738                decl->uniqueId   = old->uniqueId;
     
    17201750                );
    17211751                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
    1722                 decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
    17231752                decl->extension  = old->extension;
    17241753                decl->uniqueId   = old->uniqueId;
     
    20702099        }
    20712100
     2101        // TypeSubstitution shouldn't exist yet in old.
    20722102        ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
    2073 
     2103               
    20742104                if (!old) return nullptr;
    2075 
     2105                if (old->empty()) return nullptr;
     2106                assert(false);
     2107
     2108                /*
    20762109                ast::TypeSubstitution *rslt = new ast::TypeSubstitution();
    20772110
     
    20812114                }
    20822115
    2083                 for (decltype(old->beginVar()) old_i = old->beginVar(); old_i != old->endVar(); old_i++) {
    2084                         rslt->addVar( old_i->first,
    2085                                       getAccept1<ast::Expr>(old_i->second) );
    2086                 }
    2087 
    20882116                return rslt;
     2117                */
    20892118        }
    20902119
     
    26142643                        ty->params.emplace_back(v->get_type());
    26152644                }
    2616                 ty->forall = GET_ACCEPT_V( forall, TypeDecl );
     2645                // xxx - when will this be non-null?
     2646                // will have to create dangling (no-owner) decls to be pointed to
     2647                auto foralls = GET_ACCEPT_V( forall, TypeDecl );
     2648
     2649                for (auto & param : foralls) {
     2650                        ty->forall.emplace_back(new ast::TypeInstType(param->name, param));
     2651                        for (auto asst : param->assertions) {
     2652                                ty->assertions.emplace_back(new ast::VariableExpr({}, asst));
     2653                        }
     2654                }
    26172655                visitType( old, ty );
    26182656        }
    26192657
    26202658        void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) {
    2621                 ty->forall = GET_ACCEPT_V( forall, TypeDecl );
    26222659                ty->params = GET_ACCEPT_V( parameters, Expr );
    26232660                ty->hoistType = old->hoistType;
     
    28072844        ConverterOldToNew c;
    28082845        ast::TranslationUnit unit;
     2846        if (Validate::SizeType) {
     2847                // this should be a BasicType.
     2848                auto old = strict_dynamic_cast<BasicType *>(Validate::SizeType);
     2849                ast::sizeType = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind };
     2850        }
     2851
    28092852        for(auto d : translationUnit) {
    28102853                d->accept( c );
  • src/AST/Decl.cpp

    rb3c8496 r53449a4  
    5050
    5151FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name,
    52                 std::vector<ptr<TypeDecl>>&& forall,
    53                 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    54                 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
    55                 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
    56         : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
    57           stmts( stmts ) {
    58                   FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs));
    59                   for (auto & param : this->params) {
    60                           ftype->params.emplace_back(param->get_type());
    61                   }
    62                   for (auto & ret : this->returns) {
    63                           ftype->returns.emplace_back(ret->get_type());
    64                   }
    65                   ftype->forall = std::move(forall);
    66                   this->type = ftype;
    67           }
     52        std::vector<ptr<TypeDecl>>&& forall,
     53        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
     54        CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
     55        std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
     56: DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     57        type_params(std::move(forall)), stmts( stmts ) {
     58        FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs));
     59        for (auto & param : this->params) {
     60                ftype->params.emplace_back(param->get_type());
     61        }
     62        for (auto & ret : this->returns) {
     63                ftype->returns.emplace_back(ret->get_type());
     64        }
     65        for (auto & tp : this->type_params) {
     66                ftype->forall.emplace_back(new TypeInstType(tp->name, tp));
     67        }
     68        this->type = ftype;
     69}
    6870
    6971
  • src/AST/Decl.hpp

    rb3c8496 r53449a4  
    132132        std::vector< ptr<Expr> > withExprs;
    133133
     134        std::vector<ptr<TypeDecl>> type_params;
     135        std::vector<ptr<DeclWithType>> assertions;
     136
    134137        FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
    135138                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
     
    154157public:
    155158        ptr<Type> base;
    156         std::vector<ptr<TypeDecl>> params;
    157159        std::vector<ptr<DeclWithType>> assertions;
    158160
     
    160162                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
    161163                const Type * b, Linkage::Spec spec = Linkage::Cforall )
    162         : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {}
     164        : Decl( loc, name, storage, spec ), base( b ), assertions() {}
    163165
    164166        /// Produces a name for the kind of alias
  • src/AST/Expr.cpp

    rb3c8496 r53449a4  
    206206        assert( aggregate->result );
    207207
    208         // Deep copy on result type avoids mutation on transitively multiply referenced object.
    209         //
    210         // Example, adapted from parts of builtins and bootloader:
    211         //
    212         // forall(dtype T)
    213         // struct __Destructor {
    214         //   T * object;
    215         //   void (*dtor)(T *);
    216         // };
    217         //
    218         // forall(dtype S)
    219         // void foo(__Destructor(S) &d) {
    220         //   if (d.dtor) {  // here
    221         //   }
    222         // }
    223         //
    224         // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve.  Let d be the
    225         // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level
    226         // declaration of __Destructor.  Consider the types e.result and d.type.  In the old AST, one
    227         // is a clone of the other.  Ordinary new-AST use would set them up as a multiply-referenced
    228         // object.
    229         //
    230         // e.result: PointerType
    231         // .base: FunctionType
    232         // .params.front(): ObjectDecl, the anonymous parameter of type T*
    233         // .type: PointerType
    234         // .base: TypeInstType
    235         // let x = that
    236         // let y = similar, except start from d.type
    237         //
    238         // Consider two code lines down, genericSubstitution(...).apply(result).
    239         //
    240         // Applying this chosen-candidate's type substitution means modifying x, substituting
    241         // S for T.  This mutation should affect x and not y.
    242 
    243         result = deepCopy(mem->get_type());
     208        result = mem->get_type();
    244209
    245210        // substitute aggregate generic parameters into member type
  • src/AST/Expr.hpp

    rb3c8496 r53449a4  
    112112
    113113                bool hasSlots() const { return data.resnSlots; }
     114                bool hasParams() const { return data.inferParams; }
    114115
    115116                ResnSlots& resnSlots() {
  • src/AST/Fwd.hpp

    rb3c8496 r53449a4  
    139139struct TranslationUnit;
    140140// TODO: Get from the TranslationUnit:
    141 extern Type * sizeType;
    142 extern FunctionDecl * dereferenceOperator;
    143 extern StructDecl   * dtorStruct;
    144 extern FunctionDecl * dtorStructDestroy;
     141extern ptr<Type> sizeType;
     142extern const FunctionDecl * dereferenceOperator;
     143extern const StructDecl   * dtorStruct;
     144extern const FunctionDecl * dtorStructDestroy;
    145145
    146146}
  • src/AST/Pass.hpp

    rb3c8496 r53449a4  
    3434
    3535#include "AST/SymbolTable.hpp"
    36 
    37 #include "AST/ForallSubstitutionTable.hpp"
    3836
    3937// Private prelude header, needed for some of the magic tricks this class pulls off
     
    6664// | WithVisitorRef        - provides an pointer to the templated visitor wrapper
    6765// | WithSymbolTable       - provides symbol table functionality
    68 // | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation
    6966//
    7067// Other Special Members:
     
    258255        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    259256
    260         /// Mutate forall-list, accounting for presence of type substitution map
    261         template<typename node_t>
    262         void mutate_forall( const node_t *& );
    263 
    264257public:
    265258        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     
    287280        /// Internal RAII guard for forall substitutions
    288281        struct guard_forall_subs {
    289                 guard_forall_subs( Pass<core_t> & pass, const ParameterizedType * type )
     282                guard_forall_subs( Pass<core_t> & pass, const FunctionType * type )
    290283                : pass( pass ), type( type ) { __pass::forall::enter(pass.core, 0, type ); }
    291284                ~guard_forall_subs()         { __pass::forall::leave(pass.core, 0, type ); }
    292285                Pass<core_t> & pass;
    293                 const ParameterizedType * type;
     286                const FunctionType * type;
    294287        };
    295288
     
    398391};
    399392
    400 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
    401 struct WithForallSubstitutor {
    402         ForallSubstitutionTable subs;
    403 };
    404 
    405393}
    406394
  • src/AST/Pass.impl.hpp

    rb3c8496 r53449a4  
    367367        }
    368368
    369 
    370         template< typename core_t >
    371         template< typename node_t >
    372         void ast::Pass< core_t >::mutate_forall( const node_t *& node ) {
    373                 if ( auto subs = __pass::forall::subs( core, 0 ) ) {
    374                         // tracking TypeDecl substitution, full clone
    375                         if ( node->forall.empty() ) return;
    376 
    377                         node_t * mut = __pass::mutate<core_t>( node );
    378                         mut->forall = subs->clone( node->forall, *this );
    379                         node = mut;
    380                 } else {
    381                         // not tracking TypeDecl substitution, just mutate
    382                         maybe_accept( node, &node_t::forall );
    383                 }
    384         }
    385369}
    386370
     
    504488                        __pass::symtab::addId( core, 0, func );
    505489                        VISIT(
    506                                 // parameter declarations are now directly here
     490                                // parameter declarations
    507491                                maybe_accept( node, &FunctionDecl::params );
    508492                                maybe_accept( node, &FunctionDecl::returns );
    509                                 // foralls are still in function type
    510                                 maybe_accept( node, &FunctionDecl::type );
     493                                // type params and assertions
     494                                maybe_accept( node, &FunctionDecl::type_params );
     495                                maybe_accept( node, &FunctionDecl::assertions );
    511496                                // First remember that we are now within a function.
    512497                                ValueGuard< bool > oldInFunction( inFunction );
     
    609594        VISIT({
    610595                guard_symtab guard { *this };
    611                 maybe_accept( node, &TypeDecl::params );
    612596                maybe_accept( node, &TypeDecl::base   );
    613597        })
     
    638622        VISIT({
    639623                guard_symtab guard { *this };
    640                 maybe_accept( node, &TypedefDecl::params );
    641624                maybe_accept( node, &TypedefDecl::base   );
    642625        })
     
    17601743
    17611744        VISIT({
    1762                 guard_forall_subs forall_guard { *this, node };
    1763                 mutate_forall( node );
     1745                // guard_forall_subs forall_guard { *this, node };
     1746                // mutate_forall( node );
     1747                maybe_accept( node, &FunctionType::assertions );
    17641748                maybe_accept( node, &FunctionType::returns );
    17651749                maybe_accept( node, &FunctionType::params  );
     
    17791763        VISIT({
    17801764                guard_symtab guard { *this };
    1781                 guard_forall_subs forall_guard { *this, node };
    1782                 mutate_forall( node );
    17831765                maybe_accept( node, &StructInstType::params );
    17841766        })
     
    17971779        VISIT({
    17981780                guard_symtab guard { *this };
    1799                 guard_forall_subs forall_guard { *this, node };
    1800                 mutate_forall( node );
    18011781                maybe_accept( node, &UnionInstType::params );
    18021782        })
     
    18121792
    18131793        VISIT({
    1814                 guard_forall_subs forall_guard { *this, node };
    1815                 mutate_forall( node );
    18161794                maybe_accept( node, &EnumInstType::params );
    18171795        })
     
    18271805
    18281806        VISIT({
    1829                 guard_forall_subs forall_guard { *this, node };
    1830                 mutate_forall( node );
    18311807                maybe_accept( node, &TraitInstType::params );
    18321808        })
     
    18431819        VISIT(
    18441820                {
    1845                         guard_forall_subs forall_guard { *this, node };
    1846                         mutate_forall( node );
    18471821                        maybe_accept( node, &TypeInstType::params );
    18481822                }
     
    19931967                {
    19941968                        bool mutated = false;
    1995                         std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
     1969                        std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map;
    19961970                        for ( const auto & p : node->typeEnv ) {
    19971971                                guard_symtab guard { *this };
     
    20061980                        }
    20071981                }
    2008 
    2009                 {
    2010                         bool mutated = false;
    2011                         std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
    2012                         for ( const auto & p : node->varEnv ) {
    2013                                 guard_symtab guard { *this };
    2014                                 auto new_node = p.second->accept( *this );
    2015                                 if (new_node != p.second) mutated = true;
    2016                                 new_map.insert({ p.first, new_node });
    2017                         }
    2018                         if (mutated) {
    2019                                 auto new_node = __pass::mutate<core_t>( node );
    2020                                 new_node->varEnv.swap( new_map );
    2021                                 node = new_node;
    2022                         }
    2023                 }
    20241982        )
    20251983
  • src/AST/Pass.proto.hpp

    rb3c8496 r53449a4  
    396396                // Some simple scoping rules
    397397                template<typename core_t>
    398                 static inline auto enter( core_t & core, int, const ast::ParameterizedType * type )
     398                static inline auto enter( core_t & core, int, const ast::FunctionType * type )
    399399                -> decltype( core.subs, void() ) {
    400400                        if ( ! type->forall.empty() ) core.subs.beginScope();
     
    402402
    403403                template<typename core_t>
    404                 static inline auto enter( core_t &, long, const ast::ParameterizedType * ) {}
    405 
    406                 template<typename core_t>
    407                 static inline auto leave( core_t & core, int, const ast::ParameterizedType * type )
     404                static inline auto enter( core_t &, long, const ast::FunctionType * ) {}
     405
     406                template<typename core_t>
     407                static inline auto leave( core_t & core, int, const ast::FunctionType * type )
    408408                -> decltype( core.subs, void() ) {
    409409                        if ( ! type->forall.empty() ) { core.subs.endScope(); }
     
    411411
    412412                template<typename core_t>
    413                 static inline auto leave( core_t &, long, const ast::ParameterizedType * ) {}
    414 
    415                 // Get the substitution table, if present
    416                 template<typename core_t>
    417                 static inline auto subs( core_t & core, int ) -> decltype( &core.subs ) {
    418                         return &core.subs;
    419                 }
    420 
    421                 template<typename core_t>
    422                 static inline ast::ForallSubstitutionTable * subs( core_t &, long ) { return nullptr; }
     413                static inline auto leave( core_t &, long, const ast::FunctionType * ) {}
    423414
    424415                // Replaces a TypeInstType's base TypeDecl according to the table
  • src/AST/Print.cpp

    rb3c8496 r53449a4  
    146146        }
    147147
    148         void print( const ast::ParameterizedType::ForallList & forall ) {
     148        void print( const ast::FunctionType::ForallList & forall ) {
    149149                if ( forall.empty() ) return;
    150150                os << "forall" << endl;
    151151                ++indent;
    152152                printAll( forall );
     153                os << indent;
     154                --indent;
     155        }
     156
     157        void print( const ast::FunctionType::AssertionList & assts ) {
     158                if (assts.empty()) return;
     159                os << "with assertions" << endl;
     160                ++indent;
     161                printAll(assts);
    153162                os << indent;
    154163                --indent;
     
    206215        void preprint( const ast::NamedTypeDecl * node ) {
    207216                if ( ! node->name.empty() ) {
    208                         if( deterministic_output && isUnboundType(node->name) ) os << "[unbound]:";
    209                         else os << node->name << ": ";
     217                        os << node->name << ": ";
    210218                }
    211219
     
    224232                }
    225233
    226                 if ( ! node->params.empty() ) {
    227                         os << endl << indent << "... with parameters" << endl;
    228                         ++indent;
    229                         printAll( node->params );
    230                         --indent;
    231                 }
    232 
    233234                if ( ! node->assertions.empty() ) {
    234235                        os << endl << indent << "... with assertions" << endl;
     
    266267        }
    267268
    268         void preprint( const ast::ParameterizedType * node ) {
     269        void preprint( const ast::FunctionType * node ) {
    269270                print( node->forall );
     271                print( node->assertions );
    270272                print( node->qualifiers );
    271273        }
    272274
    273275        void preprint( const ast::BaseInstType * node ) {
    274                 print( node->forall );
    275276                print( node->attributes );
    276277                print( node->qualifiers );
     
    13831384        virtual const ast::Type * visit( const ast::TypeInstType * node ) override final {
    13841385                preprint( node );
    1385                 const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->name;
     1386                const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->typeString();
    13861387                os << "instance of type " << _name
    13871388                   << " (" << (node->kind == ast::TypeDecl::Ftype ? "" : "not ") << "function type)";
     
    15101511                os << indent << "Types:" << endl;
    15111512                for ( const auto& i : *node ) {
    1512                         os << indent+1 << i.first << " -> ";
     1513                        os << indent+1 << i.first.typeString() << " -> ";
    15131514                        indent += 2;
    15141515                        safe_print( i.second );
    1515                         indent -= 2;
    1516                         os << endl;
    1517                 }
    1518                 os << indent << "Non-types:" << endl;
    1519                 for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {
    1520                         os << indent+1 << i->first << " -> ";
    1521                         indent += 2;
    1522                         safe_print( i->second );
    15231516                        indent -= 2;
    15241517                        os << endl;
  • src/AST/SymbolTable.cpp

    rb3c8496 r53449a4  
    414414
    415415void SymbolTable::addFunction( const FunctionDecl * func ) {
    416         addTypes( func->type->forall );
     416        for (auto & td : func->type_params) {
     417                addType(td);
     418        }
     419        for (auto & asst : func->assertions) {
     420                addId(asst);
     421        }
     422        // addTypes( func->type->forall );
    417423        addIds( func->returns );
    418424        addIds( func->params );
  • src/AST/TranslationUnit.hpp

    rb3c8496 r53449a4  
    2929                std::map< UniqueId, Decl * > idMap;
    3030
    31                 Type * sizeType;
    32                 FunctionDecl * dereference;
    33                 StructDecl * dtorStruct;
    34                 FunctionDecl * dtorDestroy;
     31                const Type * sizeType;
     32                const FunctionDecl * dereference;
     33                const StructDecl * dtorStruct;
     34                const FunctionDecl * dtorDestroy;
    3535        } global;
    3636};
  • src/AST/Type.cpp

    rb3c8496 r53449a4  
    2121
    2222#include "Decl.hpp"
    23 #include "ForallSubstitutor.hpp" // for substituteForall
    2423#include "Init.hpp"
    2524#include "Common/utility.h"      // for copy, move
     
    9291// GENERATED END
    9392
    94 // --- ParameterizedType
    95 
    96 void ParameterizedType::initWithSub(
    97         const ParameterizedType & o, Pass< ForallSubstitutor > & sub
    98 ) {
    99         forall = sub.core( o.forall );
    100 }
    101 
    10293// --- FunctionType
    103 
    104 
    105 FunctionType::FunctionType( const FunctionType & o )
    106 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
    107   isVarArgs( o.isVarArgs ) {
    108         Pass< ForallSubstitutor > sub;
    109         initWithSub( o, sub );           // initialize substitution map
    110         returns = sub.core( o.returns ); // apply to return and parameter types
    111         params = sub.core( o.params );
    112 }
    113 
    11494namespace {
    11595        bool containsTtype( const std::vector<ptr<Type>> & l ) {
     
    123103bool FunctionType::isTtype() const {
    124104        return containsTtype( returns ) || containsTtype( params );
    125 }
    126 
    127 // --- BaseInstType
    128 
    129 void BaseInstType::initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ) {
    130         ParameterizedType::initWithSub( o, sub ); // initialize substitution
    131         params = sub.core( o.params );            // apply to parameters
    132 }
    133 
    134 BaseInstType::BaseInstType( const BaseInstType & o )
    135 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
    136   hoistType( o.hoistType ) {
    137         Pass< ForallSubstitutor > sub;
    138         initWithSub( o, sub );
    139105}
    140106
     
    177143: BaseInstType( b->name, q, move(as) ), base( b ) {}
    178144
    179 // --- TypeInstType
    180 
    181 TypeInstType::TypeInstType( const TypeInstType & o )
    182 : BaseInstType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
    183         Pass< ForallSubstitutor > sub;
    184         initWithSub( o, sub );      // initialize substitution
    185         base = sub.core( o.base );  // apply to base type
    186 }
    187 
    188145void TypeInstType::set_base( const TypeDecl * b ) {
    189146        base = b;
     
    222179                // TODO: once TypeInstType representation is updated, it should properly check
    223180                // if the context id is filled. this is a temporary hack for now
    224                 return isUnboundType(typeInst->name);
    225         }
    226         return false;
    227 }
    228 
    229 bool isUnboundType(const std::string & tname) {
    230         // xxx - look for a type name produced by renameTyVars.
    231 
    232         // TODO: once TypeInstType representation is updated, it should properly check
    233         // if the context id is filled. this is a temporary hack for now
    234         if (std::count(tname.begin(), tname.end(), '_') >= 3) {
    235                 return true;
     181                return typeInst->formal_usage > 0;
    236182        }
    237183        return false;
  • src/AST/Type.hpp

    rb3c8496 r53449a4  
    3636
    3737template< typename T > class Pass;
    38 
    39 struct ForallSubstitutor;
    4038
    4139class Type : public Node {
     
    267265};
    268266
    269 /// Base type for potentially forall-qualified types
    270 class ParameterizedType : public Type {
    271 protected:
    272         /// initializes forall with substitutor
    273         void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
    274 public:
    275         using ForallList = std::vector<ptr<TypeDecl>>;
    276 
    277         ForallList forall;
    278 
    279         ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {},
    280                 std::vector<ptr<Attribute>> && as = {} )
    281         : Type(q, std::move(as)), forall(std::move(fs)) {}
    282 
    283         ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    284         : Type(q, std::move(as)), forall() {}
    285 
    286         // enforce use of ForallSubstitutor to copy parameterized type
    287         ParameterizedType( const ParameterizedType & ) = delete;
    288 
    289         ParameterizedType( ParameterizedType && ) = default;
    290 
    291         // no need to change destructor, and operator= deleted in Node
    292 
    293 private:
    294         virtual ParameterizedType * clone() const override = 0;
    295         MUTATE_FRIEND
    296 };
    297 
    298267/// Function variable arguments flag
    299268enum ArgumentFlag { FixedArgs, VariableArgs };
    300269
    301270/// Type of a function `[R1, R2](*)(P1, P2, P3)`
    302 class FunctionType final : public ParameterizedType {
    303 public:
     271class FunctionType final : public Type {
     272public:
     273        using ForallList = std::vector<ptr<TypeInstType>>;
     274        using AssertionList = std::vector<ptr<VariableExpr>>;
     275        ForallList forall;
     276        AssertionList assertions;
     277
    304278        std::vector<ptr<Type>> returns;
    305279        std::vector<ptr<Type>> params;
     
    313287
    314288        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
    315         : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
    316 
    317         FunctionType( const FunctionType & o );
     289        : Type(q), returns(), params(), isVarArgs(va) {}
     290
     291        FunctionType( const FunctionType & o ) = default;
    318292
    319293        /// true if either the parameters or return values contain a tttype
     
    329303
    330304/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    331 class BaseInstType : public ParameterizedType {
    332 protected:
    333         /// Initializes forall and parameters based on substitutor
    334         void initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub );
     305class BaseInstType : public Type {
    335306public:
    336307        std::vector<ptr<Expr>> params;
     
    340311        BaseInstType(
    341312                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    342         : ParameterizedType(q, std::move(as)), params(), name(n) {}
     313        : Type(q, std::move(as)), params(), name(n) {}
    343314
    344315        BaseInstType(
    345316                const std::string& n, std::vector<ptr<Expr>> && params,
    346317                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    347         : ParameterizedType(q, std::move(as)), params(std::move(params)), name(n) {}
    348 
    349         BaseInstType( const BaseInstType & o );
     318        : Type(q, std::move(as)), params(std::move(params)), name(n) {}
     319
     320        BaseInstType( const BaseInstType & o ) = default;
    350321
    351322        /// Gets aggregate declaration this type refers to
     
    423394public:
    424395        readonly<TypeDecl> base;
     396        // previously from renameTyVars; now directly use integer fields instead of synthesized strings
     397        // a nonzero value of formal_usage indicates a formal type (only used in function type)
     398        // a zero value of formal_usage indicates an actual type (referenced inside body of parametric structs and functions)
    425399        TypeDecl::Kind kind;
     400        int formal_usage;
     401        int expr_id;
     402
     403        // compact representation used for map lookups.
     404        struct TypeEnvKey {
     405                const TypeDecl * base;
     406                int formal_usage;
     407                int expr_id;
     408
     409                TypeEnvKey() = default;
     410                TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0): base(base), formal_usage(formal_usage), expr_id(expr_id) {}
     411                TypeEnvKey(const TypeInstType & inst): base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
     412                std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; }
     413                bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
     414
     415        };
     416
     417        bool operator==(const TypeInstType & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
    426418
    427419        TypeInstType(
     
    433425        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
    434426
    435         TypeInstType( const TypeInstType & o );
     427        TypeInstType( const TypeInstType & o ) = default;
     428
     429        TypeInstType( const TypeEnvKey & key )
     430        : BaseInstType(key.base->name), base(key.base), kind(key.base->kind), formal_usage(key.formal_usage), expr_id(key.expr_id) {}
    436431
    437432        /// sets `base`, updating `kind` correctly
     
    444439
    445440        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     441
     442        std::string typeString() const {
     443                if (formal_usage > 0) return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + name;
     444                else return name;
     445        }
    446446private:
    447447        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
     
    536536
    537537bool isUnboundType(const Type * type);
    538 bool isUnboundType(const std::string & tname);
    539 
     538
     539}
     540
     541namespace std {
     542        template<>
     543        struct hash<typename ast::TypeInstType::TypeEnvKey> {
     544                size_t operator() (const ast::TypeInstType::TypeEnvKey & x) const {
     545                        const size_t p = 1000007;
     546                        size_t res = reinterpret_cast<size_t>(x.base);
     547                        res = p * res + x.formal_usage;
     548                        res = p * res + x.expr_id;
     549                        return res;
     550                }
     551        };
    540552}
    541553
  • src/AST/TypeEnvironment.cpp

    rb3c8496 r53449a4  
    5252        for ( const auto & i : open ) {
    5353                if ( first ) { first = false; } else { out << ' '; }
    54                 out << i.first << "(" << i.second << ")";
     54                out << i.first.typeString() << "(" << i.second << ")";
    5555        }
    5656}
     
    6262                if(first) first = false;
    6363                else out << " ";
    64                 if( deterministic_output && isUnboundType(var) ) out << "[unbound]";
    65                 else out << var;
     64
     65                if( deterministic_output ) out << "[unbound]";
     66                else out << "_" << var.formal_usage << "_" << var.expr_id << "_";
     67
     68                out << var.base->name;
    6669        }
    6770        out << ")";
     
    7982}
    8083
    81 const EqvClass * TypeEnvironment::lookup( const std::string & var ) const {
     84const EqvClass * TypeEnvironment::lookup( const TypeInstType::TypeEnvKey & var ) const {
    8285        for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) {
    8386                if ( i->vars.find( var ) != i->vars.end() ) return &*i;
     
    105108}
    106109
    107 void TypeEnvironment::add( const ParameterizedType::ForallList & tyDecls ) {
    108         for ( const TypeDecl * tyDecl : tyDecls ) {
     110void TypeEnvironment::add( const FunctionType::ForallList & tyDecls ) {
     111        for ( auto & tyDecl : tyDecls ) {
    109112                env.emplace_back( tyDecl );
    110113        }
     
    119122void TypeEnvironment::writeToSubstitution( TypeSubstitution & sub ) const {
    120123        for ( const auto & clz : env ) {
    121                 std::string clzRep;
     124                TypeInstType::TypeEnvKey clzRep;
     125                bool first = true;
    122126                for ( const auto & var : clz.vars ) {
    123127                        if ( clz.bound ) {
    124128                                sub.add( var, clz.bound );
    125                         } else if ( clzRep.empty() ) {
     129                        } else if ( first ) {
    126130                                clzRep = var;
     131                                first = false;
    127132                        } else {
    128                                 sub.add( var, new TypeInstType{ clzRep, clz.data.kind } );
     133                                sub.add( var, new TypeInstType{ clzRep } );
    129134                        }
    130135                }
     
    141146        struct Occurs : public ast::WithVisitorRef<Occurs> {
    142147                bool result;
    143                 std::set< std::string > vars;
     148                std::unordered_set< TypeInstType::TypeEnvKey > vars;
    144149                const TypeEnvironment & tenv;
    145150
    146                 Occurs( const std::string & var, const TypeEnvironment & env )
     151                Occurs( const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env )
    147152                : result( false ), vars(), tenv( env ) {
    148153                        if ( const EqvClass * clz = tenv.lookup( var ) ) {
     
    154159
    155160                void previsit( const TypeInstType * typeInst ) {
    156                         if ( vars.count( typeInst->name ) ) {
     161                        if ( vars.count( *typeInst ) ) {
    157162                                result = true;
    158                         } else if ( const EqvClass * clz = tenv.lookup( typeInst->name ) ) {
     163                        } else if ( const EqvClass * clz = tenv.lookup( *typeInst ) ) {
    159164                                if ( clz->bound ) {
    160165                                        clz->bound->accept( *visitor );
     
    165170
    166171        /// true if `var` occurs in `ty` under `env`
    167         bool occurs( const Type * ty, const std::string & var, const TypeEnvironment & env ) {
     172        bool occurs( const Type * ty, const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env ) {
    168173                Pass<Occurs> occur{ var, env };
    169174                maybe_accept( ty, occur );
     
    280285        // remove references from bound type, so that type variables can only bind to value types
    281286        ptr<Type> target = bindTo->stripReferences();
    282         auto tyvar = open.find( typeInst->name );
     287        auto tyvar = open.find( *typeInst );
    283288        assert( tyvar != open.end() );
    284289        if ( ! tyVarCompatible( tyvar->second, target ) ) return false;
    285         if ( occurs( target, typeInst->name, *this ) ) return false;
    286 
    287         auto it = internal_lookup( typeInst->name );
     290        if ( occurs( target, *typeInst, *this ) ) return false;
     291
     292        auto it = internal_lookup( *typeInst );
    288293        if ( it != env.end() ) {
    289294                if ( it->bound ) {
     
    308313        } else {
    309314                env.emplace_back(
    310                         typeInst->name, target, widen.first && widen.second, data );
     315                        *typeInst, target, widen.first && widen.second, data );
    311316        }
    312317        return true;
     
    318323                WidenMode widen, const SymbolTable & symtab
    319324) {
    320         auto c1 = internal_lookup( var1->name );
    321         auto c2 = internal_lookup( var2->name );
     325        auto c1 = internal_lookup( *var1 );
     326        auto c2 = internal_lookup( *var2 );
    322327
    323328        // exit early if variables already bound together
     
    333338        if ( c1 != env.end() ) {
    334339                if ( c1->bound ) {
    335                         if ( occurs( c1->bound, var2->name, *this ) ) return false;
     340                        if ( occurs( c1->bound, *var2, *this ) ) return false;
    336341                        type1 = c1->bound;
    337342                }
     
    340345        if ( c2 != env.end() ) {
    341346                if ( c2->bound ) {
    342                         if ( occurs( c2->bound, var1->name, *this ) ) return false;
     347                        if ( occurs( c2->bound, *var1, *this ) ) return false;
    343348                        type2 = c2->bound;
    344349                }
     
    378383        } else if ( c1 != env.end() ) {
    379384                // var2 unbound, add to env[c1]
    380                 c1->vars.emplace( var2->name );
     385                c1->vars.emplace( *var2 );
    381386                c1->allowWidening = widen1;
    382387                c1->data.isComplete |= data.isComplete;
    383388        } else if ( c2 != env.end() ) {
    384389                // var1 unbound, add to env[c2]
    385                 c2->vars.emplace( var1->name );
     390                c2->vars.emplace( *var1 );
    386391                c2->allowWidening = widen2;
    387392                c2->data.isComplete |= data.isComplete;
    388393        } else {
    389394                // neither var bound, create new class
    390                 env.emplace_back( var1->name, var2->name, widen1 && widen2, data );
     395                env.emplace_back( *var1, *var2, widen1 && widen2, data );
    391396        }
    392397
     
    452457}
    453458
    454 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string & var ) {
     459TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const TypeInstType::TypeEnvKey & var ) {
    455460        for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) {
    456461                if ( i->vars.count( var ) ) return i;
  • src/AST/TypeEnvironment.hpp

    rb3c8496 r53449a4  
    5555/// recorded. More investigation is needed.
    5656struct AssertCompare {
    57         bool operator()( const DeclWithType * d1, const DeclWithType * d2 ) const {
    58                 int cmp = d1->name.compare( d2->name );
    59                 return cmp < 0 || ( cmp == 0 && d1->get_type() < d2->get_type() );
     57        bool operator()( const VariableExpr * d1, const VariableExpr * d2 ) const {
     58                int cmp = d1->var->name.compare( d2->var->name );
     59                return cmp < 0 || ( cmp == 0 && d1->result < d2->result );
    6060        }
    6161};
     
    7070
    7171/// Set of assertions pending satisfaction
    72 using AssertionSet = std::map< readonly<DeclWithType>, AssertionSetValue, AssertCompare >;
     72using AssertionSet = std::map< const VariableExpr *, AssertionSetValue, AssertCompare >;
    7373
    7474/// Set of open variables
    75 using OpenVarSet = std::unordered_map< std::string, TypeDecl::Data >;
     75using OpenVarSet = std::unordered_map< TypeInstType::TypeEnvKey, TypeDecl::Data >;
    7676
    7777/// Merges one set of open vars into another
     
    8989/// they bind to.
    9090struct EqvClass {
    91         std::set< std::string > vars;
     91        std::unordered_set< TypeInstType::TypeEnvKey > vars;
    9292        ptr<Type> bound;
    9393        bool allowWidening;
     
    101101
    102102        /// Singleton class constructor from TypeDecl
    103         EqvClass( const TypeDecl * decl )
    104         : vars{ decl->name }, bound(), allowWidening( true ), data( decl ) {}
     103        EqvClass( const TypeInstType * inst )
     104        : vars{ *inst }, bound(), allowWidening( true ), data( inst->base ) {}
    105105
    106106        /// Singleton class constructor from substitution
    107         EqvClass( const std::string & v, const Type * b )
     107        EqvClass( const TypeInstType::TypeEnvKey & v, const Type * b )
    108108        : vars{ v }, bound( b ), allowWidening( false ), data( TypeDecl::Dtype, false ) {}
    109109
    110110        /// Single-var constructor (strips qualifiers from bound type)
    111         EqvClass( const std::string & v, const Type * b, bool w, const TypeDecl::Data & d )
     111        EqvClass( const TypeInstType::TypeEnvKey & v, const Type * b, bool w, const TypeDecl::Data & d )
    112112        : vars{ v }, bound( b ), allowWidening( w ), data( d ) {
    113113                reset_qualifiers( bound );
     
    115115
    116116        /// Double-var constructor
    117         EqvClass( const std::string & v, const std::string & u, bool w, const TypeDecl::Data & d )
     117        EqvClass( const TypeInstType::TypeEnvKey & v, const TypeInstType::TypeEnvKey & u, bool w, const TypeDecl::Data & d )
    118118        : vars{ v, u }, bound(), allowWidening( w ), data( d ) {}
    119119
     
    131131public:
    132132        /// Finds the equivalence class containing a variable; nullptr for none such
    133         const EqvClass * lookup( const std::string & var ) const;
     133        const EqvClass * lookup( const TypeInstType::TypeEnvKey & var ) const;
    134134
    135135        /// Add a new equivalence class for each type variable
    136         void add( const ParameterizedType::ForallList & tyDecls );
     136        void add( const FunctionType::ForallList & tyDecls );
    137137
    138138        /// Add a new equivalence class for each branch of the substitution, checking for conflicts
     
    207207
    208208        /// Private lookup API; returns array index of string, or env.size() for not found
    209         ClassList::iterator internal_lookup( const std::string & );
     209        ClassList::iterator internal_lookup( const TypeInstType::TypeEnvKey & );
    210210};
    211211
  • src/AST/TypeSubstitution.cpp

    rb3c8496 r53449a4  
    3939void TypeSubstitution::initialize( const TypeSubstitution &src, TypeSubstitution &dest ) {
    4040        dest.typeEnv.clear();
    41         dest.varEnv.clear();
    4241        dest.add( src );
    4342}
     
    4746                typeEnv[ i->first ] = i->second;
    4847        } // for
    49         for ( VarEnvType::const_iterator i = other.varEnv.begin(); i != other.varEnv.end(); ++i ) {
    50                 varEnv[ i->first ] = i->second;
    51         } // for
    5248}
    5349
    54 void TypeSubstitution::add( std::string formalType, const Type *actualType ) {
    55         typeEnv[ formalType ] = actualType;
     50void TypeSubstitution::add( const TypeInstType * formalType, const Type *actualType ) {
     51        typeEnv[ *formalType ] = actualType;
    5652}
    5753
    58 void TypeSubstitution::addVar( std::string formalExpr, const Expr *actualExpr ) {
    59         varEnv[ formalExpr ] = actualExpr;
     54void TypeSubstitution::add( const TypeInstType::TypeEnvKey & key, const Type * actualType) {
     55        typeEnv[ key ] = actualType;
    6056}
    6157
    62 void TypeSubstitution::remove( std::string formalType ) {
    63         TypeEnvType::iterator i = typeEnv.find( formalType );
     58void TypeSubstitution::remove( const TypeInstType * formalType ) {
     59        TypeEnvType::iterator i = typeEnv.find( *formalType );
    6460        if ( i != typeEnv.end() ) {
    65                 typeEnv.erase( formalType );
     61                typeEnv.erase( *formalType );
    6662        } // if
    6763}
    6864
    69 const Type *TypeSubstitution::lookup( std::string formalType ) const {
    70         TypeEnvType::const_iterator i = typeEnv.find( formalType );
     65const Type *TypeSubstitution::lookup( const TypeInstType * formalType ) const {
     66        TypeEnvType::const_iterator i = typeEnv.find( *formalType );
    7167
    7268        // break on not in substitution set
     
    7571        // attempt to transitively follow TypeInstType links.
    7672        while ( const TypeInstType *actualType = i->second.as<TypeInstType>()) {
    77                 const std::string& typeName = actualType->name;
    78 
    7973                // break cycles in the transitive follow
    80                 if ( formalType == typeName ) break;
     74                if ( *formalType == *actualType ) break;
    8175
    8276                // Look for the type this maps to, returning previous mapping if none-such
    83                 i = typeEnv.find( typeName );
     77                i = typeEnv.find( *actualType );
    8478                if ( i == typeEnv.end() ) return actualType;
    8579        }
     
    9084
    9185bool TypeSubstitution::empty() const {
    92         return typeEnv.empty() && varEnv.empty();
     86        return typeEnv.empty();
    9387}
    9488
     
    9892                TypeSubstitution * newEnv;
    9993                EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
    100                 void previsit( TypeDecl * tyDecl ) {
     94                void previsit( FunctionType * ftype ) {
    10195                        // transfer known bindings for seen type variables
    102                         if ( const Type * t = env->lookup( tyDecl->name ) ) {
    103                                 newEnv->add( tyDecl->name, t );
     96                        for (auto & formal : ftype->forall) {
     97                                if ( const Type * t = env->lookup( formal ) ) {
     98                                        newEnv->add( formal, t );
     99                                }
    104100                        }
    105101                }
     
    130126
    131127const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
    132         BoundVarsType::const_iterator bound = boundVars.find( inst->name );
     128        BoundVarsType::const_iterator bound = boundVars.find( *inst );
    133129        if ( bound != boundVars.end() ) return inst;
    134130
    135         TypeEnvType::const_iterator i = sub.typeEnv.find( inst->name );
     131        TypeEnvType::const_iterator i = sub.typeEnv.find( *inst );
    136132        if ( i == sub.typeEnv.end() ) {
    137133                return inst;
     
    141137                // TODO: investigate preventing type variables from being bound to themselves in the first place.
    142138                if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) {
    143                         if ( inst->name == replacement->name ) {
     139                        if ( *inst == *replacement ) {
    144140                                return inst;
    145141                        }
     
    156152}
    157153
    158 const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) {
    159         VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
    160         if ( i == sub.varEnv.end() ) {
    161                 return nameExpr;
    162         } else {
    163                 subCount++;
    164                 return i->second;
    165         } // if
    166 }
    167 
    168 void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) {
     154void TypeSubstitution::Substituter::previsit( const FunctionType * ptype ) {
    169155        GuardValue( boundVars );
    170156        // bind type variables from forall-qualifiers
    171157        if ( freeOnly ) {
    172                 for ( const TypeDecl * tyvar : ptype->forall ) {
    173                                 boundVars.insert( tyvar->name );
     158                for ( auto & tyvar : ptype->forall ) {
     159                                boundVars.insert( *tyvar );
    174160                } // for
    175161        } // if
    176162}
    177163
     164/*
    178165void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) {
    179166        GuardValue( boundVars );
    180167        // bind type variables from forall-qualifiers
    181168        if ( freeOnly ) {
    182                 for ( const TypeDecl * tyvar : type->forall ) {
    183                         boundVars.insert( tyvar->name );
    184                 } // for
    185169                // bind type variables from generic type instantiations
    186170                if ( auto decl = type->aggr() ) {
    187171                        if ( ! type->params.empty() ) {
    188172                                for ( const TypeDecl * tyvar : decl->params ) {
    189                                         boundVars.insert( tyvar->name );
     173                                        boundVars.insert( *tyvar );
    190174                                } // for
    191175                        } // if
     
    201185        handleAggregateType( aggregateUseType );
    202186}
     187*/
    203188
    204189} // namespace ast
  • src/AST/TypeSubstitution.hpp

    rb3c8496 r53449a4  
    6969        }
    7070
    71         void add( std::string formalType, const Type *actualType );
     71        void add( const TypeInstType * formalType, const Type *actualType );
     72        void add( const TypeInstType::TypeEnvKey & key, const Type *actualType );
    7273        void add( const TypeSubstitution &other );
    73         void remove( std::string formalType );
    74         const Type *lookup( std::string formalType ) const;
     74        void remove( const TypeInstType * formalType );
     75        const Type *lookup( const TypeInstType * formalType ) const;
    7576        bool empty() const;
    76 
    77         void addVar( std::string formalExpr, const Expr *actualExpr );
    7877
    7978        template< typename FormalIterator, typename ActualIterator >
     
    101100        friend class Pass;
    102101
    103         typedef std::unordered_map< std::string, ptr<Type> > TypeEnvType;
    104         typedef std::unordered_map< std::string, ptr<Expr> > VarEnvType;
     102        typedef std::unordered_map< TypeInstType::TypeEnvKey, ptr<Type> > TypeEnvType;
    105103        TypeEnvType typeEnv;
    106         VarEnvType varEnv;
    107104
    108105  public:
     
    113110        auto   end() const -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
    114111
    115         auto beginVar()       -> decltype( varEnv.begin() ) { return varEnv.begin(); }
    116         auto   endVar()       -> decltype( varEnv.  end() ) { return varEnv.  end(); }
    117         auto beginVar() const -> decltype( varEnv.begin() ) { return varEnv.begin(); }
    118         auto   endVar() const -> decltype( varEnv.  end() ) { return varEnv.  end(); }
    119112};
    120113
     114// this is the only place where type parameters outside a function formal may be substituted.
    121115template< typename FormalIterator, typename ActualIterator >
    122116void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
     
    129123                        if ( const TypeExpr *actual = actualIt->template as<TypeExpr>() ) {
    130124                                if ( formal->name != "" ) {
    131                                         typeEnv[ formal->name ] = actual->type;
     125                                        typeEnv[ formal ] = actual->type;
    132126                                } // if
    133127                        } else {
     
    135129                        } // if
    136130                } else {
    137                         // TODO: type check the formal and actual parameters
    138                         if ( (*formalIt)->name != "" ) {
    139                                 varEnv[ (*formalIt)->name ] = *actualIt;
    140                         } // if
     131                       
    141132                } // if
    142133        } // for
    143134}
     135
     136
    144137
    145138template< typename FormalIterator, typename ActualIterator >
     
    147140        add( formalBegin, formalEnd, actualBegin );
    148141}
     142
    149143
    150144} // namespace ast
     
    164158
    165159                const Type * postvisit( const TypeInstType * aggregateUseType );
    166                 const Expr * postvisit( const NameExpr * nameExpr );
    167160
    168161                /// Records type variable bindings from forall-statements
    169                 void previsit( const ParameterizedType * type );
     162                void previsit( const FunctionType * type );
    170163                /// Records type variable bindings from forall-statements and instantiations of generic types
    171                 void handleAggregateType( const BaseInstType * type );
     164                // void handleAggregateType( const BaseInstType * type );
    172165
    173                 void previsit( const StructInstType * aggregateUseType );
    174                 void previsit( const UnionInstType * aggregateUseType );
     166                // void previsit( const StructInstType * aggregateUseType );
     167                // void previsit( const UnionInstType * aggregateUseType );
    175168
    176169                const TypeSubstitution & sub;
    177170                int subCount = 0;
    178171                bool freeOnly;
    179                 typedef std::unordered_set< std::string > BoundVarsType;
     172                typedef std::unordered_set< TypeInstType::TypeEnvKey > BoundVarsType;
    180173                BoundVarsType boundVars;
    181174
  • src/AST/module.mk

    rb3c8496 r53449a4  
    3333        AST/Expr.cpp \
    3434        AST/Expr.hpp \
    35         AST/ForallSubstitutionTable.cpp \
    36         AST/ForallSubstitutionTable.hpp \
    37         AST/ForallSubstitutor.hpp \
    3835        AST/FunctionSpec.hpp \
    3936        AST/Fwd.hpp \
  • src/Common/PassVisitor.impl.h

    rb3c8496 r53449a4  
    835835        {
    836836                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    837                 maybeAccept_impl( node->parameters, *this );
    838837                maybeAccept_impl( node->base      , *this );
    839838        }
     
    858857        {
    859858                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    860                 maybeAccept_impl( node->parameters, *this );
    861859                maybeAccept_impl( node->base      , *this );
    862860        }
     
    880878        {
    881879                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    882                 maybeMutate_impl( node->parameters, *this );
    883880                maybeMutate_impl( node->base      , *this );
    884881        }
     
    904901        {
    905902                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    906                 maybeAccept_impl( node->parameters, *this );
    907903                maybeAccept_impl( node->base      , *this );
    908904        }
     
    921917        {
    922918                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    923                 maybeAccept_impl( node->parameters, *this );
    924919                maybeAccept_impl( node->base      , *this );
    925920        }
     
    938933        {
    939934                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    940                 maybeMutate_impl( node->parameters, *this );
    941935                maybeMutate_impl( node->base      , *this );
    942936        }
  • src/GenPoly/GenPoly.cc

    rb3c8496 r53449a4  
    115115                if (!env) return type;
    116116                if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) {
    117                         auto newType = env->lookup(typeInst->name);
     117                        auto newType = env->lookup(typeInst);
    118118                        if (newType) return newType;
    119119                }
     
    172172
    173173                if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    174                         return tyVars.find(typeInst->name) != tyVars.end() ? type : nullptr;
     174                        return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr;
    175175                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    176176                        return isPolyType( arrayType->base, env );
     
    552552        }
    553553
    554         void addToTyVarMap( const ast::TypeDecl * tyVar, TyVarMap & tyVarMap) {
    555                 tyVarMap.insert(tyVar->name, convData(ast::TypeDecl::Data{tyVar}));
     554        void addToTyVarMap( const ast::TypeInstType * tyVar, TyVarMap & tyVarMap) {
     555                tyVarMap.insert(tyVar->typeString(), convData(ast::TypeDecl::Data{tyVar->base}));
    556556        }
    557557
     
    567567
    568568        void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap) {
    569                 if (auto ptype = dynamic_cast<const ast::ParameterizedType *>(type)) {
     569                if (auto ptype = dynamic_cast<const ast::FunctionType *>(type)) {
    570570                        for (auto & tyVar : ptype->forall) {
    571571                                assert (tyVar);
  • src/Parser/TypeData.cc

    rb3c8496 r53449a4  
    900900                ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true );
    901901        } // if
    902         buildList( td->symbolic.params, ret->get_parameters() );
    903902        buildList( td->symbolic.assertions, ret->get_assertions() );
    904903        ret->base->attributes.splice( ret->base->attributes.end(), attributes );
  • src/ResolvExpr/AdjustExprType.cc

    rb3c8496 r53449a4  
    133133                const ast::Type * postvisit( const ast::TypeInstType * inst ) {
    134134                        // replace known function-type-variables with pointer-to-function
    135                         if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
     135                        if ( const ast::EqvClass * eqvClass = tenv.lookup( *inst ) ) {
    136136                                if ( eqvClass->data.kind == ast::TypeDecl::Ftype ) {
    137137                                        return new ast::PointerType{ inst };
  • src/ResolvExpr/CandidateFinder.cpp

    rb3c8496 r53449a4  
    212212                // mark type variable and specialization cost of forall clause
    213213                convCost.incVar( function->forall.size() );
    214                 for ( const ast::TypeDecl * td : function->forall ) {
    215                         convCost.decSpec( td->assertions.size() );
    216                 }
     214                convCost.decSpec( function->assertions.size() );
    217215
    218216                return convCost;
     
    220218
    221219        void makeUnifiableVars(
    222                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
     220                const ast::FunctionType * type, ast::OpenVarSet & unifiableVars,
    223221                ast::AssertionSet & need
    224222        ) {
    225                 for ( const ast::TypeDecl * tyvar : type->forall ) {
    226                         unifiableVars[ tyvar->name ] = ast::TypeDecl::Data{ tyvar };
    227                         for ( const ast::DeclWithType * assn : tyvar->assertions ) {
    228                                 need[ assn ].isUsed = true;
    229                         }
     223                for ( auto & tyvar : type->forall ) {
     224                        unifiableVars[ *tyvar ] = ast::TypeDecl::Data{ tyvar->base };
     225                }
     226                for ( auto & assn : type->assertions ) {
     227                        need[ assn ].isUsed = true;
    230228                }
    231229        }
     
    953951                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    954952                                        ) {
    955                                                 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
     953                                                if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) {
    956954                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    957955                                                                CandidateRef newFunc{ new Candidate{ *func } };
     
    10771075                        assert( toType );
    10781076                        toType = resolveTypeof( toType, symtab );
    1079                         toType = SymTab::validateType( castExpr->location, toType, symtab );
     1077                        // toType = SymTab::validateType( castExpr->location, toType, symtab );
    10801078                        toType = adjustExprType( toType, tenv, symtab );
    10811079
     
    11621160
    11631161                                        if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) {
    1164                                                 auto td = cand->env.lookup(insttype->name);
     1162                                                auto td = cand->env.lookup(*insttype);
    11651163                                                if(!td) { continue; }
    11661164                                                expr = td->bound.get();
     
    15681566                                // calculate target type
    15691567                                const ast::Type * toType = resolveTypeof( initAlt.type, symtab );
    1570                                 toType = SymTab::validateType( initExpr->location, toType, symtab );
     1568                                // toType = SymTab::validateType( initExpr->location, toType, symtab );
    15711569                                toType = adjustExprType( toType, tenv, symtab );
    15721570                                // The call to find must occur inside this loop, otherwise polymorphic return
  • src/ResolvExpr/CastCost.cc

    rb3c8496 r53449a4  
    165165                                } else {
    166166                                        ast::TypeEnvironment newEnv{ env };
    167                                         if ( auto wParams = pointerType->base.as< ast::ParameterizedType >() ) {
     167                                        if ( auto wParams = pointerType->base.as< ast::FunctionType >() ) {
    168168                                                newEnv.add( wParams->forall );
    169169                                        }
     
    202202) {
    203203        if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    204                 if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name ) ) {
     204                if ( const ast::EqvClass * eqvClass = env.lookup( *typeInst ) ) {
    205205                        // check cast cost against bound type, if present
    206206                        if ( eqvClass->bound ) {
  • src/ResolvExpr/CommonType.cc

    rb3c8496 r53449a4  
    713713                        const ast::Type * base = oPtr->base;
    714714                        if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) {
    715                                 auto entry = open.find( var->name );
     715                                auto entry = open.find( *var );
    716716                                if ( entry != open.end() ) {
    717717                                        ast::AssertionSet need, have;
  • src/ResolvExpr/ConversionCost.cc

    rb3c8496 r53449a4  
    498498) {
    499499        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    500                 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
     500                if ( const ast::EqvClass * eqv = env.lookup( *inst ) ) {
    501501                        if ( eqv->bound ) {
    502502                                return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
     
    675675
    676676void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
    677         if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
     677        if ( const ast::EqvClass * eqv = env.lookup( *typeInstType ) ) {
    678678                cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
    679679        } else if ( const ast::TypeInstType * dstAsInst =
    680680                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    681                 if ( typeInstType->name == dstAsInst->name ) {
     681                if ( *typeInstType == *dstAsInst ) {
    682682                        cost = Cost::zero;
    683683                }
  • src/ResolvExpr/FindOpenVars.cc

    rb3c8496 r53449a4  
    112112                                // mark open/closed variables
    113113                                if ( nextIsOpen ) {
    114                                         for ( const ast::TypeDecl * decl : type->forall ) {
    115                                                 open[ decl->name ] = ast::TypeDecl::Data{ decl };
    116                                                 for ( const ast::DeclWithType * assert : decl->assertions ) {
    117                                                         need[ assert ].isUsed = false;
    118                                                 }
     114                                        for ( auto & decl : type->forall ) {
     115                                                open[ *decl ] = ast::TypeDecl::Data{ decl->base };
     116                                        }
     117                                        for ( auto & assert : type->assertions ) {
     118                                                need[ assert ].isUsed = false;
    119119                                        }
    120120                                } else {
    121                                         for ( const ast::TypeDecl * decl : type->forall ) {
    122                                                 closed[ decl->name ] = ast::TypeDecl::Data{ decl };
    123                                                 for ( const ast::DeclWithType * assert : decl->assertions ) {
    124                                                         have[ assert ].isUsed = false;
    125                                                 }
     121                                        for ( auto & decl : type->forall ) {
     122                                                closed[ *decl ] = ast::TypeDecl::Data{ decl->base };   
     123                                        }
     124                                        for ( auto & assert : type->assertions ) {
     125                                                have[ assert ].isUsed = false;
    126126                                        }
    127127                                }
  • src/ResolvExpr/PolyCost.cc

    rb3c8496 r53449a4  
    6868
    6969        void previsit( const ast::TypeInstType * type ) {
    70                 if ( const ast::EqvClass * eqv = env_.lookup( type->name ) ) /* && */ if ( eqv->bound ) {
     70                if ( const ast::EqvClass * eqv = env_.lookup( *type ) ) /* && */ if ( eqv->bound ) {
    7171                        if ( const ast::TypeInstType * otherType = eqv->bound.as< ast::TypeInstType >() ) {
    7272                                if ( symtab.lookupType( otherType->name ) ) {
  • src/ResolvExpr/PtrsAssignable.cc

    rb3c8496 r53449a4  
    134134        }
    135135        void postvisit( const ast::TypeInstType * inst ) {
    136                 if ( const ast::EqvClass * eqv = typeEnv.lookup( inst->name ) ) {
     136                if ( const ast::EqvClass * eqv = typeEnv.lookup( *inst ) ) {
    137137                        if ( eqv->bound ) {
    138138                                // T * = S * for any S depends on the type bound to T
     
    146146                const ast::TypeEnvironment & env ) {
    147147        if ( const ast::TypeInstType * dstAsInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    148                 if ( const ast::EqvClass * eqv = env.lookup( dstAsInst->name ) ) {
     148                if ( const ast::EqvClass * eqv = env.lookup( *dstAsInst ) ) {
    149149                        return ptrsAssignable( src, eqv->bound, env );
    150150                }
  • src/ResolvExpr/PtrsCastable.cc

    rb3c8496 r53449a4  
    180180                                        }
    181181                                }
    182                         } else if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
     182                        } else if ( const ast::EqvClass * eqvClass = env.lookup( *inst ) ) {
    183183                                if ( eqvClass->data.kind == ast::TypeDecl::Ftype ) {
    184184                                        return -1;
     
    283283) {
    284284        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    285                 if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
     285                if ( const ast::EqvClass * eqvClass = env.lookup( *inst ) ) {
    286286                        return ptrsAssignable( src, eqvClass->bound, env );
    287287                }
  • src/ResolvExpr/RenameVars.cc

    rb3c8496 r53449a4  
    1919#include <utility>                 // for pair
    2020
    21 #include "AST/ForallSubstitutionTable.hpp"
    2221#include "AST/Pass.hpp"
    2322#include "AST/Type.hpp"
     
    3938                int level = 0;
    4039                int resetCount = 0;
     40
     41                int next_expr_id = 1;
     42                int next_usage_id = 1;
    4143                ScopedMap< std::string, std::string > nameMap;
     44                ScopedMap< std::string, ast::TypeInstType::TypeEnvKey > idMap;
    4245        public:
    43                 ast::ForallSubstitutionTable subs;
    44 
    4546                void reset() {
    4647                        level = 0;
     
    5354                                type->name = it->second;
    5455                        }
     56                }
     57
     58                void nextUsage() {
     59                        ++next_usage_id;
    5560                }
    5661
     
    7883
    7984                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
    80                         // re-linking of base type handled by WithForallSubstitutor
    81 
    8285                        // rename
    83                         auto it = nameMap.find( type->name );
    84                         if ( it != nameMap.end() ) {
    85                                 // unconditionally mutate because map will *always* have different name,
    86                                 // if this mutates, will *always* have been mutated by ForallSubstitutor above
    87                                 ast::TypeInstType * mut = ast::mutate( type );
    88                                 mut->name = it->second;
     86                        auto it = idMap.find( type->name );
     87                        if ( it != idMap.end() ) {
     88                                // unconditionally mutate because map will *always* have different name
     89                                ast::TypeInstType * mut = ast::shallowCopy( type );
     90                                // reconcile base node since some copies might have been made
     91                                mut->base = it->second.base;
     92                                mut->formal_usage = it->second.formal_usage;
     93                                mut->expr_id = it->second.expr_id;
    8994                    type = mut;
    9095                        }
     
    9398                }
    9499
    95                 template<typename NodeT>
    96                 const NodeT * openLevel( const NodeT * type ) {
     100                const ast::FunctionType * openLevel( const ast::FunctionType * type, RenameMode mode ) {
    97101                        if ( type->forall.empty() ) return type;
    98 
    99                         nameMap.beginScope();
     102                        idMap.beginScope();
    100103
    101104                        // Load new names from this forall clause and perform renaming.
    102                         NodeT * mutType = ast::mutate( type );
    103                         assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
    104                         for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
    105                                 std::ostringstream output;
    106                                 output << "_" << resetCount << "_" << level << "_" << td->name;
    107                                 std::string newname =  output.str();
    108                                 nameMap[ td->name ] = newname;
    109                                 ++level;
    110 
    111                                 ast::TypeDecl * mutDecl = ast::mutate( td.get() );
    112                                 assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
    113                                 mutDecl->name = newname;
    114                                 // assertion above means `td = mutDecl;` is unnecessary
    115                         }
    116                         // assertion above means `type = mutType;` is unnecessary
    117 
    118                         return type;
    119                 }
    120 
    121                 void closeLevel( const ast::ParameterizedType * type ) {
     105                        auto mutType = ast::shallowCopy( type );
     106                        // assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
     107                        for ( auto & td : mutType->forall ) {
     108                                auto mut = ast::shallowCopy( td.get() );
     109                                // assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
     110
     111                                if (mode == GEN_EXPR_ID) {
     112                                        mut->expr_id = next_expr_id;
     113                                        mut->formal_usage = -1;
     114                                        ++next_expr_id;
     115                                }
     116                                else if (mode == GEN_USAGE) {
     117                                        assertf(mut->expr_id, "unfilled expression id in generating candidate type");
     118                                        mut->formal_usage = next_usage_id;
     119                                }
     120                                else {
     121                                        assert(false);
     122                                }
     123                                idMap[ td->name ] = ast::TypeInstType::TypeEnvKey(*mut);
     124                               
     125                                td = mut;
     126                        }
     127
     128                        return mutType;
     129                }
     130
     131                void closeLevel( const ast::FunctionType * type ) {
    122132                        if ( type->forall.empty() ) return;
    123 
    124                         nameMap.endScope();
     133                        idMap.endScope();
    125134                }
    126135        };
     
    142151        };
    143152
    144         struct RenameVars_new /*: public ast::WithForallSubstitutor*/ {
    145                 #warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor
    146                 ast::ForallSubstitutionTable & subs = renaming.subs;
     153        struct RenameVars_new : public ast::PureVisitor /*: public ast::WithForallSubstitutor*/ {
     154                RenameMode mode;
    147155
    148156                const ast::FunctionType * previsit( const ast::FunctionType * type ) {
    149                         return renaming.openLevel( type );
    150                 }
     157                        return renaming.openLevel( type, mode );
     158                }
     159
     160                /*
    151161                const ast::StructInstType * previsit( const ast::StructInstType * type ) {
    152162                        return renaming.openLevel( type );
     
    158168                        return renaming.openLevel( type );
    159169                }
     170                */
     171
    160172                const ast::TypeInstType * previsit( const ast::TypeInstType * type ) {
    161                         return renaming.rename( renaming.openLevel( type ) );
    162                 }
    163                 void postvisit( const ast::ParameterizedType * type ) {
     173                        if (mode == GEN_USAGE && !type->formal_usage) return type; // do not rename an actual type
     174                        return renaming.rename( type );
     175                }
     176                void postvisit( const ast::FunctionType * type ) {
    164177                        renaming.closeLevel( type );
    165178                }
     
    173186}
    174187
    175 const ast::Type * renameTyVars( const ast::Type * t ) {
    176         ast::Type *tc = ast::deepCopy(t);
     188const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode ) {
     189        // ast::Type *tc = ast::deepCopy(t);
    177190        ast::Pass<RenameVars_new> renamer;
    178 //      return t->accept( renamer );
    179         return tc->accept( renamer );
     191        renamer.core.mode = mode;
     192        if (mode == GEN_USAGE) {
     193                renaming.nextUsage();
     194        }
     195        return t->accept( renamer );
    180196}
    181197
  • src/ResolvExpr/RenameVars.h

    rb3c8496 r53449a4  
    3030        /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
    3131        void renameTyVars( Type * );
    32         const ast::Type * renameTyVars( const ast::Type * );
     32
     33        enum RenameMode {
     34                GEN_USAGE, // for type in VariableExpr
     35                GEN_EXPR_ID // for type in decl
     36        };
     37        const ast::Type * renameTyVars( const ast::Type *, RenameMode mode = GEN_USAGE );
    3338
    3439        /// resets internal state of renamer to avoid overflow
    3540        void resetTyVarRenaming();
     41
     42       
    3643} // namespace ResolvExpr
    3744
  • src/ResolvExpr/ResolveTypeof.cc

    rb3c8496 r53449a4  
    1515
    1616#include "ResolveTypeof.h"
     17#include "RenameVars.h"
    1718
    1819#include <cassert>               // for assert
     
    218219                        mutDecl->mangleName = Mangle::mangle(mutDecl); // do not mangle unnamed variables
    219220               
     221                mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID);
    220222                mutDecl->isTypeFixed = true;
    221223                return mutDecl;
  • src/ResolvExpr/Resolver.cc

    rb3c8496 r53449a4  
    968968        namespace {
    969969                /// Finds deleted expressions in an expression tree
    970                 struct DeleteFinder_new final : public ast::WithShortCircuiting {
     970                struct DeleteFinder_new final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder_new> {
    971971                        const ast::DeletedExpr * result = nullptr;
    972972
     
    976976                        }
    977977
    978                         void previsit( const ast::Expr * ) {
     978                        void previsit( const ast::Expr * expr ) {
    979979                                if ( result ) { visit_children = false; }
     980                                if (expr->inferred.hasParams()) {
     981                                        for (auto & imp : expr->inferred.inferParams() ) {
     982                                                imp.second.expr->accept(*visitor);
     983                                        }
     984                                }
    980985                        }
    981986                };
    982987        } // anonymous namespace
    983 
    984988        /// Check if this expression is or includes a deleted expression
    985989        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
     
    13701374                        }
    13711375
    1372                         // handle assertions. (seems deep)
     1376                        // handle assertions
    13731377
    13741378                        symtab.enterScope();
    1375                         for (auto & typeParam : mutType->forall) {
    1376                                 auto mutParam = typeParam.get_and_mutate();
    1377                                 symtab.addType(mutParam);
    1378                                 for (auto & asst : mutParam->assertions) {
    1379                                         asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
    1380                                         symtab.addId(asst);
    1381                                 }
    1382                                 typeParam = mutParam;
     1379                        mutType->forall.clear();
     1380                        mutType->assertions.clear();
     1381                        for (auto & typeParam : mutDecl->type_params) {
     1382                                symtab.addType(typeParam);
     1383                                mutType->forall.emplace_back(new ast::TypeInstType(typeParam->name, typeParam));
     1384                        }
     1385                        for (auto & asst : mutDecl->assertions) {
     1386                                asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
     1387                                symtab.addId(asst);
     1388                                mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
    13831389                        }
    13841390
     
    14021408                        mutType->returns = std::move(returnTypes);
    14031409
     1410                        auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID));
     1411
    14041412                        std::list<ast::ptr<ast::Stmt>> newStmts;
    14051413                        resolveWithExprs (mutDecl->withExprs, newStmts);
     
    14131421                        symtab.leaveScope();
    14141422
     1423                        mutDecl->type = renamedType;
    14151424                        mutDecl->mangleName = Mangle::mangle(mutDecl);
    14161425                        mutDecl->isTypeFixed = true;
  • src/ResolvExpr/SatisfyAssertions.cpp

    rb3c8496 r53449a4  
    6969        /// Reference to a single deferred item
    7070        struct DeferRef {
    71                 const ast::DeclWithType * decl;
     71                const ast::VariableExpr * expr;
    7272                const ast::AssertionSetValue & info;
    7373                const AssnCandidate & match;
     
    7777        /// Acts like an indexed list of DeferRef
    7878        struct DeferItem {
    79                 const ast::DeclWithType * decl;
     79                const ast::VariableExpr * expr;
    8080                const ast::AssertionSetValue & info;
    8181                AssnCandidateList matches;
    8282
    8383                DeferItem(
    84                         const ast::DeclWithType * d, const ast::AssertionSetValue & i, AssnCandidateList && ms )
    85                 : decl( d ), info( i ), matches( std::move( ms ) ) {}
     84                        const ast::VariableExpr * d, const ast::AssertionSetValue & i, AssnCandidateList && ms )
     85                : expr( d ), info( i ), matches( std::move( ms ) ) {}
    8686
    8787                bool empty() const { return matches.empty(); }
     
    8989                AssnCandidateList::size_type size() const { return matches.size(); }
    9090
    91                 DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; }
     91                DeferRef operator[] ( unsigned i ) const { return { expr, info, matches[i] }; }
    9292        };
    9393
     
    138138        void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) {
    139139                for ( auto & i : have ) {
    140                         if ( i.second.isUsed ) { symtab.addId( i.first ); }
     140                        if ( i.second.isUsed ) { symtab.addId( i.first->var ); }
    141141                }
    142142        }
     
    144144        /// Binds a single assertion, updating satisfaction state
    145145        void bindAssertion(
    146                 const ast::DeclWithType * decl, const ast::AssertionSetValue & info, CandidateRef & cand,
     146                const ast::VariableExpr * expr, const ast::AssertionSetValue & info, CandidateRef & cand,
    147147                AssnCandidate & match, InferCache & inferred
    148148        ) {
     
    156156
    157157                // place newly-inferred assertion in proper location in cache
    158                 inferred[ info.resnSlot ][ decl->uniqueId ] = ast::ParamEntry{
    159                         candidate->uniqueId, candidate, match.adjType, decl->get_type(), varExpr };
     158                inferred[ info.resnSlot ][ expr->var->uniqueId ] = ast::ParamEntry{
     159                        candidate->uniqueId, candidate, match.adjType, expr->result, varExpr };
    160160        }
    161161
     
    169169
    170170                std::vector<ast::SymbolTable::IdData> candidates;
    171                 auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->name);
     171                auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->var->name);
    172172                if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
    173173                        // prefilter special decls by argument type, if already known
    174                         ast::ptr<ast::Type> thisArgType = strict_dynamic_cast<const ast::PointerType *>(assn.first->get_type())->base
     174                        ast::ptr<ast::Type> thisArgType = assn.first->result.strict_as<ast::PointerType>()->base
    175175                                .strict_as<ast::FunctionType>()->params[0]
    176176                                .strict_as<ast::ReferenceType>()->base;
     
    184184                }
    185185                else {
    186                         candidates = sat.symtab.lookupId(assn.first->name);
     186                        candidates = sat.symtab.lookupId(assn.first->var->name);
    187187                }
    188188                for ( const ast::SymbolTable::IdData & cdata : candidates ) {
     
    194194                        // if we should implement the same rule here
    195195                        // (i.e. error if unique best match is deleted)
    196                         if (candidate->isDeleted) continue;
     196                        if (candidate->isDeleted && candidate->linkage == ast::Linkage::AutoGen) continue;
    197197
    198198                        // build independent unification context for candidate
     
    200200                        ast::TypeEnvironment newEnv{ sat.cand->env };
    201201                        ast::OpenVarSet newOpen{ sat.cand->open };
    202                         ast::ptr< ast::Type > toType = assn.first->get_type();
     202                        ast::ptr< ast::Type > toType = assn.first->result;
    203203                        ast::ptr< ast::Type > adjType =
    204204                                renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ) );
     
    337337                                        // compute conversion cost from satisfying decl to assertion
    338338                                        cost += computeConversionCost(
    339                                                 assn.match.adjType, assn.decl->get_type(), false, symtab, env );
     339                                                assn.match.adjType, assn.expr->result, false, symtab, env );
    340340
    341341                                        // mark vars+specialization on function-type assertions
     
    350350                                        cost.incVar( func->forall.size() );
    351351
    352                                         for ( const ast::TypeDecl * td : func->forall ) {
    353                                                 cost.decSpec( td->assertions.size() );
    354                                         }
     352                                        cost.decSpec( func->assertions.size() );
    355353                                }
    356354                        }
     
    451449                                ss << (tabs-1) << "Too many non-unique satisfying assignments for assertions:\n";
    452450                                for ( const auto & d : sat.deferred ) {
    453                                         ast::print( ss, d.decl, tabs );
     451                                        ast::print( ss, d.expr, tabs );
    454452                                }
    455453
     
    469467                                        ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n";
    470468                                        for ( const auto& d : sat.deferred ) {
    471                                                 ast::print( ss, d.decl, tabs );
     469                                                ast::print( ss, d.expr, tabs );
    472470                                        }
    473471
     
    501499                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    502500
    503                                                 bindAssertion( r.decl, r.info, nextCand, match, nextInferred );
     501                                                bindAssertion( r.expr, r.info, nextCand, match, nextInferred );
    504502                                        }
    505503
  • src/ResolvExpr/Unify.cc

    rb3c8496 r53449a4  
    773773
    774774                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    775                                 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
     775                                if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {
    776776                                        // expand ttype parameter into its actual type
    777777                                        if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {
     
    888888                }
    889889
    890                 static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) {
     890                static void markAssertionSet( ast::AssertionSet & assns, const ast::VariableExpr * assn ) {
    891891                        auto i = assns.find( assn );
    892892                        if ( i != assns.end() ) {
     
    898898                static void markAssertions(
    899899                        ast::AssertionSet & assn1, ast::AssertionSet & assn2,
    900                         const ast::ParameterizedType * type
     900                        const ast::FunctionType * type
    901901                ) {
    902                         for ( const auto & tyvar : type->forall ) {
    903                                 for ( const ast::DeclWithType * assert : tyvar->assertions ) {
    904                                         markAssertionSet( assn1, assert );
    905                                         markAssertionSet( assn2, assert );
    906                                 }
     902                        for ( auto & assert : type->assertions ) {
     903                                markAssertionSet( assn1, assert );
     904                                markAssertionSet( assn2, assert );
    907905                        }
    908906                }
     
    10301028
    10311029                void postvisit( const ast::TypeInstType * typeInst ) {
    1032                         assert( open.find( typeInst->name ) == open.end() );
     1030                        assert( open.find( *typeInst ) == open.end() );
    10331031                        handleRefType( typeInst, type2 );
    10341032                }
     
    11711169                auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );
    11721170                ast::OpenVarSet::const_iterator
    1173                         entry1 = var1 ? open.find( var1->name ) : open.end(),
    1174                         entry2 = var2 ? open.find( var2->name ) : open.end();
     1171                        entry1 = var1 ? open.find( *var1 ) : open.end(),
     1172                        entry2 = var2 ? open.find( *var2 ) : open.end();
    11751173                bool isopen1 = entry1 != open.end();
    11761174                bool isopen2 = entry2 != open.end();
  • src/SymTab/Mangler.cc

    rb3c8496 r53449a4  
    666666                        // skip if not including qualifiers
    667667                        if ( typeMode ) return;
    668                         if ( auto ptype = dynamic_cast< const ast::ParameterizedType * >(type) ) {
     668                        if ( auto ptype = dynamic_cast< const ast::FunctionType * >(type) ) {
    669669                                if ( ! ptype->forall.empty() ) {
    670670                                        std::list< std::string > assertionNames;
    671671                                        int dcount = 0, fcount = 0, vcount = 0, acount = 0;
    672672                                        mangleName += Encoding::forall;
    673                                         for ( const ast::TypeDecl * decl : ptype->forall ) {
     673                                        for ( auto & decl : ptype->forall ) {
    674674                                                switch ( decl->kind ) {
    675675                                                case ast::TypeDecl::Kind::Dtype:
     
    686686                                                } // switch
    687687                                                varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
    688                                                 for ( const ast::DeclWithType * assert : decl->assertions ) {
    689                                                         ast::Pass<Mangler_new> sub_mangler(
    690                                                                 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
    691                                                         assert->accept( sub_mangler );
    692                                                         assertionNames.push_back( sub_mangler.core.get_mangleName() );
    693                                                         acount++;
    694                                                 } // for
     688                                        } // for
     689                                        for ( auto & assert : ptype->assertions ) {
     690                                                ast::Pass<Mangler_new> sub_mangler(
     691                                                        mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
     692                                                assert->var->accept( sub_mangler );
     693                                                assertionNames.push_back( sub_mangler.core.get_mangleName() );
     694                                                acount++;
    695695                                        } // for
    696696                                        mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
  • src/SymTab/Validate.cc

    rb3c8496 r53449a4  
    14631463        }
    14641464
     1465        /*
     1466
    14651467        /// Associates forward declarations of aggregates with their definitions
    14661468        class LinkReferenceToTypes_new final
     
    17931795                static const node_t * forallFixer(
    17941796                        const CodeLocation & loc, const node_t * node,
    1795                         ast::ParameterizedType::ForallList parent_t::* forallField
     1797                        ast::FunctionType::ForallList parent_t::* forallField
    17961798                ) {
    17971799                        for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) {
     
    18441846                }
    18451847        };
     1848        */
    18461849} // anonymous namespace
    18471850
     1851/*
    18481852const ast::Type * validateType(
    18491853                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
     
    18541858        return type->accept( lrt )->accept( fpd );
    18551859}
     1860*/
    18561861
    18571862} // namespace SymTab
  • src/SynTree/Declaration.h

    rb3c8496 r53449a4  
    181181  public:
    182182        Type * base;
    183         std::list< TypeDecl * > parameters;
    184183        std::list< DeclarationWithType * > assertions;
    185184
     
    190189        Type * get_base() const { return base; }
    191190        void set_base( Type * newValue ) { base = newValue; }
    192         std::list< TypeDecl* > & get_parameters() { return parameters; }
    193191        std::list< DeclarationWithType * >& get_assertions() { return assertions; }
    194192
  • src/SynTree/NamedTypeDecl.cc

    rb3c8496 r53449a4  
    2929NamedTypeDecl::NamedTypeDecl( const NamedTypeDecl &other )
    3030        : Parent( other ), base( maybeClone( other.base ) ) {
    31         cloneAll( other.parameters, parameters );
    3231        cloneAll( other.assertions, assertions );
    3332}
     
    3534NamedTypeDecl::~NamedTypeDecl() {
    3635        delete base;
    37         deleteAll( parameters );
    3836        deleteAll( assertions );
    3937}
     
    5654                base->print( os, indent+1 );
    5755        } // if
    58         if ( ! parameters.empty() ) {
    59                 os << endl << indent << "... with parameters" << endl;
    60                 printAll( parameters, os, indent+1 );
    61         } // if
    6256        if ( ! assertions.empty() ) {
    6357                os << endl << indent << "... with assertions" << endl;
     
    7670                base->print( os, indent+1 );
    7771        } // if
    78         if ( ! parameters.empty() ) {
    79                 os << endl << indent << "... with parameters" << endl;
    80                 printAll( parameters, os, indent+1 );
    81         } // if
    8272}
    8373
  • src/Tuples/TupleAssignment.cc

    rb3c8496 r53449a4  
    504504
    505505                        std::vector< ast::ptr< ast::Expr > > match() override {
    506                                 // temporary workaround for new and old ast to coexist and avoid name collision
    507                                 static UniqueName lhsNamer( "__massassign_Ln" );
    508                                 static UniqueName rhsNamer( "__massassign_Rn" );
     506                                static UniqueName lhsNamer( "__massassign_L" );
     507                                static UniqueName rhsNamer( "__massassign_R" );
    509508                                // empty tuple case falls into this matcher
    510509                                assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 );
     
    535534
    536535                        std::vector< ast::ptr< ast::Expr > > match() override {
    537                                 // temporary workaround for new and old ast to coexist and avoid name collision
    538                                 static UniqueName lhsNamer( "__multassign_Ln" );
    539                                 static UniqueName rhsNamer( "__multassign_Rn" );
     536                                static UniqueName lhsNamer( "__multassign_L" );
     537                                static UniqueName rhsNamer( "__multassign_R" );
    540538
    541539                                if ( lhs.size() != rhs.size() ) return {};
  • tests/errors/.expect/completeType.nast.x64.txt

    rb3c8496 r53449a4  
    1212      Application of
    1313        Variable Expression: *?: forall
    14           DT: data type
     14          instance of type DT (not function type)
    1515          function
    1616        ... with parameters
     
    2121        ... with resolved type:
    2222          pointer to forall
    23             [unbound]:data type
     23            instance of type [unbound] (not function type)
    2424            function
    2525          ... with parameters
     
    4141    void
    4242  )
    43   Environment:([unbound]) -> instance of struct A without body (no widening)
     43  Environment:([unbound]DT) -> instance of struct A without body (no widening)
    4444
    4545
     
    4747      Application of
    4848        Variable Expression: *?: forall
    49           DT: data type
     49          instance of type DT (not function type)
    5050          function
    5151        ... with parameters
     
    5656        ... with resolved type:
    5757          pointer to forall
    58             [unbound]:data type
     58            instance of type [unbound] (not function type)
    5959            function
    6060          ... with parameters
     
    7676    void
    7777  )
    78   Environment:([unbound]) -> instance of struct B with body (no widening)
     78  Environment:([unbound]DT) -> instance of struct B with body (no widening)
    7979
    8080
     
    113113Cost ( 0, 1, 0, 0, 1, -5, 0 ): Application of
    114114            Variable Expression: baz: forall
    115               T: sized data type
    116               ... with assertions
    117                 ?=?: pointer to function
     115              instance of type T (not function type)
     116              with assertions
     117              Variable Expression: ?=?: pointer to function
     118              ... with parameters
     119                reference to instance of type T (not function type)
     120                instance of type T (not function type)
     121              ... returning
     122                instance of type T (not function type)
     123
     124              ... with resolved type:
     125                pointer to function
    118126                ... with parameters
    119127                  reference to instance of type T (not function type)
     
    122130                  instance of type T (not function type)
    123131
    124                 ?{}: pointer to function
    125                 ... with parameters
    126                   reference to instance of type T (not function type)
    127                 ... returning nothing
    128 
    129                 ?{}: pointer to function
    130                 ... with parameters
    131                   reference to instance of type T (not function type)
    132                   instance of type T (not function type)
    133                 ... returning nothing
    134 
    135                 ^?{}: pointer to function
    136                 ... with parameters
    137                   reference to instance of type T (not function type)
    138                 ... returning nothing
    139 
     132              Variable Expression: ?{}: pointer to function
     133              ... with parameters
     134                reference to instance of type T (not function type)
     135              ... returning nothing
     136
     137              ... with resolved type:
     138                pointer to function
     139                ... with parameters
     140                  reference to instance of type T (not function type)
     141                ... returning nothing
     142
     143              Variable Expression: ?{}: pointer to function
     144              ... with parameters
     145                reference to instance of type T (not function type)
     146                instance of type T (not function type)
     147              ... returning nothing
     148
     149              ... with resolved type:
     150                pointer to function
     151                ... with parameters
     152                  reference to instance of type T (not function type)
     153                  instance of type T (not function type)
     154                ... returning nothing
     155
     156              Variable Expression: ^?{}: pointer to function
     157              ... with parameters
     158                reference to instance of type T (not function type)
     159              ... returning nothing
     160
     161              ... with resolved type:
     162                pointer to function
     163                ... with parameters
     164                  reference to instance of type T (not function type)
     165                ... returning nothing
    140166
    141167              function
     
    146172            ... with resolved type:
    147173              pointer to forall
    148                 [unbound]:sized data type
    149                 ... with assertions
    150                   ?=?: pointer to function
     174                instance of type [unbound] (not function type)
     175                with assertions
     176                Variable Expression: ?=?: pointer to function
     177                ... with parameters
     178                  reference to instance of type T (not function type)
     179                  instance of type T (not function type)
     180                ... returning
     181                  instance of type T (not function type)
     182
     183                ... with resolved type:
     184                  pointer to function
    151185                  ... with parameters
    152186                    reference to instance of type [unbound] (not function type)
     
    155189                    instance of type [unbound] (not function type)
    156190
    157                   ?{}: pointer to function
     191                Variable Expression: ?{}: pointer to function
     192                ... with parameters
     193                  reference to instance of type T (not function type)
     194                ... returning nothing
     195
     196                ... with resolved type:
     197                  pointer to function
    158198                  ... with parameters
    159199                    reference to instance of type [unbound] (not function type)
    160200                  ... returning nothing
    161201
    162                   ?{}: pointer to function
     202                Variable Expression: ?{}: pointer to function
     203                ... with parameters
     204                  reference to instance of type T (not function type)
     205                  instance of type T (not function type)
     206                ... returning nothing
     207
     208                ... with resolved type:
     209                  pointer to function
    163210                  ... with parameters
    164211                    reference to instance of type [unbound] (not function type)
     
    166213                  ... returning nothing
    167214
    168                   ^?{}: pointer to function
     215                Variable Expression: ^?{}: pointer to function
     216                ... with parameters
     217                  reference to instance of type T (not function type)
     218                ... returning nothing
     219
     220                ... with resolved type:
     221                  pointer to function
    169222                  ... with parameters
    170223                    reference to instance of type [unbound] (not function type)
    171224                  ... returning nothing
    172 
    173225
    174226                function
     
    188240          void
    189241        )
    190         Environment:([unbound]) -> instance of type T (not function type) (no widening)
     242        Environment:([unbound]T) -> instance of type T (not function type) (no widening)
    191243
    192244      Could not satisfy assertion:
    193 ?=?: pointer to function
     245Variable Expression: ?=?: pointer to function
    194246        ... with parameters
    195           reference to instance of type [unbound] (not function type)
    196           instance of type [unbound] (not function type)
     247          reference to instance of type T (not function type)
     248          instance of type T (not function type)
    197249        ... returning
    198           instance of type [unbound] (not function type)
    199 
     250          instance of type T (not function type)
     251
     252        ... with resolved type:
     253          pointer to function
     254          ... with parameters
     255            reference to instance of type [unbound] (not function type)
     256            instance of type [unbound] (not function type)
     257          ... returning
     258            instance of type [unbound] (not function type)
     259
  • tests/errors/.expect/completeType.nast.x86.txt

    rb3c8496 r53449a4  
    1212      Application of
    1313        Variable Expression: *?: forall
    14           DT: data type
     14          instance of type DT (not function type)
    1515          function
    1616        ... with parameters
     
    2121        ... with resolved type:
    2222          pointer to forall
    23             [unbound]:data type
     23            instance of type [unbound] (not function type)
    2424            function
    2525          ... with parameters
     
    4141    void
    4242  )
    43   Environment:([unbound]) -> instance of struct A without body (no widening)
     43  Environment:([unbound]DT) -> instance of struct A without body (no widening)
    4444
    4545
     
    4747      Application of
    4848        Variable Expression: *?: forall
    49           DT: data type
     49          instance of type DT (not function type)
    5050          function
    5151        ... with parameters
     
    5656        ... with resolved type:
    5757          pointer to forall
    58             [unbound]:data type
     58            instance of type [unbound] (not function type)
    5959            function
    6060          ... with parameters
     
    7676    void
    7777  )
    78   Environment:([unbound]) -> instance of struct B with body (no widening)
     78  Environment:([unbound]DT) -> instance of struct B with body (no widening)
    7979
    8080
     
    113113Cost ( 0, 1, 0, 0, 1, -5, 0 ): Application of
    114114            Variable Expression: baz: forall
    115               T: sized data type
    116               ... with assertions
    117                 ?=?: pointer to function
     115              instance of type T (not function type)
     116              with assertions
     117              Variable Expression: ?=?: pointer to function
     118              ... with parameters
     119                reference to instance of type T (not function type)
     120                instance of type T (not function type)
     121              ... returning
     122                instance of type T (not function type)
     123
     124              ... with resolved type:
     125                pointer to function
    118126                ... with parameters
    119127                  reference to instance of type T (not function type)
     
    122130                  instance of type T (not function type)
    123131
    124                 ?{}: pointer to function
    125                 ... with parameters
    126                   reference to instance of type T (not function type)
    127                 ... returning nothing
    128 
    129                 ?{}: pointer to function
    130                 ... with parameters
    131                   reference to instance of type T (not function type)
    132                   instance of type T (not function type)
    133                 ... returning nothing
    134 
    135                 ^?{}: pointer to function
    136                 ... with parameters
    137                   reference to instance of type T (not function type)
    138                 ... returning nothing
    139 
     132              Variable Expression: ?{}: pointer to function
     133              ... with parameters
     134                reference to instance of type T (not function type)
     135              ... returning nothing
     136
     137              ... with resolved type:
     138                pointer to function
     139                ... with parameters
     140                  reference to instance of type T (not function type)
     141                ... returning nothing
     142
     143              Variable Expression: ?{}: pointer to function
     144              ... with parameters
     145                reference to instance of type T (not function type)
     146                instance of type T (not function type)
     147              ... returning nothing
     148
     149              ... with resolved type:
     150                pointer to function
     151                ... with parameters
     152                  reference to instance of type T (not function type)
     153                  instance of type T (not function type)
     154                ... returning nothing
     155
     156              Variable Expression: ^?{}: pointer to function
     157              ... with parameters
     158                reference to instance of type T (not function type)
     159              ... returning nothing
     160
     161              ... with resolved type:
     162                pointer to function
     163                ... with parameters
     164                  reference to instance of type T (not function type)
     165                ... returning nothing
    140166
    141167              function
     
    146172            ... with resolved type:
    147173              pointer to forall
    148                 [unbound]:sized data type
    149                 ... with assertions
    150                   ?=?: pointer to function
     174                instance of type [unbound] (not function type)
     175                with assertions
     176                Variable Expression: ?=?: pointer to function
     177                ... with parameters
     178                  reference to instance of type T (not function type)
     179                  instance of type T (not function type)
     180                ... returning
     181                  instance of type T (not function type)
     182
     183                ... with resolved type:
     184                  pointer to function
    151185                  ... with parameters
    152186                    reference to instance of type [unbound] (not function type)
     
    155189                    instance of type [unbound] (not function type)
    156190
    157                   ?{}: pointer to function
     191                Variable Expression: ?{}: pointer to function
     192                ... with parameters
     193                  reference to instance of type T (not function type)
     194                ... returning nothing
     195
     196                ... with resolved type:
     197                  pointer to function
    158198                  ... with parameters
    159199                    reference to instance of type [unbound] (not function type)
    160200                  ... returning nothing
    161201
    162                   ?{}: pointer to function
     202                Variable Expression: ?{}: pointer to function
     203                ... with parameters
     204                  reference to instance of type T (not function type)
     205                  instance of type T (not function type)
     206                ... returning nothing
     207
     208                ... with resolved type:
     209                  pointer to function
    163210                  ... with parameters
    164211                    reference to instance of type [unbound] (not function type)
     
    166213                  ... returning nothing
    167214
    168                   ^?{}: pointer to function
     215                Variable Expression: ^?{}: pointer to function
     216                ... with parameters
     217                  reference to instance of type T (not function type)
     218                ... returning nothing
     219
     220                ... with resolved type:
     221                  pointer to function
    169222                  ... with parameters
    170223                    reference to instance of type [unbound] (not function type)
    171224                  ... returning nothing
    172 
    173225
    174226                function
     
    188240          void
    189241        )
    190         Environment:([unbound]) -> instance of type T (not function type) (no widening)
     242        Environment:([unbound]T) -> instance of type T (not function type) (no widening)
    191243
    192244      Could not satisfy assertion:
    193 ?=?: pointer to function
     245Variable Expression: ?=?: pointer to function
    194246        ... with parameters
    195           reference to instance of type [unbound] (not function type)
    196           instance of type [unbound] (not function type)
     247          reference to instance of type T (not function type)
     248          instance of type T (not function type)
    197249        ... returning
    198           instance of type [unbound] (not function type)
    199 
     250          instance of type T (not function type)
     251
     252        ... with resolved type:
     253          pointer to function
     254          ... with parameters
     255            reference to instance of type [unbound] (not function type)
     256            instance of type [unbound] (not function type)
     257          ... returning
     258            instance of type [unbound] (not function type)
     259
  • tests/heap.cfa

    rb3c8496 r53449a4  
    1010// Created On       : Tue Nov  6 17:54:56 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Sep 25 15:21:52 2020
    13 // Update Count     : 73
     12// Last Modified On : Tue Dec 15 12:11:51 2020
     13// Update Count     : 79
    1414//
    1515
     
    2727// }
    2828
    29 #define __U_DEFAULT_MMAP_START__ (512 * 1024 + 1)
    30 size_t default_mmap_start() __attribute__(( weak )) {
    31         return __U_DEFAULT_MMAP_START__;
     29size_t default_heap_expansion() {
     30        return 10 * 1024 * 1024;
     31} // default_heap_expansion
     32
     33size_t default_mmap_start() {
     34        return 512 * 1024 + 1;
    3235} // default_mmap_start
    3336
  • tests/raii/.expect/ctor-autogen-ERR1.nast.txt

    rb3c8496 r53449a4  
    7070            ... with environment:
    7171              Types:
    72               Non-types:
    7372
    7473
Note: See TracChangeset for help on using the changeset viewer.