Changeset 53449a4
- Timestamp:
- Dec 16, 2020, 4:01:57 PM (2 years ago)
- 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. - Files:
-
- 1 added
- 3 deleted
- 62 edited
Legend:
- Unmodified
- Added
- Removed
-
Jenkins/FullBuild
rb3c8496 r53449a4 8 8 def err = null 9 9 10 final scmVars = checkout scm 11 final commitId = scmVars.GIT_COMMIT 12 10 13 try { 11 14 //Wrap build to add timestamp to command line … … 13 16 14 17 stage('Build') { 15 16 results = [null, null]17 18 18 19 parallel ( … … 31 32 32 33 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())] 34 35 } 35 36 } … … 102 103 } 103 104 104 //Helper routine to collect information about the git history105 def collect_git_info() {106 107 //create the temporary output directory in case it doesn't already exist108 def out_dir = pwd tmp: true109 sh "mkdir -p ${out_dir}"110 111 //parse git logs to find what changed112 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 120 105 //=========================================================================================================== 121 106 //Routine responsible of sending the email notification once the build is completed -
benchmark/io/http/main.cfa
rb3c8496 r53449a4 75 75 address.sin_port = htons( options.socket.port ); 76 76 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; 80 95 } 81 96 -
doc/theses/thierry_delisle_PhD/code/readQ_example/Makefile
rb3c8496 r53449a4 1 all: gui-proto 1 all: gui-proto-pthread gui-proto-fibre gui-proto-cforall 2 3 PRECIOUS: thrdlib/libthrd-pthread.so thrdlib/libthrd-fibre.so thrdlib/libthrd-cforall.so 2 4 3 5 CXXFLAGS = -fpic -g -O0 -I. 4 6 5 gui-proto: proto-gui/main.o thrdlib/thread.o 6 $(CXX) -pthread -ldl -o ${@} ${^} -ftls-model=initial-exec 7 thrdlib/libthrd-%.so: 8 +${MAKE} -C thrdlib libthrd-$*.so 9 10 gui-proto-%: proto-gui/main.o thrdlib/libthrd-%.so Makefile 11 $(CXX) -Lthrdlib -Wl,--rpath,thrdlib -pthread -o $@ $< -lthrd-$* 12 13 CFAINC=${HOME}/local/include/cfa-dev 14 CFALIB=${HOME}/local/lib/cfa-dev/x64-debug 15 CFAFLAGS=-z execstack -ftls-model=initial-exec -L${CFALIB} -Wl,-rpath,${CFALIB} 16 17 gui-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 11 11 #include <getopt.h> 12 12 using 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 #else29 uint64_t rand_seed;30 #endif31 struct {32 uint64_t fwd_seed;33 uint64_t bck_seed;34 } ready_rng;35 } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));36 13 37 14 //-------------------- … … 148 125 } 149 126 127 typedef uint64_t __wyhash64_state_t; 128 static 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 150 138 void Simulator( thread_t self ) { 151 139 for(unsigned i = 0; i < nproduce; i++) { … … 156 144 } 157 145 146 __wyhash64_state_t state = 0; 147 158 148 // Write the frame information 159 149 frame.number = i; 160 150 for( unsigned x = 0; x < fsize; x++ ) { 161 frame.data[x] = i;151 frame.data[x] = __wyhash64(state); 162 152 } 163 153 std::cout << "Simulated " << i << std::endl; … … 187 177 188 178 std::cout << "Rendered " << i << std::endl; 189 assert(total == i * fsize);179 // assert(total == i * fsize); 190 180 191 181 // Release … … 201 191 int main(int argc, char * argv[]) { 202 192 nframes = 3; 203 fsize = 1000;193 fsize = 3840 * 2160 * 4 * 4; 204 194 nproduce = 60; 205 206 const char * framework;207 195 208 196 for(;;) { … … 222 210 // Exit Case 223 211 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];231 212 goto run; 232 213 case 'b': … … 261 242 std::cerr << opt << std::endl; 262 243 usage: 263 std::cerr << "Usage: " << argv[0] << " [options] framework" << std::endl;244 std::cerr << "Usage: " << argv[0] << " [options]" << std::endl; 264 245 std::cerr << std::endl; 265 246 std::cerr << " -b, --buff=COUNT Number of frames to buffer" << std::endl; … … 270 251 } 271 252 run: 272 assert( framework );273 274 253 frames.reset(new Frame[nframes]); 275 254 for(unsigned i = 0; i < nframes; i++) { … … 280 259 std::cout << "(Buffering " << nframes << ")" << std::endl; 281 260 282 thrdlib::init( framework,2 );261 thrdlib::init( 2 ); 283 262 284 263 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.so1 all: fibre.so libthrd-pthread.so.so cforall.so 2 2 3 3 clean: 4 rm -rf fibre.so pthread.so4 rm -rf fibre.so libthrd-pthread.so.so cforall.so 5 5 6 6 CXXFLAGS=-Wall -Wextra -O3 -g -fpic -std=c++17 -pthread -ftls-model=initial-exec 7 7 8 pthread.so: pthread.cpp Makefile9 $(CXX) $(CXXFLAGS) -shared -o $ {@} ${<}8 libthrd-pthread.so: thread.cpp thread.hpp Makefile 9 $(CXX) $(CXXFLAGS) -shared -o $@ $< -DWITH_PTHREADS 10 10 11 fibre.so: fibre.cpp Makefile12 $(CXX) $(CXXFLAGS) -shared -o $ {@} ${<}-lfibre11 libthrd-fibre.so: thread.cpp thread.hpp Makefile 12 $(CXX) $(CXXFLAGS) -shared -o $@ $< -DWITH_LIBFIBRE -lfibre 13 13 14 14 CFAINC=${HOME}/local/include/cfa-dev … … 16 16 CFAFLAGS=-z execstack -I${CFAINC} -I${CFAINC}/concurrency -L${CFALIB} -Wl,-rpath,${CFALIB} 17 17 18 cforall.so: cforall.cpp Makefile19 $(CXX) $(CXXFLAGS) $(CFAFLAGS) -shared -o $ {@} ${<} -lcfathread -lcfa -ldl -lm18 libthrd-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 1 3 #include <pthread.h> 2 4 #include <errno.h> … … 97 99 // Basic kernel features 98 100 void thrdlib_init( int ) {} 101 void thrdlib_clean( void ) {} 99 102 } -
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 2 4 3 #i nclude <cstdarg> // va_start, va_end4 #include <cstdio>5 # include <cstring> // strlen6 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 12 14 13 #include <iostream> 14 #include <string> 15 namespace 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(); } 15 23 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 6 6 //-------------------- 7 7 // 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 ) ; 13 13 14 14 //-------------------- 15 15 // Basic kernel features 16 extern void init( const char * name,int procs );16 extern void init( int procs ); 17 17 extern void clean( void ); 18 18 }; -
libcfa/src/concurrency/coroutine.cfa
rb3c8496 r53449a4 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Oct 23 23:05:24 202013 // Update Count : 2 212 // Last Modified On : Tue Dec 15 12:06:04 2020 13 // Update Count : 23 14 14 // 15 15 … … 28 28 #include "kernel_private.hfa" 29 29 #include "exception.hfa" 30 #include "math.hfa" 31 32 #define CFA_COROUTINE_USE_MMAP 0 30 33 31 34 #define __CFA_INVOKE_PRIVATE__ … … 85 88 static const size_t MinStackSize = 1000; 86 89 extern size_t __page_size; // architecture pagesize HACK, should go in proper runtime singleton 90 extern int __map_prot; 87 91 88 92 void __stack_prepare( __stack_info_t * this, size_t create_size ); 93 void __stack_clean ( __stack_info_t * this ); 89 94 90 95 //----------------------------------------------------------------------------- … … 107 112 bool userStack = ((intptr_t)this.storage & 0x1) != 0; 108 113 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 ); 121 115 } 122 116 } … … 167 161 assert(__page_size != 0l); 168 162 size_t size = libCeiling( storageSize, 16 ) + stack_data_size; 163 size = ceiling(size, __page_size); 169 164 170 165 // If we are running debug, we also need to allocate a guardpage to catch stack overflows. 171 166 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 179 191 __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 );186 192 187 193 verify( ((intptr_t)storage & (libAlign() - 1)) == 0ul ); 188 194 return [storage, size]; 195 } 196 197 void __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); 189 217 } 190 218 … … 210 238 assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %zd bytes for a stack.", size, MinStackSize ); 211 239 212 this->storage = (__stack_t *)((intptr_t)storage + size );240 this->storage = (__stack_t *)((intptr_t)storage + size - sizeof(__stack_t)); 213 241 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)); 215 243 this->storage->exception_context.top_resume = 0p; 216 244 this->storage->exception_context.current_exception = 0p; -
libcfa/src/concurrency/coroutine.hfa
rb3c8496 r53449a4 102 102 } 103 103 104 extern void __stack_prepare ( __stack_info_t * this, size_t size /* ignored if storage already allocated */); 104 extern void __stack_prepare( __stack_info_t * this, size_t size /* ignored if storage already allocated */); 105 extern void __stack_clean ( __stack_info_t * this ); 106 105 107 106 108 // Suspend implementation inlined for performance … … 142 144 143 145 if( unlikely(dst->context.SP == 0p) ) { 144 active_thread()->curr_cor = dst;145 146 __stack_prepare(&dst->stack, 65000); 146 147 __cfactx_start(main, dst, cor, __cfactx_invoke_coroutine); 147 active_thread()->curr_cor = src;148 148 } 149 149 -
libcfa/src/concurrency/io/setup.cfa
rb3c8496 r53449a4 17 17 #define _GNU_SOURCE /* See feature_test_macros(7) */ 18 18 19 #if defined(__CFA_DEBUG__) 20 // #define __CFA_DEBUG_PRINT_IO__ 21 // #define __CFA_DEBUG_PRINT_IO_CORE__ 22 #endif 23 19 24 #include "io/types.hfa" 20 25 #include "kernel.hfa" … … 111 116 112 117 void __kernel_io_startup(void) { 113 __cfa abi_dbg_print_safe("Kernel : Creating EPOLL instance\n" );118 __cfadbg_print_safe(io_core, "Kernel : Creating EPOLL instance\n" ); 114 119 115 120 iopoll.epollfd = epoll_create1(0); … … 118 123 } 119 124 120 __cfa abi_dbg_print_safe("Kernel : Starting io poller thread\n" );125 __cfadbg_print_safe(io_core, "Kernel : Starting io poller thread\n" ); 121 126 122 127 iopoll.run = true; … … 132 137 // Wait for the io poller thread to finish 133 138 134 pthread_join( iopoll.thrd, 0p ); 135 free( iopoll.stack ); 139 __destroy_pthread( iopoll.thrd, iopoll.stack, 0p ); 136 140 137 141 int ret = close(iopoll.epollfd); … … 142 146 // Io polling is now fully stopped 143 147 144 __cfa abi_dbg_print_safe("Kernel : IO poller stopped\n" );148 __cfadbg_print_safe(io_core, "Kernel : IO poller stopped\n" ); 145 149 } 146 150 … … 150 154 id.id = doregister(&id); 151 155 __cfaabi_tls.this_proc_id = &id; 152 __cfa abi_dbg_print_safe("Kernel : IO poller thread starting\n" );156 __cfadbg_print_safe(io_core, "Kernel : IO poller thread starting\n" ); 153 157 154 158 // Block signals to control when they arrive … … 185 189 } 186 190 187 __cfa abi_dbg_print_safe("Kernel : IO poller thread stopping\n" );191 __cfadbg_print_safe(io_core, "Kernel : IO poller thread stopping\n" ); 188 192 unregister(&id); 189 193 return 0p; -
libcfa/src/concurrency/kernel/startup.cfa
rb3c8496 r53449a4 29 29 #include "kernel_private.hfa" 30 30 #include "startup.hfa" // STARTUP_PRIORITY_XXX 31 #include "math.hfa" 32 33 #define CFA_PROCESSOR_USE_MMAP 0 31 34 32 35 //----------------------------------------------------------------------------- … … 114 117 } 115 118 116 size_t __page_size = 0;119 extern size_t __page_size; 117 120 118 121 //----------------------------------------------------------------------------- … … 158 161 /* paranoid */ verify( ! __preemption_enabled() ); 159 162 __cfadbg_print_safe(runtime_core, "Kernel : Starting\n"); 160 161 __page_size = sysconf( _SC_PAGESIZE );162 163 163 164 __cfa_dbg_global_clusters.list{ __get }; … … 539 540 } 540 541 542 extern size_t __page_size; 541 543 void ^?{}(processor & this) with( this ){ 542 544 if( ! __atomic_load_n(&do_terminate, __ATOMIC_ACQUIRE) ) { … … 550 552 } 551 553 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 ); 556 555 557 556 disable_interrupts(); … … 678 677 679 678 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 } 683 685 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 ) ); 685 687 } // 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 690 701 691 702 check( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" ); … … 694 705 return stack; 695 706 } 707 708 void __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 696 731 697 732 #if defined(__CFA_WITH_VERIFY__) -
libcfa/src/concurrency/kernel_private.hfa
rb3c8496 r53449a4 49 49 50 50 void * __create_pthread( pthread_t *, void * (*)(void *), void * ); 51 void __destroy_pthread( pthread_t pthread, void * stack, void ** retval ); 51 52 52 53 -
libcfa/src/concurrency/preemption.cfa
rb3c8496 r53449a4 575 575 // Wait for the preemption thread to finish 576 576 577 pthread_join( alarm_thread, 0p ); 578 free( alarm_stack ); 577 __destroy_pthread( alarm_thread, alarm_stack, 0p ); 579 578 580 579 // Preemption is now fully stopped -
libcfa/src/heap.cfa
rb3c8496 r53449a4 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Sep 7 22:17:46202013 // Update Count : 95712 // Last Modified On : Wed Dec 16 12:28:25 2020 13 // Update Count : 1023 14 14 // 15 15 16 16 #include <unistd.h> // sbrk, sysconf 17 #include <stdlib.h> // EXIT_FAILURE 17 18 #include <stdbool.h> // true, false 18 19 #include <stdio.h> // snprintf, fileno … … 71 72 // Define the default extension heap amount in units of bytes. When the uC++ supplied heap reaches the brk address, 72 73 // 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), 74 75 75 76 // Define the mmap crossover point during allocation. Allocations less than this amount are allocated from buckets; … … 115 116 116 117 // statically allocated variables => zero filled. 117 static size_t pageSize; // architecture pagesize 118 size_t __page_size; // architecture pagesize 119 int __map_prot; // common mmap/mprotect protection 118 120 static size_t heapExpand; // sbrk advance 119 121 static size_t mmapStart; // cross over point for mmap … … 249 251 #endif // FASTLOOKUP 250 252 251 static int mmapFd = -1;// fake or actual fd for anonymous file253 static const off_t mmapFd = -1; // fake or actual fd for anonymous file 252 254 #ifdef __CFA_DEBUG__ 253 255 static bool heapBoot = 0; // detect recursion during boot … … 374 376 375 377 static 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; 377 379 mmapStart = value; // set global 378 380 … … 436 438 header = headerAddr( addr ); 437 439 438 if ( unlikely( heapEnd < addr ) ) {// mmapped ?440 if ( unlikely( addr < heapBegin || heapEnd < addr ) ) { // mmapped ? 439 441 fakeHeader( header, alignment ); 440 442 size = header->kind.real.blockSize & -3; // mmap size … … 443 445 444 446 #ifdef __CFA_DEBUG__ 445 checkHeader( addr < heapBegin, name, addr );// bad low address ?447 checkHeader( header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ? 446 448 #endif // __CFA_DEBUG__ 447 449 … … 464 466 } // headers 465 467 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 476 static 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 466 487 #define NO_MEMORY_MSG "insufficient heap memory available for allocating %zd new bytes." 467 488 … … 472 493 // If the size requested is bigger than the current remaining storage, increase the size of the heap. 473 494 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. 475 497 if ( sbrk( increase ) == (void *)-1 ) { // failed, no memory ? 476 498 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 ); 478 506 } // if 479 507 #ifdef __STATISTICS__ … … 483 511 #ifdef __CFA_DEBUG__ 484 512 // 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 ); 486 515 #endif // __CFA_DEBUG__ 487 516 rem = heapRemaining + increase - size; … … 542 571 block->header.kind.real.home = freeElem; // pointer back to free list of apropriate size 543 572 } else { // large size => mmap 544 if ( unlikely( size > ULONG_MAX - pageSize ) ) return 0p;545 tsize = ceiling2( tsize, pageSize ); // must be multiple of page size573 if ( unlikely( size > ULONG_MAX - __page_size ) ) return 0p; 574 tsize = ceiling2( tsize, __page_size ); // must be multiple of page size 546 575 #ifdef __STATISTICS__ 547 576 __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST ); … … 549 578 #endif // __STATISTICS__ 550 579 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 ); 552 581 if ( block == (HeapManager.Storage *)MAP_FAILED ) { // failed ? 553 582 if ( errno == ENOMEM ) abort( NO_MEMORY_MSG, tsize ); // no memory 554 583 // Do not call strerror( errno ) as it may call malloc. 555 abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu err or:%d.", &heapManager, tsize, errno );584 abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu errno:%d.", &heapManager, tsize, errno ); 556 585 } //if 557 586 #ifdef __CFA_DEBUG__ 558 587 // 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 ); 560 590 #endif // __CFA_DEBUG__ 561 591 block->header.kind.real.blockSize = tsize; // storage size for munmap … … 597 627 #endif // __STATISTICS__ 598 628 if ( munmap( header, size ) == -1 ) { 599 #ifdef __CFA_DEBUG__600 629 abort( "Attempt to deallocate storage %p not allocated or with corrupt header.\n" 601 630 "Possible cause is invalid pointer.", 602 631 addr ); 603 #endif // __CFA_DEBUG__604 632 } // if 605 633 } else { 606 634 #ifdef __CFA_DEBUG__ 607 635 // 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 ) ); 609 638 #endif // __CFA_DEBUG__ 610 639 … … 648 677 for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) { 649 678 #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 ) { 651 681 // 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` 654 683 // typeof(p) temp = (( p )`next)->top; // FIX ME: direct assignent fails, initialization works` 655 684 // p = temp; … … 675 704 676 705 static 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; 678 708 679 709 for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists … … 695 725 696 726 char * end = (char *)sbrk( 0 ); 697 heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, libAlign()) - end ); // move start of heap to multiple of alignment727 heapBegin = heapEnd = sbrk( (char *)ceiling2( (long unsigned int)end, __page_size ) - end ); // move start of heap to multiple of alignment 698 728 } // HeapManager 699 729 … … 713 743 #ifdef __CFA_DEBUG__ 714 744 if ( heapBoot ) { // check for recursion during system boot 715 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.716 745 abort( "boot() : internal error, recursively invoked during system boot." ); 717 746 } // if … … 935 964 header->kind.real.size = size; // reset allocation size 936 965 if ( unlikely( ozfill ) && size > osize ) { // previous request zero fill and larger ? 937 memset( (char *)oaddr + osize, (int)'\0', size - osize ); // initialize added storage966 memset( (char *)oaddr + osize, '\0', size - osize ); // initialize added storage 938 967 } // if 939 968 return oaddr; … … 960 989 header->kind.real.blockSize |= 2; // mark new request as zero filled 961 990 if ( size > osize ) { // previous request larger ? 962 memset( (char *)naddr + osize, (int)'\0', size - osize ); // initialize added storage991 memset( (char *)naddr + osize, '\0', size - osize ); // initialize added storage 963 992 } // if 964 993 } // if … … 999 1028 return cmemalignNoStats( alignment, dim, elemSize ); 1000 1029 } // cmemalign 1030 1001 1031 1002 1032 // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple … … 1017 1047 } // posix_memalign 1018 1048 1049 1019 1050 // Allocates size bytes and returns a pointer to the allocated memory. The memory address shall be a multiple of the 1020 1051 // page size. It is equivalent to memalign(sysconf(_SC_PAGESIZE),size). 1021 1052 void * valloc( size_t size ) { 1022 return memalign( pageSize, size );1053 return memalign( __page_size, size ); 1023 1054 } // valloc 1024 1055 … … 1026 1057 // Same as valloc but rounds size to multiple of page size. 1027 1058 void * pvalloc( size_t size ) { 1028 return memalign( pageSize, ceiling2( size, pageSize ) );1059 return memalign( __page_size, ceiling2( size, __page_size ) ); 1029 1060 } // pvalloc 1030 1061 … … 1165 1196 choose( option ) { 1166 1197 case M_TOP_PAD: 1167 heapExpand = ceiling2( value, pageSize ); return 1;1198 heapExpand = ceiling2( value, __page_size ); return 1; 1168 1199 case M_MMAP_THRESHOLD: 1169 1200 if ( setMmapStart( value ) ) return 1; … … 1327 1358 header->kind.real.blockSize |= 2; // mark new request as zero filled 1328 1359 if ( size > osize ) { // previous request larger ? 1329 memset( (char *)naddr + osize, (int)'\0', size - osize ); // initialize added storage1360 memset( (char *)naddr + osize, '\0', size - osize ); // initialize added storage 1330 1361 } // if 1331 1362 } // if -
libcfa/src/stdlib.hfa
rb3c8496 r53449a4 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Dec 8 18:27:22202013 // Update Count : 5 2412 // Last Modified On : Sat Dec 12 13:52:34 2020 13 // Update Count : 536 14 14 // 15 15 … … 49 49 50 50 static inline forall( dtype T | sized(T) ) { 51 // C forallsafe equivalents, i.e., implicit size specification51 // CFA safe equivalents, i.e., implicit size specification 52 52 53 53 T * malloc( void ) { … … 234 234 235 235 static inline forall( dtype T | sized(T) ) { 236 // C forallsafe initialization/copy, i.e., implicit size specification, non-array types236 // CFA safe initialization/copy, i.e., implicit size specification, non-array types 237 237 T * memset( T * dest, char fill ) { 238 238 return (T *)memset( dest, fill, sizeof(T) ); … … 243 243 } // memcpy 244 244 245 // C forallsafe initialization/copy, i.e., implicit size specification, array types245 // CFA safe initialization/copy, i.e., implicit size specification, array types 246 246 T * amemset( T dest[], char fill, size_t dim ) { 247 247 return (T *)(void *)memset( dest, fill, dim * sizeof(T) ); // C memset … … 253 253 } // distribution 254 254 255 // Cforall deallocation for multiple objects 255 // CFA deallocation for multiple objects 256 static inline forall( dtype T ) // FIX ME, problems with 0p in list 257 void free( T * ptr ) { 258 free( (void *)ptr ); // C free 259 } // free 256 260 static inline forall( dtype T, ttype TT | { void free( TT ); } ) 257 void free( T * addr, TT rest ) {258 free( ( void *)addr ); // use C free261 void free( T * ptr, TT rest ) { 262 free( ptr ); 259 263 free( rest ); 260 264 } // free 261 265 262 // C forallallocation/deallocation and constructor/destructor, non-array types266 // CFA allocation/deallocation and constructor/destructor, non-array types 263 267 static inline forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } ) 264 268 T * new( TT p ) { … … 272 276 ^(*ptr){}; // run destructor 273 277 } // if 274 free( ptr ); 278 free( ptr ); // always call free 275 279 } // delete 276 277 280 static inline forall( dtype T, ttype TT | { void ^?{}( T & ); void delete( TT ); } ) 278 281 void delete( T * ptr, TT rest ) { … … 281 284 } // delete 282 285 283 // C forallallocation/deallocation and constructor/destructor, array types286 // CFA allocation/deallocation and constructor/destructor, array types 284 287 forall( dtype T | sized(T), ttype TT | { void ?{}( T &, TT ); } ) T * anew( size_t dim, TT p ); 285 288 forall( dtype T | sized(T) | { void ^?{}( T & ); } ) void adelete( T arr[] ); -
src/AST/Convert.cpp
rb3c8496 r53449a4 55 55 56 56 // 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;57 ast::ptr<ast::Type> sizeType = nullptr; 58 const ast::FunctionDecl * dereferenceOperator = nullptr; 59 const ast::StructDecl * dtorStruct = nullptr; 60 const ast::FunctionDecl * dtorStructDestroy = nullptr; 61 61 62 62 } … … 205 205 ftype->parameters = get<DeclarationWithType>().acceptL(node->params); 206 206 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 } 208 213 209 214 visitType(node->type, ftype); … … 233 238 const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) { 234 239 // base comes from constructor 235 decl->parameters = get<TypeDecl>().acceptL( node->params );236 240 decl->assertions = get<DeclarationWithType>().acceptL( node->assertions ); 237 241 declPostamble( decl, node ); … … 603 607 604 608 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(), 606 610 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) );612 611 } 613 612 … … 1213 1212 // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns ); 1214 1213 // 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 1216 1235 return visitType( node, ty ); 1217 1236 } 1218 1237 1219 1238 const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) { 1220 ty->forall = get<TypeDecl>().acceptL( old->forall );1221 1239 ty->parameters = get<Expression>().acceptL( old->params ); 1222 1240 ty->hoistType = old->hoistType; … … 1301 1319 ty = new TypeInstType{ 1302 1320 cv( node ), 1303 node-> name,1321 node->typeString(), 1304 1322 get<TypeDecl>().accept1( node->base ), 1305 1323 get<Attribute>().acceptL( node->attributes ) … … 1308 1326 ty = new TypeInstType{ 1309 1327 cv( node ), 1310 node-> name,1328 node->typeString(), 1311 1329 node->kind == ast::TypeDecl::Ftype, 1312 1330 get<Attribute>().acceptL( node->attributes ) … … 1433 1451 /// at conversion stage, all created nodes are guaranteed to be unique, therefore 1434 1452 /// 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 = {}; 1436 1454 1437 1455 // Local Utilities: … … 1567 1585 // can function type have attributes? seems not to be the case. 1568 1586 // 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 } 1569 1599 1570 1600 auto decl = new ast::FunctionDecl{ … … 1586 1616 cache.emplace( old, decl ); 1587 1617 1618 decl->assertions = std::move(assertions); 1588 1619 decl->withExprs = GET_ACCEPT_V(withExprs, Expr); 1589 1620 decl->stmts = GET_ACCEPT_1(statements, CompoundStmt); … … 1704 1735 cache.emplace( old, decl ); 1705 1736 decl->assertions = GET_ACCEPT_V(assertions, DeclWithType); 1706 decl->params = GET_ACCEPT_V(parameters, TypeDecl);1707 1737 decl->extension = old->extension; 1708 1738 decl->uniqueId = old->uniqueId; … … 1720 1750 ); 1721 1751 decl->assertions = GET_ACCEPT_V(assertions, DeclWithType); 1722 decl->params = GET_ACCEPT_V(parameters, TypeDecl);1723 1752 decl->extension = old->extension; 1724 1753 decl->uniqueId = old->uniqueId; … … 2070 2099 } 2071 2100 2101 // TypeSubstitution shouldn't exist yet in old. 2072 2102 ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) { 2073 2103 2074 2104 if (!old) return nullptr; 2075 2105 if (old->empty()) return nullptr; 2106 assert(false); 2107 2108 /* 2076 2109 ast::TypeSubstitution *rslt = new ast::TypeSubstitution(); 2077 2110 … … 2081 2114 } 2082 2115 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 2088 2116 return rslt; 2117 */ 2089 2118 } 2090 2119 … … 2614 2643 ty->params.emplace_back(v->get_type()); 2615 2644 } 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 } 2617 2655 visitType( old, ty ); 2618 2656 } 2619 2657 2620 2658 void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) { 2621 ty->forall = GET_ACCEPT_V( forall, TypeDecl );2622 2659 ty->params = GET_ACCEPT_V( parameters, Expr ); 2623 2660 ty->hoistType = old->hoistType; … … 2807 2844 ConverterOldToNew c; 2808 2845 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 2809 2852 for(auto d : translationUnit) { 2810 2853 d->accept( c ); -
src/AST/Decl.cpp
rb3c8496 r53449a4 50 50 51 51 FunctionDecl::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 } 68 70 69 71 -
src/AST/Decl.hpp
rb3c8496 r53449a4 132 132 std::vector< ptr<Expr> > withExprs; 133 133 134 std::vector<ptr<TypeDecl>> type_params; 135 std::vector<ptr<DeclWithType>> assertions; 136 134 137 FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall, 135 138 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, … … 154 157 public: 155 158 ptr<Type> base; 156 std::vector<ptr<TypeDecl>> params;157 159 std::vector<ptr<DeclWithType>> assertions; 158 160 … … 160 162 const CodeLocation & loc, const std::string & name, Storage::Classes storage, 161 163 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() {} 163 165 164 166 /// Produces a name for the kind of alias -
src/AST/Expr.cpp
rb3c8496 r53449a4 206 206 assert( aggregate->result ); 207 207 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(); 244 209 245 210 // substitute aggregate generic parameters into member type -
src/AST/Expr.hpp
rb3c8496 r53449a4 112 112 113 113 bool hasSlots() const { return data.resnSlots; } 114 bool hasParams() const { return data.inferParams; } 114 115 115 116 ResnSlots& resnSlots() { -
src/AST/Fwd.hpp
rb3c8496 r53449a4 139 139 struct TranslationUnit; 140 140 // TODO: Get from the TranslationUnit: 141 extern Type *sizeType;142 extern FunctionDecl * dereferenceOperator;143 extern StructDecl * dtorStruct;144 extern FunctionDecl * dtorStructDestroy;141 extern ptr<Type> sizeType; 142 extern const FunctionDecl * dereferenceOperator; 143 extern const StructDecl * dtorStruct; 144 extern const FunctionDecl * dtorStructDestroy; 145 145 146 146 } -
src/AST/Pass.hpp
rb3c8496 r53449a4 34 34 35 35 #include "AST/SymbolTable.hpp" 36 37 #include "AST/ForallSubstitutionTable.hpp"38 36 39 37 // Private prelude header, needed for some of the magic tricks this class pulls off … … 66 64 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 67 65 // | WithSymbolTable - provides symbol table functionality 68 // | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation69 66 // 70 67 // Other Special Members: … … 258 255 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 259 256 260 /// Mutate forall-list, accounting for presence of type substitution map261 template<typename node_t>262 void mutate_forall( const node_t *& );263 264 257 public: 265 258 /// Logic to call the accept and mutate the parent if needed, delegates call to accept … … 287 280 /// Internal RAII guard for forall substitutions 288 281 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 ) 290 283 : pass( pass ), type( type ) { __pass::forall::enter(pass.core, 0, type ); } 291 284 ~guard_forall_subs() { __pass::forall::leave(pass.core, 0, type ); } 292 285 Pass<core_t> & pass; 293 const ParameterizedType * type;286 const FunctionType * type; 294 287 }; 295 288 … … 398 391 }; 399 392 400 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl401 struct WithForallSubstitutor {402 ForallSubstitutionTable subs;403 };404 405 393 } 406 394 -
src/AST/Pass.impl.hpp
rb3c8496 r53449a4 367 367 } 368 368 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 clone375 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 mutate382 maybe_accept( node, &node_t::forall );383 }384 }385 369 } 386 370 … … 504 488 __pass::symtab::addId( core, 0, func ); 505 489 VISIT( 506 // parameter declarations are now directly here490 // parameter declarations 507 491 maybe_accept( node, &FunctionDecl::params ); 508 492 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 ); 511 496 // First remember that we are now within a function. 512 497 ValueGuard< bool > oldInFunction( inFunction ); … … 609 594 VISIT({ 610 595 guard_symtab guard { *this }; 611 maybe_accept( node, &TypeDecl::params );612 596 maybe_accept( node, &TypeDecl::base ); 613 597 }) … … 638 622 VISIT({ 639 623 guard_symtab guard { *this }; 640 maybe_accept( node, &TypedefDecl::params );641 624 maybe_accept( node, &TypedefDecl::base ); 642 625 }) … … 1760 1743 1761 1744 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 ); 1764 1748 maybe_accept( node, &FunctionType::returns ); 1765 1749 maybe_accept( node, &FunctionType::params ); … … 1779 1763 VISIT({ 1780 1764 guard_symtab guard { *this }; 1781 guard_forall_subs forall_guard { *this, node };1782 mutate_forall( node );1783 1765 maybe_accept( node, &StructInstType::params ); 1784 1766 }) … … 1797 1779 VISIT({ 1798 1780 guard_symtab guard { *this }; 1799 guard_forall_subs forall_guard { *this, node };1800 mutate_forall( node );1801 1781 maybe_accept( node, &UnionInstType::params ); 1802 1782 }) … … 1812 1792 1813 1793 VISIT({ 1814 guard_forall_subs forall_guard { *this, node };1815 mutate_forall( node );1816 1794 maybe_accept( node, &EnumInstType::params ); 1817 1795 }) … … 1827 1805 1828 1806 VISIT({ 1829 guard_forall_subs forall_guard { *this, node };1830 mutate_forall( node );1831 1807 maybe_accept( node, &TraitInstType::params ); 1832 1808 }) … … 1843 1819 VISIT( 1844 1820 { 1845 guard_forall_subs forall_guard { *this, node };1846 mutate_forall( node );1847 1821 maybe_accept( node, &TypeInstType::params ); 1848 1822 } … … 1993 1967 { 1994 1968 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; 1996 1970 for ( const auto & p : node->typeEnv ) { 1997 1971 guard_symtab guard { *this }; … … 2006 1980 } 2007 1981 } 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 }2024 1982 ) 2025 1983 -
src/AST/Pass.proto.hpp
rb3c8496 r53449a4 396 396 // Some simple scoping rules 397 397 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 ) 399 399 -> decltype( core.subs, void() ) { 400 400 if ( ! type->forall.empty() ) core.subs.beginScope(); … … 402 402 403 403 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 ) 408 408 -> decltype( core.subs, void() ) { 409 409 if ( ! type->forall.empty() ) { core.subs.endScope(); } … … 411 411 412 412 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 * ) {} 423 414 424 415 // Replaces a TypeInstType's base TypeDecl according to the table -
src/AST/Print.cpp
rb3c8496 r53449a4 146 146 } 147 147 148 void print( const ast:: ParameterizedType::ForallList & forall ) {148 void print( const ast::FunctionType::ForallList & forall ) { 149 149 if ( forall.empty() ) return; 150 150 os << "forall" << endl; 151 151 ++indent; 152 152 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); 153 162 os << indent; 154 163 --indent; … … 206 215 void preprint( const ast::NamedTypeDecl * node ) { 207 216 if ( ! node->name.empty() ) { 208 if( deterministic_output && isUnboundType(node->name) ) os << "[unbound]:"; 209 else os << node->name << ": "; 217 os << node->name << ": "; 210 218 } 211 219 … … 224 232 } 225 233 226 if ( ! node->params.empty() ) {227 os << endl << indent << "... with parameters" << endl;228 ++indent;229 printAll( node->params );230 --indent;231 }232 233 234 if ( ! node->assertions.empty() ) { 234 235 os << endl << indent << "... with assertions" << endl; … … 266 267 } 267 268 268 void preprint( const ast:: ParameterizedType * node ) {269 void preprint( const ast::FunctionType * node ) { 269 270 print( node->forall ); 271 print( node->assertions ); 270 272 print( node->qualifiers ); 271 273 } 272 274 273 275 void preprint( const ast::BaseInstType * node ) { 274 print( node->forall );275 276 print( node->attributes ); 276 277 print( node->qualifiers ); … … 1383 1384 virtual const ast::Type * visit( const ast::TypeInstType * node ) override final { 1384 1385 preprint( node ); 1385 const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node-> name;1386 const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->typeString(); 1386 1387 os << "instance of type " << _name 1387 1388 << " (" << (node->kind == ast::TypeDecl::Ftype ? "" : "not ") << "function type)"; … … 1510 1511 os << indent << "Types:" << endl; 1511 1512 for ( const auto& i : *node ) { 1512 os << indent+1 << i.first << " -> ";1513 os << indent+1 << i.first.typeString() << " -> "; 1513 1514 indent += 2; 1514 1515 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 );1523 1516 indent -= 2; 1524 1517 os << endl; -
src/AST/SymbolTable.cpp
rb3c8496 r53449a4 414 414 415 415 void 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 ); 417 423 addIds( func->returns ); 418 424 addIds( func->params ); -
src/AST/TranslationUnit.hpp
rb3c8496 r53449a4 29 29 std::map< UniqueId, Decl * > idMap; 30 30 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; 35 35 } global; 36 36 }; -
src/AST/Type.cpp
rb3c8496 r53449a4 21 21 22 22 #include "Decl.hpp" 23 #include "ForallSubstitutor.hpp" // for substituteForall24 23 #include "Init.hpp" 25 24 #include "Common/utility.h" // for copy, move … … 92 91 // GENERATED END 93 92 94 // --- ParameterizedType95 96 void ParameterizedType::initWithSub(97 const ParameterizedType & o, Pass< ForallSubstitutor > & sub98 ) {99 forall = sub.core( o.forall );100 }101 102 93 // --- 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 map110 returns = sub.core( o.returns ); // apply to return and parameter types111 params = sub.core( o.params );112 }113 114 94 namespace { 115 95 bool containsTtype( const std::vector<ptr<Type>> & l ) { … … 123 103 bool FunctionType::isTtype() const { 124 104 return containsTtype( returns ) || containsTtype( params ); 125 }126 127 // --- BaseInstType128 129 void BaseInstType::initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ) {130 ParameterizedType::initWithSub( o, sub ); // initialize substitution131 params = sub.core( o.params ); // apply to parameters132 }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 );139 105 } 140 106 … … 177 143 : BaseInstType( b->name, q, move(as) ), base( b ) {} 178 144 179 // --- TypeInstType180 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 substitution185 base = sub.core( o.base ); // apply to base type186 }187 188 145 void TypeInstType::set_base( const TypeDecl * b ) { 189 146 base = b; … … 222 179 // TODO: once TypeInstType representation is updated, it should properly check 223 180 // 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; 236 182 } 237 183 return false; -
src/AST/Type.hpp
rb3c8496 r53449a4 36 36 37 37 template< typename T > class Pass; 38 39 struct ForallSubstitutor;40 38 41 39 class Type : public Node { … … 267 265 }; 268 266 269 /// Base type for potentially forall-qualified types270 class ParameterizedType : public Type {271 protected:272 /// initializes forall with substitutor273 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 type287 ParameterizedType( const ParameterizedType & ) = delete;288 289 ParameterizedType( ParameterizedType && ) = default;290 291 // no need to change destructor, and operator= deleted in Node292 293 private:294 virtual ParameterizedType * clone() const override = 0;295 MUTATE_FRIEND296 };297 298 267 /// Function variable arguments flag 299 268 enum ArgumentFlag { FixedArgs, VariableArgs }; 300 269 301 270 /// Type of a function `[R1, R2](*)(P1, P2, P3)` 302 class FunctionType final : public ParameterizedType { 303 public: 271 class FunctionType final : public Type { 272 public: 273 using ForallList = std::vector<ptr<TypeInstType>>; 274 using AssertionList = std::vector<ptr<VariableExpr>>; 275 ForallList forall; 276 AssertionList assertions; 277 304 278 std::vector<ptr<Type>> returns; 305 279 std::vector<ptr<Type>> params; … … 313 287 314 288 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; 318 292 319 293 /// true if either the parameters or return values contain a tttype … … 329 303 330 304 /// 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 ); 305 class BaseInstType : public Type { 335 306 public: 336 307 std::vector<ptr<Expr>> params; … … 340 311 BaseInstType( 341 312 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) {} 343 314 344 315 BaseInstType( 345 316 const std::string& n, std::vector<ptr<Expr>> && params, 346 317 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; 350 321 351 322 /// Gets aggregate declaration this type refers to … … 423 394 public: 424 395 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) 425 399 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; } 426 418 427 419 TypeInstType( … … 433 425 : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {} 434 426 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) {} 436 431 437 432 /// sets `base`, updating `kind` correctly … … 444 439 445 440 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 } 446 446 private: 447 447 TypeInstType * clone() const override { return new TypeInstType{ *this }; } … … 536 536 537 537 bool isUnboundType(const Type * type); 538 bool isUnboundType(const std::string & tname); 539 538 539 } 540 541 namespace 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 }; 540 552 } 541 553 -
src/AST/TypeEnvironment.cpp
rb3c8496 r53449a4 52 52 for ( const auto & i : open ) { 53 53 if ( first ) { first = false; } else { out << ' '; } 54 out << i.first << "(" << i.second << ")";54 out << i.first.typeString() << "(" << i.second << ")"; 55 55 } 56 56 } … … 62 62 if(first) first = false; 63 63 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; 66 69 } 67 70 out << ")"; … … 79 82 } 80 83 81 const EqvClass * TypeEnvironment::lookup( const std::string& var ) const {84 const EqvClass * TypeEnvironment::lookup( const TypeInstType::TypeEnvKey & var ) const { 82 85 for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) { 83 86 if ( i->vars.find( var ) != i->vars.end() ) return &*i; … … 105 108 } 106 109 107 void TypeEnvironment::add( const ParameterizedType::ForallList & tyDecls ) {108 for ( const TypeDecl *tyDecl : tyDecls ) {110 void TypeEnvironment::add( const FunctionType::ForallList & tyDecls ) { 111 for ( auto & tyDecl : tyDecls ) { 109 112 env.emplace_back( tyDecl ); 110 113 } … … 119 122 void TypeEnvironment::writeToSubstitution( TypeSubstitution & sub ) const { 120 123 for ( const auto & clz : env ) { 121 std::string clzRep; 124 TypeInstType::TypeEnvKey clzRep; 125 bool first = true; 122 126 for ( const auto & var : clz.vars ) { 123 127 if ( clz.bound ) { 124 128 sub.add( var, clz.bound ); 125 } else if ( clzRep.empty()) {129 } else if ( first ) { 126 130 clzRep = var; 131 first = false; 127 132 } else { 128 sub.add( var, new TypeInstType{ clzRep , clz.data.kind} );133 sub.add( var, new TypeInstType{ clzRep } ); 129 134 } 130 135 } … … 141 146 struct Occurs : public ast::WithVisitorRef<Occurs> { 142 147 bool result; 143 std:: set< std::string> vars;148 std::unordered_set< TypeInstType::TypeEnvKey > vars; 144 149 const TypeEnvironment & tenv; 145 150 146 Occurs( const std::string& var, const TypeEnvironment & env )151 Occurs( const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env ) 147 152 : result( false ), vars(), tenv( env ) { 148 153 if ( const EqvClass * clz = tenv.lookup( var ) ) { … … 154 159 155 160 void previsit( const TypeInstType * typeInst ) { 156 if ( vars.count( typeInst->name) ) {161 if ( vars.count( *typeInst ) ) { 157 162 result = true; 158 } else if ( const EqvClass * clz = tenv.lookup( typeInst->name) ) {163 } else if ( const EqvClass * clz = tenv.lookup( *typeInst ) ) { 159 164 if ( clz->bound ) { 160 165 clz->bound->accept( *visitor ); … … 165 170 166 171 /// 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 ) { 168 173 Pass<Occurs> occur{ var, env }; 169 174 maybe_accept( ty, occur ); … … 280 285 // remove references from bound type, so that type variables can only bind to value types 281 286 ptr<Type> target = bindTo->stripReferences(); 282 auto tyvar = open.find( typeInst->name);287 auto tyvar = open.find( *typeInst ); 283 288 assert( tyvar != open.end() ); 284 289 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 ); 288 293 if ( it != env.end() ) { 289 294 if ( it->bound ) { … … 308 313 } else { 309 314 env.emplace_back( 310 typeInst->name, target, widen.first && widen.second, data );315 *typeInst, target, widen.first && widen.second, data ); 311 316 } 312 317 return true; … … 318 323 WidenMode widen, const SymbolTable & symtab 319 324 ) { 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 ); 322 327 323 328 // exit early if variables already bound together … … 333 338 if ( c1 != env.end() ) { 334 339 if ( c1->bound ) { 335 if ( occurs( c1->bound, var2->name, *this ) ) return false;340 if ( occurs( c1->bound, *var2, *this ) ) return false; 336 341 type1 = c1->bound; 337 342 } … … 340 345 if ( c2 != env.end() ) { 341 346 if ( c2->bound ) { 342 if ( occurs( c2->bound, var1->name, *this ) ) return false;347 if ( occurs( c2->bound, *var1, *this ) ) return false; 343 348 type2 = c2->bound; 344 349 } … … 378 383 } else if ( c1 != env.end() ) { 379 384 // var2 unbound, add to env[c1] 380 c1->vars.emplace( var2->name);385 c1->vars.emplace( *var2 ); 381 386 c1->allowWidening = widen1; 382 387 c1->data.isComplete |= data.isComplete; 383 388 } else if ( c2 != env.end() ) { 384 389 // var1 unbound, add to env[c2] 385 c2->vars.emplace( var1->name);390 c2->vars.emplace( *var1 ); 386 391 c2->allowWidening = widen2; 387 392 c2->data.isComplete |= data.isComplete; 388 393 } else { 389 394 // 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 ); 391 396 } 392 397 … … 452 457 } 453 458 454 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string& var ) {459 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const TypeInstType::TypeEnvKey & var ) { 455 460 for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) { 456 461 if ( i->vars.count( var ) ) return i; -
src/AST/TypeEnvironment.hpp
rb3c8496 r53449a4 55 55 /// recorded. More investigation is needed. 56 56 struct 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 ); 60 60 } 61 61 }; … … 70 70 71 71 /// Set of assertions pending satisfaction 72 using AssertionSet = std::map< readonly<DeclWithType>, AssertionSetValue, AssertCompare >;72 using AssertionSet = std::map< const VariableExpr *, AssertionSetValue, AssertCompare >; 73 73 74 74 /// Set of open variables 75 using OpenVarSet = std::unordered_map< std::string, TypeDecl::Data >;75 using OpenVarSet = std::unordered_map< TypeInstType::TypeEnvKey, TypeDecl::Data >; 76 76 77 77 /// Merges one set of open vars into another … … 89 89 /// they bind to. 90 90 struct EqvClass { 91 std:: set< std::string> vars;91 std::unordered_set< TypeInstType::TypeEnvKey > vars; 92 92 ptr<Type> bound; 93 93 bool allowWidening; … … 101 101 102 102 /// Singleton class constructor from TypeDecl 103 EqvClass( const Type Decl * decl)104 : vars{ decl->name }, bound(), allowWidening( true ), data( decl) {}103 EqvClass( const TypeInstType * inst ) 104 : vars{ *inst }, bound(), allowWidening( true ), data( inst->base ) {} 105 105 106 106 /// Singleton class constructor from substitution 107 EqvClass( const std::string& v, const Type * b )107 EqvClass( const TypeInstType::TypeEnvKey & v, const Type * b ) 108 108 : vars{ v }, bound( b ), allowWidening( false ), data( TypeDecl::Dtype, false ) {} 109 109 110 110 /// 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 ) 112 112 : vars{ v }, bound( b ), allowWidening( w ), data( d ) { 113 113 reset_qualifiers( bound ); … … 115 115 116 116 /// 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 ) 118 118 : vars{ v, u }, bound(), allowWidening( w ), data( d ) {} 119 119 … … 131 131 public: 132 132 /// 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; 134 134 135 135 /// Add a new equivalence class for each type variable 136 void add( const ParameterizedType::ForallList & tyDecls );136 void add( const FunctionType::ForallList & tyDecls ); 137 137 138 138 /// Add a new equivalence class for each branch of the substitution, checking for conflicts … … 207 207 208 208 /// 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 & ); 210 210 }; 211 211 -
src/AST/TypeSubstitution.cpp
rb3c8496 r53449a4 39 39 void TypeSubstitution::initialize( const TypeSubstitution &src, TypeSubstitution &dest ) { 40 40 dest.typeEnv.clear(); 41 dest.varEnv.clear();42 41 dest.add( src ); 43 42 } … … 47 46 typeEnv[ i->first ] = i->second; 48 47 } // for 49 for ( VarEnvType::const_iterator i = other.varEnv.begin(); i != other.varEnv.end(); ++i ) {50 varEnv[ i->first ] = i->second;51 } // for52 48 } 53 49 54 void TypeSubstitution::add( std::stringformalType, const Type *actualType ) {55 typeEnv[ formalType ] = actualType;50 void TypeSubstitution::add( const TypeInstType * formalType, const Type *actualType ) { 51 typeEnv[ *formalType ] = actualType; 56 52 } 57 53 58 void TypeSubstitution::add Var( std::string formalExpr, const Expr *actualExpr) {59 varEnv[ formalExpr ] = actualExpr;54 void TypeSubstitution::add( const TypeInstType::TypeEnvKey & key, const Type * actualType) { 55 typeEnv[ key ] = actualType; 60 56 } 61 57 62 void TypeSubstitution::remove( std::stringformalType ) {63 TypeEnvType::iterator i = typeEnv.find( formalType );58 void TypeSubstitution::remove( const TypeInstType * formalType ) { 59 TypeEnvType::iterator i = typeEnv.find( *formalType ); 64 60 if ( i != typeEnv.end() ) { 65 typeEnv.erase( formalType );61 typeEnv.erase( *formalType ); 66 62 } // if 67 63 } 68 64 69 const Type *TypeSubstitution::lookup( std::stringformalType ) const {70 TypeEnvType::const_iterator i = typeEnv.find( formalType );65 const Type *TypeSubstitution::lookup( const TypeInstType * formalType ) const { 66 TypeEnvType::const_iterator i = typeEnv.find( *formalType ); 71 67 72 68 // break on not in substitution set … … 75 71 // attempt to transitively follow TypeInstType links. 76 72 while ( const TypeInstType *actualType = i->second.as<TypeInstType>()) { 77 const std::string& typeName = actualType->name;78 79 73 // break cycles in the transitive follow 80 if ( formalType == typeName ) break;74 if ( *formalType == *actualType ) break; 81 75 82 76 // Look for the type this maps to, returning previous mapping if none-such 83 i = typeEnv.find( typeName );77 i = typeEnv.find( *actualType ); 84 78 if ( i == typeEnv.end() ) return actualType; 85 79 } … … 90 84 91 85 bool TypeSubstitution::empty() const { 92 return typeEnv.empty() && varEnv.empty();86 return typeEnv.empty(); 93 87 } 94 88 … … 98 92 TypeSubstitution * newEnv; 99 93 EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} 100 void previsit( TypeDecl * tyDecl) {94 void previsit( FunctionType * ftype ) { 101 95 // 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 } 104 100 } 105 101 } … … 130 126 131 127 const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) { 132 BoundVarsType::const_iterator bound = boundVars.find( inst->name);128 BoundVarsType::const_iterator bound = boundVars.find( *inst ); 133 129 if ( bound != boundVars.end() ) return inst; 134 130 135 TypeEnvType::const_iterator i = sub.typeEnv.find( inst->name);131 TypeEnvType::const_iterator i = sub.typeEnv.find( *inst ); 136 132 if ( i == sub.typeEnv.end() ) { 137 133 return inst; … … 141 137 // TODO: investigate preventing type variables from being bound to themselves in the first place. 142 138 if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) { 143 if ( inst->name == replacement->name) {139 if ( *inst == *replacement ) { 144 140 return inst; 145 141 } … … 156 152 } 157 153 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 ) { 154 void TypeSubstitution::Substituter::previsit( const FunctionType * ptype ) { 169 155 GuardValue( boundVars ); 170 156 // bind type variables from forall-qualifiers 171 157 if ( freeOnly ) { 172 for ( const TypeDecl *tyvar : ptype->forall ) {173 boundVars.insert( tyvar->name);158 for ( auto & tyvar : ptype->forall ) { 159 boundVars.insert( *tyvar ); 174 160 } // for 175 161 } // if 176 162 } 177 163 164 /* 178 165 void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) { 179 166 GuardValue( boundVars ); 180 167 // bind type variables from forall-qualifiers 181 168 if ( freeOnly ) { 182 for ( const TypeDecl * tyvar : type->forall ) {183 boundVars.insert( tyvar->name );184 } // for185 169 // bind type variables from generic type instantiations 186 170 if ( auto decl = type->aggr() ) { 187 171 if ( ! type->params.empty() ) { 188 172 for ( const TypeDecl * tyvar : decl->params ) { 189 boundVars.insert( tyvar->name);173 boundVars.insert( *tyvar ); 190 174 } // for 191 175 } // if … … 201 185 handleAggregateType( aggregateUseType ); 202 186 } 187 */ 203 188 204 189 } // namespace ast -
src/AST/TypeSubstitution.hpp
rb3c8496 r53449a4 69 69 } 70 70 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 ); 72 73 void add( const TypeSubstitution &other ); 73 void remove( std::stringformalType );74 const Type *lookup( std::stringformalType ) const;74 void remove( const TypeInstType * formalType ); 75 const Type *lookup( const TypeInstType * formalType ) const; 75 76 bool empty() const; 76 77 void addVar( std::string formalExpr, const Expr *actualExpr );78 77 79 78 template< typename FormalIterator, typename ActualIterator > … … 101 100 friend class Pass; 102 101 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; 105 103 TypeEnvType typeEnv; 106 VarEnvType varEnv;107 104 108 105 public: … … 113 110 auto end() const -> decltype( typeEnv. end() ) { return typeEnv. end(); } 114 111 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(); }119 112 }; 120 113 114 // this is the only place where type parameters outside a function formal may be substituted. 121 115 template< typename FormalIterator, typename ActualIterator > 122 116 void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) { … … 129 123 if ( const TypeExpr *actual = actualIt->template as<TypeExpr>() ) { 130 124 if ( formal->name != "" ) { 131 typeEnv[ formal ->name] = actual->type;125 typeEnv[ formal ] = actual->type; 132 126 } // if 133 127 } else { … … 135 129 } // if 136 130 } else { 137 // TODO: type check the formal and actual parameters 138 if ( (*formalIt)->name != "" ) { 139 varEnv[ (*formalIt)->name ] = *actualIt; 140 } // if 131 141 132 } // if 142 133 } // for 143 134 } 135 136 144 137 145 138 template< typename FormalIterator, typename ActualIterator > … … 147 140 add( formalBegin, formalEnd, actualBegin ); 148 141 } 142 149 143 150 144 } // namespace ast … … 164 158 165 159 const Type * postvisit( const TypeInstType * aggregateUseType ); 166 const Expr * postvisit( const NameExpr * nameExpr );167 160 168 161 /// Records type variable bindings from forall-statements 169 void previsit( const ParameterizedType * type );162 void previsit( const FunctionType * type ); 170 163 /// Records type variable bindings from forall-statements and instantiations of generic types 171 void handleAggregateType( const BaseInstType * type );164 // void handleAggregateType( const BaseInstType * type ); 172 165 173 void previsit( const StructInstType * aggregateUseType );174 void previsit( const UnionInstType * aggregateUseType );166 // void previsit( const StructInstType * aggregateUseType ); 167 // void previsit( const UnionInstType * aggregateUseType ); 175 168 176 169 const TypeSubstitution & sub; 177 170 int subCount = 0; 178 171 bool freeOnly; 179 typedef std::unordered_set< std::string> BoundVarsType;172 typedef std::unordered_set< TypeInstType::TypeEnvKey > BoundVarsType; 180 173 BoundVarsType boundVars; 181 174 -
src/AST/module.mk
rb3c8496 r53449a4 33 33 AST/Expr.cpp \ 34 34 AST/Expr.hpp \ 35 AST/ForallSubstitutionTable.cpp \36 AST/ForallSubstitutionTable.hpp \37 AST/ForallSubstitutor.hpp \38 35 AST/FunctionSpec.hpp \ 39 36 AST/Fwd.hpp \ -
src/Common/PassVisitor.impl.h
rb3c8496 r53449a4 835 835 { 836 836 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 837 maybeAccept_impl( node->parameters, *this );838 837 maybeAccept_impl( node->base , *this ); 839 838 } … … 858 857 { 859 858 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 860 maybeAccept_impl( node->parameters, *this );861 859 maybeAccept_impl( node->base , *this ); 862 860 } … … 880 878 { 881 879 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 882 maybeMutate_impl( node->parameters, *this );883 880 maybeMutate_impl( node->base , *this ); 884 881 } … … 904 901 { 905 902 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 906 maybeAccept_impl( node->parameters, *this );907 903 maybeAccept_impl( node->base , *this ); 908 904 } … … 921 917 { 922 918 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 923 maybeAccept_impl( node->parameters, *this );924 919 maybeAccept_impl( node->base , *this ); 925 920 } … … 938 933 { 939 934 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } ); 940 maybeMutate_impl( node->parameters, *this );941 935 maybeMutate_impl( node->base , *this ); 942 936 } -
src/GenPoly/GenPoly.cc
rb3c8496 r53449a4 115 115 if (!env) return type; 116 116 if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) { 117 auto newType = env->lookup(typeInst ->name);117 auto newType = env->lookup(typeInst); 118 118 if (newType) return newType; 119 119 } … … 172 172 173 173 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; 175 175 } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) { 176 176 return isPolyType( arrayType->base, env ); … … 552 552 } 553 553 554 void addToTyVarMap( const ast::Type Decl* 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})); 556 556 } 557 557 … … 567 567 568 568 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)) { 570 570 for (auto & tyVar : ptype->forall) { 571 571 assert (tyVar); -
src/Parser/TypeData.cc
rb3c8496 r53449a4 900 900 ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true ); 901 901 } // if 902 buildList( td->symbolic.params, ret->get_parameters() );903 902 buildList( td->symbolic.assertions, ret->get_assertions() ); 904 903 ret->base->attributes.splice( ret->base->attributes.end(), attributes ); -
src/ResolvExpr/AdjustExprType.cc
rb3c8496 r53449a4 133 133 const ast::Type * postvisit( const ast::TypeInstType * inst ) { 134 134 // 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 ) ) { 136 136 if ( eqvClass->data.kind == ast::TypeDecl::Ftype ) { 137 137 return new ast::PointerType{ inst }; -
src/ResolvExpr/CandidateFinder.cpp
rb3c8496 r53449a4 212 212 // mark type variable and specialization cost of forall clause 213 213 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() ); 217 215 218 216 return convCost; … … 220 218 221 219 void makeUnifiableVars( 222 const ast:: ParameterizedType * type, ast::OpenVarSet & unifiableVars,220 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars, 223 221 ast::AssertionSet & need 224 222 ) { 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; 230 228 } 231 229 } … … 953 951 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 954 952 ) { 955 if ( const ast::EqvClass * clz = func->env.lookup( inst->name) ) {953 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) { 956 954 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 957 955 CandidateRef newFunc{ new Candidate{ *func } }; … … 1077 1075 assert( toType ); 1078 1076 toType = resolveTypeof( toType, symtab ); 1079 toType = SymTab::validateType( castExpr->location, toType, symtab );1077 // toType = SymTab::validateType( castExpr->location, toType, symtab ); 1080 1078 toType = adjustExprType( toType, tenv, symtab ); 1081 1079 … … 1162 1160 1163 1161 if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) { 1164 auto td = cand->env.lookup( insttype->name);1162 auto td = cand->env.lookup(*insttype); 1165 1163 if(!td) { continue; } 1166 1164 expr = td->bound.get(); … … 1568 1566 // calculate target type 1569 1567 const ast::Type * toType = resolveTypeof( initAlt.type, symtab ); 1570 toType = SymTab::validateType( initExpr->location, toType, symtab );1568 // toType = SymTab::validateType( initExpr->location, toType, symtab ); 1571 1569 toType = adjustExprType( toType, tenv, symtab ); 1572 1570 // The call to find must occur inside this loop, otherwise polymorphic return -
src/ResolvExpr/CastCost.cc
rb3c8496 r53449a4 165 165 } else { 166 166 ast::TypeEnvironment newEnv{ env }; 167 if ( auto wParams = pointerType->base.as< ast:: ParameterizedType >() ) {167 if ( auto wParams = pointerType->base.as< ast::FunctionType >() ) { 168 168 newEnv.add( wParams->forall ); 169 169 } … … 202 202 ) { 203 203 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 ) ) { 205 205 // check cast cost against bound type, if present 206 206 if ( eqvClass->bound ) { -
src/ResolvExpr/CommonType.cc
rb3c8496 r53449a4 713 713 const ast::Type * base = oPtr->base; 714 714 if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) { 715 auto entry = open.find( var->name);715 auto entry = open.find( *var ); 716 716 if ( entry != open.end() ) { 717 717 ast::AssertionSet need, have; -
src/ResolvExpr/ConversionCost.cc
rb3c8496 r53449a4 498 498 ) { 499 499 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 ) ) { 501 501 if ( eqv->bound ) { 502 502 return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env ); … … 675 675 676 676 void 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 ) ) { 678 678 cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env ); 679 679 } else if ( const ast::TypeInstType * dstAsInst = 680 680 dynamic_cast< const ast::TypeInstType * >( dst ) ) { 681 if ( typeInstType->name == dstAsInst->name) {681 if ( *typeInstType == *dstAsInst ) { 682 682 cost = Cost::zero; 683 683 } -
src/ResolvExpr/FindOpenVars.cc
rb3c8496 r53449a4 112 112 // mark open/closed variables 113 113 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; 119 119 } 120 120 } 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; 126 126 } 127 127 } -
src/ResolvExpr/PolyCost.cc
rb3c8496 r53449a4 68 68 69 69 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 ) { 71 71 if ( const ast::TypeInstType * otherType = eqv->bound.as< ast::TypeInstType >() ) { 72 72 if ( symtab.lookupType( otherType->name ) ) { -
src/ResolvExpr/PtrsAssignable.cc
rb3c8496 r53449a4 134 134 } 135 135 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 ) ) { 137 137 if ( eqv->bound ) { 138 138 // T * = S * for any S depends on the type bound to T … … 146 146 const ast::TypeEnvironment & env ) { 147 147 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 ) ) { 149 149 return ptrsAssignable( src, eqv->bound, env ); 150 150 } -
src/ResolvExpr/PtrsCastable.cc
rb3c8496 r53449a4 180 180 } 181 181 } 182 } else if ( const ast::EqvClass * eqvClass = env.lookup( inst->name) ) {182 } else if ( const ast::EqvClass * eqvClass = env.lookup( *inst ) ) { 183 183 if ( eqvClass->data.kind == ast::TypeDecl::Ftype ) { 184 184 return -1; … … 283 283 ) { 284 284 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 ) ) { 286 286 return ptrsAssignable( src, eqvClass->bound, env ); 287 287 } -
src/ResolvExpr/RenameVars.cc
rb3c8496 r53449a4 19 19 #include <utility> // for pair 20 20 21 #include "AST/ForallSubstitutionTable.hpp"22 21 #include "AST/Pass.hpp" 23 22 #include "AST/Type.hpp" … … 39 38 int level = 0; 40 39 int resetCount = 0; 40 41 int next_expr_id = 1; 42 int next_usage_id = 1; 41 43 ScopedMap< std::string, std::string > nameMap; 44 ScopedMap< std::string, ast::TypeInstType::TypeEnvKey > idMap; 42 45 public: 43 ast::ForallSubstitutionTable subs;44 45 46 void reset() { 46 47 level = 0; … … 53 54 type->name = it->second; 54 55 } 56 } 57 58 void nextUsage() { 59 ++next_usage_id; 55 60 } 56 61 … … 78 83 79 84 const ast::TypeInstType * rename( const ast::TypeInstType * type ) { 80 // re-linking of base type handled by WithForallSubstitutor81 82 85 // 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; 89 94 type = mut; 90 95 } … … 93 98 } 94 99 95 template<typename NodeT> 96 const NodeT * openLevel( const NodeT * type ) { 100 const ast::FunctionType * openLevel( const ast::FunctionType * type, RenameMode mode ) { 97 101 if ( type->forall.empty() ) return type; 98 99 nameMap.beginScope(); 102 idMap.beginScope(); 100 103 101 104 // 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 ) { 122 132 if ( type->forall.empty() ) return; 123 124 nameMap.endScope(); 133 idMap.endScope(); 125 134 } 126 135 }; … … 142 151 }; 143 152 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; 147 155 148 156 const ast::FunctionType * previsit( const ast::FunctionType * type ) { 149 return renaming.openLevel( type ); 150 } 157 return renaming.openLevel( type, mode ); 158 } 159 160 /* 151 161 const ast::StructInstType * previsit( const ast::StructInstType * type ) { 152 162 return renaming.openLevel( type ); … … 158 168 return renaming.openLevel( type ); 159 169 } 170 */ 171 160 172 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 ) { 164 177 renaming.closeLevel( type ); 165 178 } … … 173 186 } 174 187 175 const ast::Type * renameTyVars( const ast::Type * t ) {176 ast::Type *tc = ast::deepCopy(t);188 const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode ) { 189 // ast::Type *tc = ast::deepCopy(t); 177 190 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 ); 180 196 } 181 197 -
src/ResolvExpr/RenameVars.h
rb3c8496 r53449a4 30 30 /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID 31 31 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 ); 33 38 34 39 /// resets internal state of renamer to avoid overflow 35 40 void resetTyVarRenaming(); 41 42 36 43 } // namespace ResolvExpr 37 44 -
src/ResolvExpr/ResolveTypeof.cc
rb3c8496 r53449a4 15 15 16 16 #include "ResolveTypeof.h" 17 #include "RenameVars.h" 17 18 18 19 #include <cassert> // for assert … … 218 219 mutDecl->mangleName = Mangle::mangle(mutDecl); // do not mangle unnamed variables 219 220 221 mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID); 220 222 mutDecl->isTypeFixed = true; 221 223 return mutDecl; -
src/ResolvExpr/Resolver.cc
rb3c8496 r53449a4 968 968 namespace { 969 969 /// 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> { 971 971 const ast::DeletedExpr * result = nullptr; 972 972 … … 976 976 } 977 977 978 void previsit( const ast::Expr * ) {978 void previsit( const ast::Expr * expr ) { 979 979 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 } 980 985 } 981 986 }; 982 987 } // anonymous namespace 983 984 988 /// Check if this expression is or includes a deleted expression 985 989 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { … … 1370 1374 } 1371 1375 1372 // handle assertions . (seems deep)1376 // handle assertions 1373 1377 1374 1378 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)); 1383 1389 } 1384 1390 … … 1402 1408 mutType->returns = std::move(returnTypes); 1403 1409 1410 auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID)); 1411 1404 1412 std::list<ast::ptr<ast::Stmt>> newStmts; 1405 1413 resolveWithExprs (mutDecl->withExprs, newStmts); … … 1413 1421 symtab.leaveScope(); 1414 1422 1423 mutDecl->type = renamedType; 1415 1424 mutDecl->mangleName = Mangle::mangle(mutDecl); 1416 1425 mutDecl->isTypeFixed = true; -
src/ResolvExpr/SatisfyAssertions.cpp
rb3c8496 r53449a4 69 69 /// Reference to a single deferred item 70 70 struct DeferRef { 71 const ast:: DeclWithType * decl;71 const ast::VariableExpr * expr; 72 72 const ast::AssertionSetValue & info; 73 73 const AssnCandidate & match; … … 77 77 /// Acts like an indexed list of DeferRef 78 78 struct DeferItem { 79 const ast:: DeclWithType * decl;79 const ast::VariableExpr * expr; 80 80 const ast::AssertionSetValue & info; 81 81 AssnCandidateList matches; 82 82 83 83 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 ) ) {} 86 86 87 87 bool empty() const { return matches.empty(); } … … 89 89 AssnCandidateList::size_type size() const { return matches.size(); } 90 90 91 DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; }91 DeferRef operator[] ( unsigned i ) const { return { expr, info, matches[i] }; } 92 92 }; 93 93 … … 138 138 void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) { 139 139 for ( auto & i : have ) { 140 if ( i.second.isUsed ) { symtab.addId( i.first ); }140 if ( i.second.isUsed ) { symtab.addId( i.first->var ); } 141 141 } 142 142 } … … 144 144 /// Binds a single assertion, updating satisfaction state 145 145 void bindAssertion( 146 const ast:: DeclWithType * decl, const ast::AssertionSetValue & info, CandidateRef & cand,146 const ast::VariableExpr * expr, const ast::AssertionSetValue & info, CandidateRef & cand, 147 147 AssnCandidate & match, InferCache & inferred 148 148 ) { … … 156 156 157 157 // 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 }; 160 160 } 161 161 … … 169 169 170 170 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); 172 172 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { 173 173 // 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())->base174 ast::ptr<ast::Type> thisArgType = assn.first->result.strict_as<ast::PointerType>()->base 175 175 .strict_as<ast::FunctionType>()->params[0] 176 176 .strict_as<ast::ReferenceType>()->base; … … 184 184 } 185 185 else { 186 candidates = sat.symtab.lookupId(assn.first-> name);186 candidates = sat.symtab.lookupId(assn.first->var->name); 187 187 } 188 188 for ( const ast::SymbolTable::IdData & cdata : candidates ) { … … 194 194 // if we should implement the same rule here 195 195 // (i.e. error if unique best match is deleted) 196 if (candidate->isDeleted ) continue;196 if (candidate->isDeleted && candidate->linkage == ast::Linkage::AutoGen) continue; 197 197 198 198 // build independent unification context for candidate … … 200 200 ast::TypeEnvironment newEnv{ sat.cand->env }; 201 201 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; 203 203 ast::ptr< ast::Type > adjType = 204 204 renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ) ); … … 337 337 // compute conversion cost from satisfying decl to assertion 338 338 cost += computeConversionCost( 339 assn.match.adjType, assn. decl->get_type(), false, symtab, env );339 assn.match.adjType, assn.expr->result, false, symtab, env ); 340 340 341 341 // mark vars+specialization on function-type assertions … … 350 350 cost.incVar( func->forall.size() ); 351 351 352 for ( const ast::TypeDecl * td : func->forall ) { 353 cost.decSpec( td->assertions.size() ); 354 } 352 cost.decSpec( func->assertions.size() ); 355 353 } 356 354 } … … 451 449 ss << (tabs-1) << "Too many non-unique satisfying assignments for assertions:\n"; 452 450 for ( const auto & d : sat.deferred ) { 453 ast::print( ss, d. decl, tabs );451 ast::print( ss, d.expr, tabs ); 454 452 } 455 453 … … 469 467 ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n"; 470 468 for ( const auto& d : sat.deferred ) { 471 ast::print( ss, d. decl, tabs );469 ast::print( ss, d.expr, tabs ); 472 470 } 473 471 … … 501 499 nextNewNeed.insert( match.need.begin(), match.need.end() ); 502 500 503 bindAssertion( r. decl, r.info, nextCand, match, nextInferred );501 bindAssertion( r.expr, r.info, nextCand, match, nextInferred ); 504 502 } 505 503 -
src/ResolvExpr/Unify.cc
rb3c8496 r53449a4 773 773 774 774 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 ) ) { 776 776 // expand ttype parameter into its actual type 777 777 if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) { … … 888 888 } 889 889 890 static void markAssertionSet( ast::AssertionSet & assns, const ast:: DeclWithType* assn ) {890 static void markAssertionSet( ast::AssertionSet & assns, const ast::VariableExpr * assn ) { 891 891 auto i = assns.find( assn ); 892 892 if ( i != assns.end() ) { … … 898 898 static void markAssertions( 899 899 ast::AssertionSet & assn1, ast::AssertionSet & assn2, 900 const ast:: ParameterizedType * type900 const ast::FunctionType * type 901 901 ) { 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 ); 907 905 } 908 906 } … … 1030 1028 1031 1029 void postvisit( const ast::TypeInstType * typeInst ) { 1032 assert( open.find( typeInst->name) == open.end() );1030 assert( open.find( *typeInst ) == open.end() ); 1033 1031 handleRefType( typeInst, type2 ); 1034 1032 } … … 1171 1169 auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 ); 1172 1170 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(); 1175 1173 bool isopen1 = entry1 != open.end(); 1176 1174 bool isopen2 = entry2 != open.end(); -
src/SymTab/Mangler.cc
rb3c8496 r53449a4 666 666 // skip if not including qualifiers 667 667 if ( typeMode ) return; 668 if ( auto ptype = dynamic_cast< const ast:: ParameterizedType * >(type) ) {668 if ( auto ptype = dynamic_cast< const ast::FunctionType * >(type) ) { 669 669 if ( ! ptype->forall.empty() ) { 670 670 std::list< std::string > assertionNames; 671 671 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 672 672 mangleName += Encoding::forall; 673 for ( const ast::TypeDecl *decl : ptype->forall ) {673 for ( auto & decl : ptype->forall ) { 674 674 switch ( decl->kind ) { 675 675 case ast::TypeDecl::Kind::Dtype: … … 686 686 } // switch 687 687 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 } // for688 } // 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++; 695 695 } // for 696 696 mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_"; -
src/SymTab/Validate.cc
rb3c8496 r53449a4 1463 1463 } 1464 1464 1465 /* 1466 1465 1467 /// Associates forward declarations of aggregates with their definitions 1466 1468 class LinkReferenceToTypes_new final … … 1793 1795 static const node_t * forallFixer( 1794 1796 const CodeLocation & loc, const node_t * node, 1795 ast:: ParameterizedType::ForallList parent_t::* forallField1797 ast::FunctionType::ForallList parent_t::* forallField 1796 1798 ) { 1797 1799 for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) { … … 1844 1846 } 1845 1847 }; 1848 */ 1846 1849 } // anonymous namespace 1847 1850 1851 /* 1848 1852 const ast::Type * validateType( 1849 1853 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) { … … 1854 1858 return type->accept( lrt )->accept( fpd ); 1855 1859 } 1860 */ 1856 1861 1857 1862 } // namespace SymTab -
src/SynTree/Declaration.h
rb3c8496 r53449a4 181 181 public: 182 182 Type * base; 183 std::list< TypeDecl * > parameters;184 183 std::list< DeclarationWithType * > assertions; 185 184 … … 190 189 Type * get_base() const { return base; } 191 190 void set_base( Type * newValue ) { base = newValue; } 192 std::list< TypeDecl* > & get_parameters() { return parameters; }193 191 std::list< DeclarationWithType * >& get_assertions() { return assertions; } 194 192 -
src/SynTree/NamedTypeDecl.cc
rb3c8496 r53449a4 29 29 NamedTypeDecl::NamedTypeDecl( const NamedTypeDecl &other ) 30 30 : Parent( other ), base( maybeClone( other.base ) ) { 31 cloneAll( other.parameters, parameters );32 31 cloneAll( other.assertions, assertions ); 33 32 } … … 35 34 NamedTypeDecl::~NamedTypeDecl() { 36 35 delete base; 37 deleteAll( parameters );38 36 deleteAll( assertions ); 39 37 } … … 56 54 base->print( os, indent+1 ); 57 55 } // if 58 if ( ! parameters.empty() ) {59 os << endl << indent << "... with parameters" << endl;60 printAll( parameters, os, indent+1 );61 } // if62 56 if ( ! assertions.empty() ) { 63 57 os << endl << indent << "... with assertions" << endl; … … 76 70 base->print( os, indent+1 ); 77 71 } // if 78 if ( ! parameters.empty() ) {79 os << endl << indent << "... with parameters" << endl;80 printAll( parameters, os, indent+1 );81 } // if82 72 } 83 73 -
src/Tuples/TupleAssignment.cc
rb3c8496 r53449a4 504 504 505 505 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" ); 509 508 // empty tuple case falls into this matcher 510 509 assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 ); … … 535 534 536 535 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" ); 540 538 541 539 if ( lhs.size() != rhs.size() ) return {}; -
tests/errors/.expect/completeType.nast.x64.txt
rb3c8496 r53449a4 12 12 Application of 13 13 Variable Expression: *?: forall 14 DT: data type14 instance of type DT (not function type) 15 15 function 16 16 ... with parameters … … 21 21 ... with resolved type: 22 22 pointer to forall 23 [unbound]:data type23 instance of type [unbound] (not function type) 24 24 function 25 25 ... with parameters … … 41 41 void 42 42 ) 43 Environment:([unbound] ) -> instance of struct A without body (no widening)43 Environment:([unbound]DT) -> instance of struct A without body (no widening) 44 44 45 45 … … 47 47 Application of 48 48 Variable Expression: *?: forall 49 DT: data type49 instance of type DT (not function type) 50 50 function 51 51 ... with parameters … … 56 56 ... with resolved type: 57 57 pointer to forall 58 [unbound]:data type58 instance of type [unbound] (not function type) 59 59 function 60 60 ... with parameters … … 76 76 void 77 77 ) 78 Environment:([unbound] ) -> instance of struct B with body (no widening)78 Environment:([unbound]DT) -> instance of struct B with body (no widening) 79 79 80 80 … … 113 113 Cost ( 0, 1, 0, 0, 1, -5, 0 ): Application of 114 114 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 118 126 ... with parameters 119 127 reference to instance of type T (not function type) … … 122 130 instance of type T (not function type) 123 131 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 140 166 141 167 function … … 146 172 ... with resolved type: 147 173 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 151 185 ... with parameters 152 186 reference to instance of type [unbound] (not function type) … … 155 189 instance of type [unbound] (not function type) 156 190 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 158 198 ... with parameters 159 199 reference to instance of type [unbound] (not function type) 160 200 ... returning nothing 161 201 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 163 210 ... with parameters 164 211 reference to instance of type [unbound] (not function type) … … 166 213 ... returning nothing 167 214 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 169 222 ... with parameters 170 223 reference to instance of type [unbound] (not function type) 171 224 ... returning nothing 172 173 225 174 226 function … … 188 240 void 189 241 ) 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) 191 243 192 244 Could not satisfy assertion: 193 ?=?: pointer to function245 Variable Expression: ?=?: pointer to function 194 246 ... 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) 197 249 ... 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 12 12 Application of 13 13 Variable Expression: *?: forall 14 DT: data type14 instance of type DT (not function type) 15 15 function 16 16 ... with parameters … … 21 21 ... with resolved type: 22 22 pointer to forall 23 [unbound]:data type23 instance of type [unbound] (not function type) 24 24 function 25 25 ... with parameters … … 41 41 void 42 42 ) 43 Environment:([unbound] ) -> instance of struct A without body (no widening)43 Environment:([unbound]DT) -> instance of struct A without body (no widening) 44 44 45 45 … … 47 47 Application of 48 48 Variable Expression: *?: forall 49 DT: data type49 instance of type DT (not function type) 50 50 function 51 51 ... with parameters … … 56 56 ... with resolved type: 57 57 pointer to forall 58 [unbound]:data type58 instance of type [unbound] (not function type) 59 59 function 60 60 ... with parameters … … 76 76 void 77 77 ) 78 Environment:([unbound] ) -> instance of struct B with body (no widening)78 Environment:([unbound]DT) -> instance of struct B with body (no widening) 79 79 80 80 … … 113 113 Cost ( 0, 1, 0, 0, 1, -5, 0 ): Application of 114 114 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 118 126 ... with parameters 119 127 reference to instance of type T (not function type) … … 122 130 instance of type T (not function type) 123 131 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 140 166 141 167 function … … 146 172 ... with resolved type: 147 173 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 151 185 ... with parameters 152 186 reference to instance of type [unbound] (not function type) … … 155 189 instance of type [unbound] (not function type) 156 190 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 158 198 ... with parameters 159 199 reference to instance of type [unbound] (not function type) 160 200 ... returning nothing 161 201 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 163 210 ... with parameters 164 211 reference to instance of type [unbound] (not function type) … … 166 213 ... returning nothing 167 214 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 169 222 ... with parameters 170 223 reference to instance of type [unbound] (not function type) 171 224 ... returning nothing 172 173 225 174 226 function … … 188 240 void 189 241 ) 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) 191 243 192 244 Could not satisfy assertion: 193 ?=?: pointer to function245 Variable Expression: ?=?: pointer to function 194 246 ... 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) 197 249 ... 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 10 10 // Created On : Tue Nov 6 17:54:56 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Sep 25 15:21:52202013 // Update Count : 7 312 // Last Modified On : Tue Dec 15 12:11:51 2020 13 // Update Count : 79 14 14 // 15 15 … … 27 27 // } 28 28 29 #define __U_DEFAULT_MMAP_START__ (512 * 1024 + 1) 30 size_t default_mmap_start() __attribute__(( weak )) { 31 return __U_DEFAULT_MMAP_START__; 29 size_t default_heap_expansion() { 30 return 10 * 1024 * 1024; 31 } // default_heap_expansion 32 33 size_t default_mmap_start() { 34 return 512 * 1024 + 1; 32 35 } // default_mmap_start 33 36 -
tests/raii/.expect/ctor-autogen-ERR1.nast.txt
rb3c8496 r53449a4 70 70 ... with environment: 71 71 Types: 72 Non-types:73 72 74 73
Note: See TracChangeset
for help on using the changeset viewer.