Changeset 4c925cd
- Timestamp:
- Aug 14, 2020, 11:40:04 AM (3 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 5715d43, fa5e0112
- Parents:
- 309d814 (diff), badd22f (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:
-
- 8 added
- 76 edited
Legend:
- Unmodified
- Added
- Removed
-
configure.ac
r309d814 r4c925cd 24 24 #Trasforming cc1 will break compilation 25 25 M4CFA_PROGRAM_NAME 26 27 #============================================================================== 28 # New AST toggling support 29 AH_TEMPLATE([CFA_USE_NEW_AST],[Sets whether or not to use the new-ast, this is adefault value and can be overrided by --old-ast and --new-ast]) 30 AC_ARG_ENABLE(new-ast, 31 [ --enable-new-ast whether or not to use new ast as the default AST algorithm], 32 [case "${enableval}" in 33 yes) newast=true ;; 34 no) newast=false ;; 35 *) AC_MSG_ERROR([bad value ${enableval} for --enable-new-ast]) ;; 36 esac],[newast=false]) 37 AC_DEFINE_UNQUOTED([CFA_USE_NEW_AST], $newast) 26 38 27 39 #============================================================================== -
driver/cc1.cc
r309d814 r4c925cd 10 10 // Created On : Fri Aug 26 14:23:51 2005 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat May 30 18:09:05 202013 // Update Count : 40 412 // Last Modified On : Thu Aug 13 21:03:15 2020 13 // Update Count : 407 14 14 // 15 15 … … 170 170 if ( arg == "-quiet" ) { 171 171 } else if ( arg == "-imultilib" || arg == "-imultiarch" ) { 172 i += 1; // and theargument172 i += 1; // and argument 173 173 } else if ( prefix( arg, "-A" ) ) { 174 174 } else if ( prefix( arg, "-D__GNU" ) ) { … … 177 177 //******** 178 178 } else if ( arg == "-D" && prefix( argv[i + 1], "__GNU" ) ) { 179 i += 1; // and theargument179 i += 1; // and argument 180 180 181 181 // strip flags controlling cpp step … … 184 184 cpp_flag = true; 185 185 } else if ( arg == "-D" && string( argv[i + 1] ) == "__CPP__" ) { 186 i += 1; // and theargument186 i += 1; // and argument 187 187 cpp_flag = true; 188 188 … … 194 194 cpp_out = argv[i]; 195 195 } else { 196 args[nargs++] = argv[i]; // pass theflag along196 args[nargs++] = argv[i]; // pass flag along 197 197 // CPP flags with an argument 198 198 if ( arg == "-D" || arg == "-U" || arg == "-I" || arg == "-MF" || arg == "-MT" || arg == "-MQ" || … … 200 200 arg == "-iwithprefix" || arg == "-iwithprefixbefore" || arg == "-isystem" || arg == "-isysroot" ) { 201 201 i += 1; 202 args[nargs++] = argv[i]; // pass theargument along202 args[nargs++] = argv[i]; // pass argument along 203 203 #ifdef __DEBUG_H__ 204 204 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; 205 205 #endif // __DEBUG_H__ 206 206 } else if ( arg == "-MD" || arg == "-MMD" ) { 207 // gcc frontend generates the dependency file-name after the -MD/-MMD flag, but it is necessary to 208 // prefix that file name with -MF. 207 209 args[nargs++] = "-MF"; // insert before file 208 210 i += 1; 209 args[nargs++] = argv[i]; // pass theargument along211 args[nargs++] = argv[i]; // pass argument along 210 212 #ifdef __DEBUG_H__ 211 213 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; … … 279 281 // Run the C preprocessor and save the output in the given file. 280 282 281 if ( fork() == 0 ) { 283 if ( fork() == 0 ) { // child process ? 282 284 // -o xxx.ii cannot be used to write the output file from cpp because no output file is created if cpp detects 283 285 // an error (e.g., cannot find include file). Whereas, output is always generated, even when there is an error, … … 388 390 389 391 } else { 390 args[nargs++] = argv[i]; // pass theflag along392 args[nargs++] = argv[i]; // pass flag along 391 393 if ( arg == "-o" ) { 392 394 i += 1; 393 395 cpp_out = argv[i]; 394 args[nargs++] = argv[i]; // pass theargument along396 args[nargs++] = argv[i]; // pass argument along 395 397 #ifdef __DEBUG_H__ 396 398 cerr << "arg:\"" << argv[i] << "\"" << endl; -
driver/cfa.cc
r309d814 r4c925cd 10 10 // Created On : Tue Aug 20 13:44:49 2002 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat May 30 18:28:23202013 // Update Count : 43 312 // Last Modified On : Thu Aug 13 17:22:02 2020 13 // Update Count : 435 14 14 // 15 15 … … 180 180 181 181 if ( arg == "-Xlinker" || arg == "-o" ) { 182 args[nargs++] = argv[i]; // pass argumentalong182 args[nargs++] = argv[i]; // pass flag along 183 183 i += 1; 184 184 if ( i == argc ) continue; // next argument available ? 185 185 args[nargs++] = argv[i]; // pass argument along 186 186 if ( arg == "-o" ) o_file = i; // remember file 187 } else if ( strncmp(arg.c_str(), "-XCFA", 5) == 0 ) { 188 if (arg.size() == 5) {187 } else if ( strncmp(arg.c_str(), "-XCFA", 5) == 0 ) { // CFA pass through 188 if ( arg.size() == 5 ) { 189 189 i += 1; 190 if ( i == argc ) continue; 190 if ( i == argc ) continue; // next argument available ? 191 191 Putenv( argv, argv[i] ); 192 193 // CFA specific arguments 194 } 195 else if(arg[5] == ',') { 192 } else if ( arg[5] == ',' ) { // CFA specific arguments 196 193 Putenv( argv, argv[i] + 6 ); 197 198 // CFA specific arguments 199 } 200 else { 194 } else { // CFA specific arguments 201 195 args[nargs++] = argv[i]; 202 } 203 196 } // if 204 197 } else if ( arg == "-CFA" ) { 205 198 CFA_flag = true; // strip the -CFA flag … … 235 228 } else if ( arg == "-v" ) { 236 229 verbose = true; // verbosity required 237 args[nargs++] = argv[i]; // pass argumentalong230 args[nargs++] = argv[i]; // pass flag along 238 231 } else if ( arg == "-g" ) { 239 232 debugging = true; // symbolic debugging required 240 args[nargs++] = argv[i]; // pass argumentalong233 args[nargs++] = argv[i]; // pass flag along 241 234 } else if ( arg == "-save-temps" ) { 242 args[nargs++] = argv[i]; // pass argumentalong235 args[nargs++] = argv[i]; // pass flag along 243 236 Putenv( argv, arg ); // save cfa-cpp output 244 237 } else if ( prefix( arg, "-x" ) ) { // file suffix ? 245 238 string lang; 246 args[nargs++] = argv[i]; // pass argumentalong239 args[nargs++] = argv[i]; // pass flag along 247 240 if ( arg.length() == 2 ) { // separate argument ? 248 241 i += 1; … … 261 254 } else if ( prefix( arg, "-std=" ) || prefix( arg, "--std=" ) ) { 262 255 std_flag = true; // -std=XX provided 263 args[nargs++] = argv[i]; // pass argumentalong256 args[nargs++] = argv[i]; // pass flag along 264 257 } else if ( arg == "-w" ) { 265 args[nargs++] = argv[i]; // pass argumentalong258 args[nargs++] = argv[i]; // pass flag along 266 259 Putenv( argv, arg ); 267 260 } else if ( prefix( arg, "-W" ) ) { // check before next tests 268 261 if ( arg == "-Werror" || arg == "-Wall" ) { 269 args[nargs++] = argv[i]; // pass argumentalong262 args[nargs++] = argv[i]; // pass flag along 270 263 Putenv( argv, argv[i] ); 271 264 } else { … … 281 274 bprefix = arg.substr(2); // strip the -B flag 282 275 } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) { 283 args[nargs++] = argv[i]; // pass argumentalong276 args[nargs++] = argv[i]; // pass flag along 284 277 if ( arg == "-E" || arg == "-M" || arg == "-MM" ) { 285 278 cpp_flag = true; // cpp only 286 279 } // if 287 280 link = false; // no linkage required 281 } else if ( arg == "-D" || arg == "-U" || arg == "-I" || arg == "-MF" || arg == "-MT" || arg == "-MQ" || 282 arg == "-include" || arg == "-imacros" || arg == "-idirafter" || arg == "-iprefix" || 283 arg == "-iwithprefix" || arg == "-iwithprefixbefore" || arg == "-isystem" || arg == "-isysroot" ) { 284 args[nargs++] = argv[i]; // pass flag along 285 i += 1; 286 args[nargs++] = argv[i]; // pass argument along 288 287 } else if ( arg[1] == 'l' ) { 289 288 // if the user specifies a library, load it after user code -
libcfa/src/Makefile.am
r309d814 r4c925cd 44 44 45 45 headers = common.hfa fstream.hfa heap.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa \ 46 time.hfa stdlib.hfa memory.hfaparseargs.hfa \46 time.hfa stdlib.hfa parseargs.hfa \ 47 47 containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa 48 48 -
libcfa/src/concurrency/invoke.h
r309d814 r4c925cd 26 26 #ifndef _INVOKE_H_ 27 27 #define _INVOKE_H_ 28 29 struct __cfaehm_try_resume_node; 30 struct __cfaehm_base_exception_t; 31 struct exception_context_t { 32 struct __cfaehm_try_resume_node * top_resume; 33 struct __cfaehm_base_exception_t * current_exception; 34 }; 28 35 29 36 struct __stack_context_t { … … 51 58 // base of stack 52 59 void * base; 60 61 // Information for exception handling. 62 struct exception_context_t exception_context; 53 63 }; 54 64 … … 84 94 }; 85 95 86 static inline struct __stack_t * __get_stack( struct $coroutine * cor ) { return (struct __stack_t*)(((uintptr_t)cor->stack.storage) & ((uintptr_t)-2)); } 96 static inline struct __stack_t * __get_stack( struct $coroutine * cor ) { 97 return (struct __stack_t*)(((uintptr_t)cor->stack.storage) & ((uintptr_t)-2)); 98 } 87 99 88 100 // struct which calls the monitor is accepting -
libcfa/src/concurrency/kernel/startup.cfa
r309d814 r4c925cd 516 516 ( this.terminated ){ 0 }; 517 517 ( this.runner ){}; 518 init( this, name, _cltr ); 518 519 disable_interrupts(); 520 init( this, name, _cltr ); 521 enable_interrupts( __cfaabi_dbg_ctx ); 519 522 520 523 __cfadbg_print_safe(runtime_core, "Kernel : Starting core %p\n", &this); … … 540 543 free( this.stack ); 541 544 542 deinit( this ); 545 disable_interrupts(); 546 deinit( this ); 547 enable_interrupts( __cfaabi_dbg_ctx ); 543 548 } 544 549 -
libcfa/src/concurrency/ready_queue.cfa
r309d814 r4c925cd 150 150 // queues or removing them. 151 151 uint_fast32_t ready_mutate_lock( void ) with(*__scheduler_lock) { 152 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 153 152 154 // Step 1 : lock global lock 153 155 // It is needed to avoid processors that register mid Critical-Section … … 164 166 } 165 167 168 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 166 169 return s; 167 170 } 168 171 169 172 void ready_mutate_unlock( uint_fast32_t last_s ) with(*__scheduler_lock) { 173 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 174 170 175 // Step 1 : release local locks 171 176 // This must be done while the global lock is held to avoid … … 182 187 /*paranoid*/ assert(true == lock); 183 188 __atomic_store_n(&lock, (bool)false, __ATOMIC_RELEASE); 189 190 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled ); 184 191 } 185 192 … … 419 426 // Actually pop the list 420 427 struct $thread * thrd; 421 bool emptied; 422 [thrd, emptied] = pop(lane); 428 thrd = pop(lane); 423 429 424 430 /* paranoid */ verify(thrd); … … 457 463 if(head(lane)->link.next == thrd) { 458 464 $thread * pthrd; 459 bool emptied; 460 [pthrd, emptied] = pop(lane); 465 pthrd = pop(lane); 461 466 462 467 /* paranoid */ verify( pthrd == thrd ); … … 608 613 while(!is_empty(lanes.data[idx])) { 609 614 struct $thread * thrd; 610 __attribute__((unused)) bool _; 611 [thrd, _] = pop(lanes.data[idx]); 615 thrd = pop(lanes.data[idx]); 612 616 613 617 push(cltr, thrd); -
libcfa/src/concurrency/ready_subqueue.hfa
r309d814 r4c925cd 144 144 // returns popped 145 145 // returns true of lane was empty before push, false otherwise 146 [$thread *, bool]pop(__intrusive_lane_t & this) {146 $thread * pop(__intrusive_lane_t & this) { 147 147 /* paranoid */ verify(this.lock); 148 148 /* paranoid */ verify(this.before.link.ts != 0ul); … … 162 162 head->link.next = next; 163 163 next->link.prev = head; 164 node->link.[next, prev] = 0p; 164 node->link.next = 0p; 165 node->link.prev = 0p; 165 166 166 167 // Update head time stamp … … 180 181 /* paranoid */ verify(tail(this)->link.prev == head(this)); 181 182 /* paranoid */ verify(head(this)->link.next == tail(this)); 182 return [node, true];183 return node; 183 184 } 184 185 else { … … 187 188 /* paranoid */ verify(head(this)->link.next != tail(this)); 188 189 /* paranoid */ verify(this.before.link.ts != 0); 189 return [node, false];190 return node; 190 191 } 191 192 } -
libcfa/src/exception.c
r309d814 r4c925cd 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr May 21 12:18:00 202013 // Update Count : 2 012 // Last Modified On : Wed Aug 12 13:55:00 2020 13 // Update Count : 21 14 14 // 15 15 … … 28 28 #include <unwind.h> 29 29 #include <bits/debug.hfa> 30 #include "concurrency/invoke.h" 30 31 #include "stdhdr/assert.h" 31 32 … … 59 60 60 61 // Temperary global exception context. Does not work with concurency. 61 struct exception_context_t { 62 struct __cfaehm_try_resume_node * top_resume; 63 64 exception_t * current_exception; 65 int current_handler_index; 66 } static shared_stack = {NULL, NULL, 0}; 62 static struct exception_context_t shared_stack = {NULL, NULL}; 67 63 68 64 // Get the current exception context. … … 122 118 123 119 // MEMORY MANAGEMENT ========================================================= 120 121 struct __cfaehm_node { 122 struct _Unwind_Exception unwind_exception; 123 struct __cfaehm_node * next; 124 int handler_index; 125 }; 126 127 #define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node))) 128 #define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1) 129 #define UNWIND_TO_NODE(unwind) ((struct __cfaehm_node *)(unwind)) 130 #define NULL_MAP(map, ptr) ((ptr) ? (map(ptr)) : NULL) 124 131 125 132 // How to clean up an exception in various situations. … … 137 144 } 138 145 139 // We need a piece of storage to raise the exception, for now its a single140 // piece.141 static struct _Unwind_Exception this_exception_storage;142 143 struct __cfaehm_node {144 struct __cfaehm_node * next;145 };146 147 #define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))148 #define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1)149 150 146 // Creates a copy of the indicated exception and sets current_exception to it. 151 147 static void __cfaehm_allocate_exception( exception_t * except ) { … … 161 157 } 162 158 159 // Initialize the node: 160 exception_t * except_store = NODE_TO_EXCEPT(store); 161 store->unwind_exception.exception_class = __cfaehm_exception_class; 162 store->unwind_exception.exception_cleanup = __cfaehm_exception_cleanup; 163 store->handler_index = 0; 164 except->virtual_table->copy( except_store, except ); 165 163 166 // Add the node to the list: 164 store->next = EXCEPT_TO_NODE(context->current_exception); 165 context->current_exception = NODE_TO_EXCEPT(store); 166 167 // Copy the exception to storage. 168 except->virtual_table->copy( context->current_exception, except ); 169 170 // Set up the exception storage. 171 this_exception_storage.exception_class = __cfaehm_exception_class; 172 this_exception_storage.exception_cleanup = __cfaehm_exception_cleanup; 167 store->next = NULL_MAP(EXCEPT_TO_NODE, context->current_exception); 168 context->current_exception = except_store; 173 169 } 174 170 … … 185 181 if ( context->current_exception == except ) { 186 182 node = to_free->next; 187 context->current_exception = (node) ? NODE_TO_EXCEPT(node) : 0;183 context->current_exception = NULL_MAP(NODE_TO_EXCEPT, node); 188 184 } else { 189 185 node = EXCEPT_TO_NODE(context->current_exception); … … 213 209 // Verify actions follow the rules we expect. 214 210 verify((actions & _UA_CLEANUP_PHASE) && (actions & _UA_FORCE_UNWIND)); 215 verify(!(actions & (_UA_SEARCH_PHASE | _UA_HAND ER_FRAME)));211 verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME))); 216 212 217 213 if ( actions & _UA_END_OF_STACK ) { … … 222 218 } 223 219 220 static struct _Unwind_Exception cancel_exception_storage; 221 224 222 // Cancel the current stack, prefroming approprate clean-up and messaging. 225 223 void __cfaehm_cancel_stack( exception_t * exception ) { 226 224 // TODO: Detect current stack and pick a particular stop-function. 227 225 _Unwind_Reason_Code ret; 228 ret = _Unwind_ForcedUnwind( & this_exception_storage, _Stop_Fn, (void*)0x22 );226 ret = _Unwind_ForcedUnwind( &cancel_exception_storage, _Stop_Fn, (void*)0x22 ); 229 227 printf("UNWIND ERROR %d after force unwind\n", ret); 230 228 abort(); … … 247 245 static void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) { 248 246 struct exception_context_t * context = this_exception_context(); 249 struct _Unwind_Exception * storage = &this_exception_storage;250 247 if ( NULL == context->current_exception ) { 251 248 printf("UNWIND ERROR missing exception in begin unwind\n"); 252 249 abort(); 253 250 } 251 struct _Unwind_Exception * storage = 252 &EXCEPT_TO_NODE(context->current_exception)->unwind_exception; 254 253 255 254 // Call stdlibc to raise the exception … … 419 418 _Unwind_Reason_Code ret = (0 == index) 420 419 ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; 421 context->current_handler_index = index;420 UNWIND_TO_NODE(unwind_exception)->handler_index = index; 422 421 423 422 // Based on the return value, check if we matched the exception … … 425 424 __cfadbg_print_safe(exception, " handler found\n"); 426 425 } else { 426 // TODO: Continue the search if there is more in the table. 427 427 __cfadbg_print_safe(exception, " no handler\n"); 428 428 } … … 516 516 // Exception handler 517 517 // Note: Saving the exception context on the stack breaks termination exceptions. 518 catch_block( this_exception_context()->current_handler_index,518 catch_block( EXCEPT_TO_NODE( this_exception_context()->current_exception )->handler_index, 519 519 this_exception_context()->current_exception ); 520 520 } -
libcfa/src/iostream.cfa
r309d814 r4c925cd 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 10 09:32:14202013 // Update Count : 112 612 // Last Modified On : Tue Aug 11 22:16:33 2020 13 // Update Count : 1128 14 14 // 15 15 … … 37 37 38 38 forall( dtype ostype | ostream( ostype ) ) { 39 ostype & ?|?( ostype & os, zero_t ) {40 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );41 fmt( os, "%d", 0n );42 return os;43 } // ?|?44 void ?|?( ostype & os, zero_t z ) {45 (ostype &)(os | z); ends( os );46 } // ?|?47 48 ostype & ?|?( ostype & os, one_t ) {49 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );50 fmt( os, "%d", 1n );51 return os;52 } // ?|?53 void ?|?( ostype & os, one_t o ) {54 (ostype &)(os | o); ends( os );55 } // ?|?56 57 39 ostype & ?|?( ostype & os, bool b ) { 58 40 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); -
libcfa/src/iostream.hfa
r309d814 r4c925cd 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Jul 16 07:43:32202013 // Update Count : 3 4812 // Last Modified On : Tue Aug 11 22:16:14 2020 13 // Update Count : 350 14 14 // 15 15 … … 67 67 68 68 forall( dtype ostype | ostream( ostype ) ) { 69 ostype & ?|?( ostype &, zero_t );70 void ?|?( ostype &, zero_t );71 ostype & ?|?( ostype &, one_t );72 void ?|?( ostype &, one_t );73 74 69 ostype & ?|?( ostype &, bool ); 75 70 void ?|?( ostype &, bool ); -
libcfa/src/stdlib.hfa
r309d814 r4c925cd 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Jul 30 16:14:58202013 // Update Count : 49 012 // Last Modified On : Tue Aug 11 21:11:46 2020 13 // Update Count : 495 14 14 // 15 15 … … 136 136 T * alloc_set( char fill ) { 137 137 return (T *)memset( (T *)alloc(), (int)fill, sizeof(T) ); // initialize with fill value 138 } // alloc 139 140 T * alloc_set( Tfill ) {138 } // alloc_set 139 140 T * alloc_set( const T & fill ) { 141 141 return (T *)memcpy( (T *)alloc(), &fill, sizeof(T) ); // initialize with fill value 142 } // alloc 142 } // alloc_set 143 143 144 144 T * alloc_set( size_t dim, char fill ) { 145 145 return (T *)memset( (T *)alloc( dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value 146 } // alloc 147 148 T * alloc_set( size_t dim, Tfill ) {146 } // alloc_set 147 148 T * alloc_set( size_t dim, const T & fill ) { 149 149 T * r = (T *)alloc( dim ); 150 150 for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value 151 151 return r; 152 } // alloc 152 } // alloc_set 153 153 154 154 T * alloc_set( size_t dim, const T fill[] ) { 155 155 return (T *)memcpy( (T *)alloc( dim ), fill, dim * sizeof(T) ); // initialize with fill value 156 } // alloc 156 } // alloc_set 157 157 158 158 T * alloc_set( T ptr[], size_t dim, char fill ) { // realloc array with fill … … 166 166 } // alloc_set 167 167 168 T * alloc_set( T ptr[], size_t dim, T & fill ) { // realloc array with fill168 T * alloc_set( T ptr[], size_t dim, const T & fill ) { // realloc array with fill 169 169 size_t odim = malloc_size( ptr ) / sizeof(T); // current dimension 170 170 size_t nsize = dim * sizeof(T); // new allocation … … 177 177 } // if 178 178 return nptr; 179 } // alloc_ align_set179 } // alloc_set 180 180 } // distribution 181 181 … … 204 204 T * alloc_align_set( size_t align, char fill ) { 205 205 return (T *)memset( (T *)alloc_align( align ), (int)fill, sizeof(T) ); // initialize with fill value 206 } // alloc_align 207 208 T * alloc_align_set( size_t align, Tfill ) {206 } // alloc_align_set 207 208 T * alloc_align_set( size_t align, const T & fill ) { 209 209 return (T *)memcpy( (T *)alloc_align( align ), &fill, sizeof(T) ); // initialize with fill value 210 } // alloc_align 210 } // alloc_align_set 211 211 212 212 T * alloc_align_set( size_t align, size_t dim, char fill ) { 213 213 return (T *)memset( (T *)alloc_align( align, dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value 214 } // alloc_align 215 216 T * alloc_align_set( size_t align, size_t dim, Tfill ) {214 } // alloc_align_set 215 216 T * alloc_align_set( size_t align, size_t dim, const T & fill ) { 217 217 T * r = (T *)alloc_align( align, dim ); 218 218 for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value 219 219 return r; 220 } // alloc_align 220 } // alloc_align_set 221 221 222 222 T * alloc_align_set( size_t align, size_t dim, const T fill[] ) { 223 223 return (T *)memcpy( (T *)alloc_align( align, dim ), fill, dim * sizeof(T) ); 224 } // alloc_align 224 } // alloc_align_set 225 225 226 226 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ) { … … 234 234 } // alloc_align_set 235 235 236 T * alloc_align_set( T ptr[], size_t align, size_t dim, T & fill ) {236 T * alloc_align_set( T ptr[], size_t align, size_t dim, const T & fill ) { 237 237 size_t odim = malloc_size( ptr ) / sizeof(T); // current dimension 238 238 size_t nsize = dim * sizeof(T); // new allocation -
src/AST/Attribute.hpp
r309d814 r4c925cd 51 51 template<typename node_t> 52 52 friend node_t * mutate(const node_t * node); 53 template<typename node_t> 54 friend node_t * shallowCopy(const node_t * node); 53 55 }; 54 56 -
src/AST/CVQualifiers.hpp
r309d814 r4c925cd 27 27 Restrict = 1 << 1, 28 28 Volatile = 1 << 2, 29 Lvalue = 1 << 3, 30 Mutex = 1 << 4, 31 Atomic = 1 << 5, 32 NumQualifiers = 6 29 Mutex = 1 << 3, 30 Atomic = 1 << 4, 31 NumQualifiers = 5 33 32 }; 34 33 35 34 /// Mask for equivalence-preserving qualfiers 36 enum { EquivQualifiers = ~ (Restrict | Lvalue)};35 enum { EquivQualifiers = ~Restrict }; 37 36 38 37 /// Underlying data for qualifiers … … 44 43 bool is_restrict : 1; 45 44 bool is_volatile : 1; 46 bool is_lvalue : 1;47 45 bool is_mutex : 1; 48 46 bool is_atomic : 1; -
src/AST/Convert.cpp
r309d814 r4c925cd 20 20 21 21 #include "AST/Attribute.hpp" 22 #include "AST/Copy.hpp" 22 23 #include "AST/Decl.hpp" 23 24 #include "AST/Expr.hpp" … … 587 588 assert( tgtResnSlots.empty() ); 588 589 589 if ( srcInferred. mode == ast::Expr::InferUnion::Params ) {590 if ( srcInferred.data.inferParams ) { 590 591 const ast::InferredParams &srcParams = srcInferred.inferParams(); 591 592 for (auto & srcParam : srcParams) { … … 593 594 srcParam.second.decl, 594 595 get<Declaration>().accept1(srcParam.second.declptr), 595 get<Type>().accept1(srcParam.second.actualType) ,596 get<Type>().accept1(srcParam.second.formalType) ,597 get<Expression>().accept1(srcParam.second.expr) 596 get<Type>().accept1(srcParam.second.actualType)->clone(), 597 get<Type>().accept1(srcParam.second.formalType)->clone(), 598 get<Expression>().accept1(srcParam.second.expr)->clone() 598 599 )); 599 600 assert(res.second); 600 601 } 601 } else if ( srcInferred.mode == ast::Expr::InferUnion::Slots ) { 602 } 603 if ( srcInferred.data.resnSlots ) { 602 604 const ast::ResnSlots &srcSlots = srcInferred.resnSlots(); 603 605 for (auto srcSlot : srcSlots) { … … 620 622 621 623 tgt->result = get<Type>().accept1(src->result); 624 // Unconditionally use a clone of the result type. 625 // We know this will leak some objects: much of the immediate conversion result. 626 // In some cases, using the conversion result directly gives unintended object sharing. 627 // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache. 628 // But tgt->result must be fully owned privately by tgt. 629 // Applying these conservative copies here means 630 // - weak references point at the declaration's copy, not these expr.result copies (good) 631 // - we copy more objects than really needed (bad, tolerated) 632 if (tgt->result) { 633 tgt->result = tgt->result->clone(); 634 } 622 635 return visitBaseExpr_skipResultType(src, tgt); 623 636 } … … 979 992 980 993 const ast::Expr * visit( const ast::StmtExpr * node ) override final { 994 auto stmts = node->stmts; 995 // disable sharing between multiple StmtExprs explicitly. 996 if (inCache(stmts)) { 997 stmts = ast::deepCopy(stmts.get()); 998 } 981 999 auto rslt = new StmtExpr( 982 get<CompoundStmt>().accept1( node->stmts)1000 get<CompoundStmt>().accept1(stmts) 983 1001 ); 984 1002 … … 1986 2004 1987 2005 assert( oldInferParams.empty() || oldResnSlots.empty() ); 1988 assert( newInferred.mode == ast::Expr::InferUnion::Empty );2006 // assert( newInferred.mode == ast::Expr::InferUnion::Empty ); 1989 2007 1990 2008 if ( !oldInferParams.empty() ) { … … 2117 2135 old->location, 2118 2136 GET_ACCEPT_1(member, DeclWithType), 2119 GET_ACCEPT_1(aggregate, Expr) 2137 GET_ACCEPT_1(aggregate, Expr), 2138 ast::MemberExpr::NoOpConstructionChosen 2120 2139 ) 2121 2140 ); -
src/AST/Decl.cpp
r309d814 r4c925cd 50 50 51 51 const Type * FunctionDecl::get_type() const { return type.get(); } 52 void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); } 52 void FunctionDecl::set_type( const Type * t ) { 53 type = strict_dynamic_cast< const FunctionType * >( t ); 54 } 53 55 54 56 // --- TypeDecl -
src/AST/Decl.hpp
r309d814 r4c925cd 33 33 34 34 // Must be included in *all* AST classes; should be #undef'd at the end of the file 35 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 35 #define MUTATE_FRIEND \ 36 template<typename node_t> friend node_t * mutate(const node_t * node); \ 37 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 36 38 37 39 namespace ast { … … 88 90 virtual const Type * get_type() const = 0; 89 91 /// Set type of this declaration. May be verified by subclass 90 virtual void set_type( Type *) = 0;92 virtual void set_type( const Type * ) = 0; 91 93 92 94 const DeclWithType * accept( Visitor & v ) const override = 0; … … 111 113 112 114 const Type* get_type() const override { return type; } 113 void set_type( Type * ty ) override { type = ty; }115 void set_type( const Type * ty ) override { type = ty; } 114 116 115 117 const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); } … … 133 135 134 136 const Type * get_type() const override; 135 void set_type( Type * t) override;137 void set_type( const Type * t ) override; 136 138 137 139 bool has_body() const { return stmts; } … … 150 152 std::vector<ptr<DeclWithType>> assertions; 151 153 152 NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 153 Type* b, Linkage::Spec spec = Linkage::Cforall ) 154 NamedTypeDecl( 155 const CodeLocation & loc, const std::string & name, Storage::Classes storage, 156 const Type * b, Linkage::Spec spec = Linkage::Cforall ) 154 157 : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {} 155 158 … … 186 189 }; 187 190 188 TypeDecl( const CodeLocation & loc, const std::string & name, Storage::Classes storage, Type * b, 189 Kind k, bool s, Type * i = nullptr ) 190 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ), 191 init( i ) {} 191 TypeDecl( 192 const CodeLocation & loc, const std::string & name, Storage::Classes storage, 193 const Type * b, TypeDecl::Kind k, bool s, const Type * i = nullptr ) 194 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeDecl::Ttype || s ), 195 init( i ) {} 192 196 193 197 const char * typeString() const override; -
src/AST/Expr.cpp
r309d814 r4c925cd 20 20 #include <vector> 21 21 22 #include "Copy.hpp" // for shallowCopy 23 #include "Eval.hpp" // for call 22 24 #include "GenericSubstitution.hpp" 25 #include "LinkageSpec.hpp" 23 26 #include "Stmt.hpp" 24 27 #include "Type.hpp" … … 27 30 #include "Common/SemanticError.h" 28 31 #include "GenPoly/Lvalue.h" // for referencesPermissable 29 #include "InitTweak/InitTweak.h" // for get PointerBase32 #include "InitTweak/InitTweak.h" // for getFunction, getPointerBase 30 33 #include "ResolvExpr/typeops.h" // for extractResultType 31 34 #include "Tuples/Tuples.h" // for makeTupleType 32 35 33 36 namespace ast { 37 38 namespace { 39 std::set<std::string> const lvalueFunctionNames = {"*?", "?[?]"}; 40 } 41 42 // --- Expr 43 bool Expr::get_lvalue() const { 44 return false; 45 } 34 46 35 47 // --- ApplicationExpr … … 46 58 } 47 59 60 bool ApplicationExpr::get_lvalue() const { 61 if ( const DeclWithType * func = InitTweak::getFunction( this ) ) { 62 return func->linkage == Linkage::Intrinsic && lvalueFunctionNames.count( func->name ); 63 } 64 return false; 65 } 66 48 67 // --- UntypedExpr 49 68 … … 51 70 assert( arg ); 52 71 53 UntypedExpr * ret = new UntypedExpr{ 54 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } } 55 }; 72 UntypedExpr * ret = call( loc, "*?", arg ); 56 73 if ( const Type * ty = arg->result ) { 57 74 const Type * base = InitTweak::getPointerBase( ty ); … … 65 82 // base type 66 83 ret->result = base; 67 add_qualifiers( ret->result, CV::Lvalue );68 84 } 69 85 } 70 86 return ret; 87 } 88 89 bool UntypedExpr::get_lvalue() const { 90 std::string fname = InitTweak::getFunctionName( this ); 91 return lvalueFunctionNames.count( fname ); 71 92 } 72 93 … … 74 95 assert( lhs && rhs ); 75 96 76 UntypedExpr * ret = new UntypedExpr{ 77 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } } 78 }; 97 UntypedExpr * ret = call( loc, "?=?", lhs, rhs ); 79 98 if ( lhs->result && rhs->result ) { 80 99 // if both expressions are typed, assumes that this assignment is a C bitwise assignment, … … 108 127 AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) { 109 128 if ( arg->result ) { 110 if ( arg-> result->is_lvalue() ) {129 if ( arg->get_lvalue() ) { 111 130 // lvalue, retains all levels of reference, and gains a pointer inside the references 112 131 Type * res = addrType( arg->result ); 113 res->set_lvalue( false ); // result of & is never an lvalue114 132 result = res; 115 133 } else { … … 118 136 dynamic_cast< const ReferenceType * >( arg->result.get() ) ) { 119 137 Type * res = addrType( refType->base ); 120 res->set_lvalue( false ); // result of & is never an lvalue121 138 result = res; 122 139 } else { … … 139 156 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {} 140 157 158 bool CastExpr::get_lvalue() const { 159 // This is actually wrong by C, but it works with our current set-up. 160 return arg->get_lvalue(); 161 } 162 141 163 // --- KeywordCastExpr 142 164 143 165 const char * KeywordCastExpr::targetString() const { 144 166 return AggregateDecl::aggrString( target ); 167 } 168 169 // --- UntypedMemberExpr 170 171 bool UntypedMemberExpr::get_lvalue() const { 172 return aggregate->get_lvalue(); 145 173 } 146 174 … … 153 181 assert( aggregate->result ); 154 182 155 // take ownership of member type 156 result = mem->get_type(); 183 // Deep copy on result type avoids mutation on transitively multiply referenced object. 184 // 185 // Example, adapted from parts of builtins and bootloader: 186 // 187 // forall(dtype T) 188 // struct __Destructor { 189 // T * object; 190 // void (*dtor)(T *); 191 // }; 192 // 193 // forall(dtype S) 194 // void foo(__Destructor(S) &d) { 195 // if (d.dtor) { // here 196 // } 197 // } 198 // 199 // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve. Let d be the 200 // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level 201 // declaration of __Destructor. Consider the types e.result and d.type. In the old AST, one 202 // is a clone of the other. Ordinary new-AST use would set them up as a multiply-referenced 203 // object. 204 // 205 // e.result: PointerType 206 // .base: FunctionType 207 // .params.front(): ObjectDecl, the anonymous parameter of type T* 208 // .type: PointerType 209 // .base: TypeInstType 210 // let x = that 211 // let y = similar, except start from d.type 212 // 213 // Consider two code lines down, genericSubstitution(...).apply(result). 214 // 215 // Applying this chosen-candidate's type substitution means modifying x, substituting 216 // S for T. This mutation should affect x and not y. 217 218 result = deepCopy(mem->get_type()); 219 157 220 // substitute aggregate generic parameters into member type 158 221 genericSubstitution( aggregate->result ).apply( result ); 159 // ensure lvalue and appropriate restrictions from aggregate type 160 add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue ); 222 // ensure appropriate restrictions from aggregate type 223 add_qualifiers( result, aggregate->result->qualifiers ); 224 } 225 226 MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg, 227 MemberExpr::NoOpConstruction overloadSelector ) 228 : Expr( loc ), member( mem ), aggregate( agg ) { 229 assert( member ); 230 assert( aggregate ); 231 assert( aggregate->result ); 232 (void) overloadSelector; 233 } 234 235 bool MemberExpr::get_lvalue() const { 236 // This is actually wrong by C, but it works with our current set-up. 237 return true; 161 238 } 162 239 … … 170 247 assert( var ); 171 248 assert( var->get_type() ); 172 result = var->get_type(); 173 add_qualifiers( result, CV::Lvalue ); 249 result = shallowCopy( var->get_type() ); 250 } 251 252 bool VariableExpr::get_lvalue() const { 253 // It isn't always an lvalue, but it is never an rvalue. 254 return true; 174 255 } 175 256 … … 258 339 : Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {} 259 340 341 // --- CommaExpr 342 bool CommaExpr::get_lvalue() const { 343 // This is wrong by C, but the current implementation uses it. 344 // (ex: Specialize, Lvalue and Box) 345 return arg2->get_lvalue(); 346 } 347 260 348 // --- ConstructorExpr 261 349 … … 276 364 assert( t && i ); 277 365 result = t; 278 add_qualifiers( result, CV::Lvalue ); 366 } 367 368 bool CompoundLiteralExpr::get_lvalue() const { 369 return true; 279 370 } 280 371 … … 293 384 // like MemberExpr, TupleIndexExpr is always an lvalue 294 385 result = type->types[ index ]; 295 add_qualifiers( result, CV::Lvalue ); 386 } 387 388 bool TupleIndexExpr::get_lvalue() const { 389 return tuple->get_lvalue(); 296 390 } 297 391 -
src/AST/Expr.hpp
r309d814 r4c925cd 31 31 32 32 // Must be included in *all* AST classes; should be #undef'd at the end of the file 33 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 33 #define MUTATE_FRIEND \ 34 template<typename node_t> friend node_t * mutate(const node_t * node); \ 35 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 36 34 37 35 38 class ConverterOldToNew; … … 42 45 struct ParamEntry { 43 46 UniqueId decl; 44 ptr<Decl> declptr;47 readonly<Decl> declptr; 45 48 ptr<Type> actualType; 46 49 ptr<Type> formalType; … … 62 65 class Expr : public ParseNode { 63 66 public: 64 /// Saves space (~16 bytes) by combining ResnSlots and InferredParams 67 /* 68 * NOTE: the union approach is incorrect until the case of 69 * partial resolution in InferMatcher is eliminated. 70 * it is reverted to allow unresolved and resolved parameters 71 * to coexist in an expression node. 72 */ 65 73 struct InferUnion { 74 // mode is now unused 66 75 enum { Empty, Slots, Params } mode; 67 union data_t { 68 char def; 69 ResnSlots resnSlots; 70 InferredParams inferParams; 71 72 data_t() : def('\0') {} 73 ~data_t() {} 76 struct data_t { 77 // char def; 78 ResnSlots * resnSlots; 79 InferredParams * inferParams; 80 81 data_t(): resnSlots(nullptr), inferParams(nullptr) {} 82 data_t(const data_t &other) = delete; 83 ~data_t() { 84 delete resnSlots; 85 delete inferParams; 86 } 74 87 } data; 75 88 76 89 /// initializes from other InferUnion 77 90 void init_from( const InferUnion& o ) { 78 switch ( o.mode ) { 79 case Empty: return; 80 case Slots: new(&data.resnSlots) ResnSlots{ o.data.resnSlots }; return; 81 case Params: new(&data.inferParams) InferredParams{ o.data.inferParams }; return; 91 if (o.data.resnSlots) { 92 data.resnSlots = new ResnSlots(*o.data.resnSlots); 93 } 94 if (o.data.inferParams) { 95 data.inferParams = new InferredParams(*o.data.inferParams); 82 96 } 83 97 } … … 85 99 /// initializes from other InferUnion (move semantics) 86 100 void init_from( InferUnion&& o ) { 87 switch ( o.mode ) { 88 case Empty: return; 89 case Slots: new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return; 90 case Params: 91 new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return; 92 } 93 } 94 95 /// clears variant fields 96 void reset() { 97 switch( mode ) { 98 case Empty: return; 99 case Slots: data.resnSlots.~ResnSlots(); return; 100 case Params: data.inferParams.~InferredParams(); return; 101 } 101 data.resnSlots = o.data.resnSlots; 102 data.inferParams = o.data.inferParams; 103 o.data.resnSlots = nullptr; 104 o.data.inferParams = nullptr; 102 105 } 103 106 … … 107 110 InferUnion& operator= ( const InferUnion& ) = delete; 108 111 InferUnion& operator= ( InferUnion&& ) = delete; 109 ~InferUnion() { reset(); } 112 113 bool hasSlots() const { return data.resnSlots; } 110 114 111 115 ResnSlots& resnSlots() { 112 switch (mode) { 113 case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; // fallthrough 114 case Slots: return data.resnSlots; 115 case Params: assertf(false, "Cannot return to resnSlots from Params"); abort(); 116 if (!data.resnSlots) { 117 data.resnSlots = new ResnSlots(); 116 118 } 117 assertf(false, "unreachable");119 return *data.resnSlots; 118 120 } 119 121 120 122 const ResnSlots& resnSlots() const { 121 if ( mode ==Slots) {122 return data.resnSlots;123 if (data.resnSlots) { 124 return *data.resnSlots; 123 125 } 124 126 assertf(false, "Mode was not already resnSlots"); … … 127 129 128 130 InferredParams& inferParams() { 129 switch (mode) { 130 case Slots: data.resnSlots.~ResnSlots(); // fallthrough 131 case Empty: new(&data.inferParams) InferredParams{}; mode = Params; // fallthrough 132 case Params: return data.inferParams; 131 if (!data.inferParams) { 132 data.inferParams = new InferredParams(); 133 133 } 134 assertf(false, "unreachable");134 return *data.inferParams; 135 135 } 136 136 137 137 const InferredParams& inferParams() const { 138 if ( mode ==Params) {139 return data.inferParams;138 if (data.inferParams) { 139 return *data.inferParams; 140 140 } 141 141 assertf(false, "Mode was not already Params"); … … 143 143 } 144 144 145 void set_inferParams( InferredParams && ps ) { 146 switch(mode) { 147 case Slots: 148 data.resnSlots.~ResnSlots(); 149 // fallthrough 150 case Empty: 151 new(&data.inferParams) InferredParams{ std::move( ps ) }; 152 mode = Params; 153 break; 154 case Params: 155 data.inferParams = std::move( ps ); 156 break; 157 } 145 void set_inferParams( InferredParams * ps ) { 146 delete data.resnSlots; 147 data.resnSlots = nullptr; 148 delete data.inferParams; 149 data.inferParams = ps; 158 150 } 159 151 … … 161 153 /// and the other is in `Params`. 162 154 void splice( InferUnion && o ) { 163 if ( o.mode == Empty ) return; 164 if ( mode == Empty ) { init_from( o ); return; } 165 assert( mode == o.mode && "attempt to splice incompatible InferUnion" ); 166 167 if ( mode == Slots ){ 168 data.resnSlots.insert( 169 data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() ); 170 } else if ( mode == Params ) { 171 for ( const auto & p : o.data.inferParams ) { 172 data.inferParams[p.first] = std::move(p.second); 155 if (o.data.resnSlots) { 156 if (data.resnSlots) { 157 data.resnSlots->insert( 158 data.resnSlots->end(), o.data.resnSlots->begin(), o.data.resnSlots->end() ); 159 delete o.data.resnSlots; 173 160 } 174 } else assertf(false, "invalid mode"); 161 else { 162 data.resnSlots = o.data.resnSlots; 163 } 164 o.data.resnSlots = nullptr; 165 } 166 167 if (o.data.inferParams) { 168 if (data.inferParams) { 169 for ( const auto & p : *o.data.inferParams ) { 170 (*data.inferParams)[p.first] = std::move(p.second); 171 } 172 delete o.data.inferParams; 173 } 174 else { 175 data.inferParams = o.data.inferParams; 176 } 177 o.data.inferParams = nullptr; 178 } 175 179 } 176 180 }; … … 185 189 186 190 Expr * set_extension( bool ex ) { extension = ex; return this; } 191 virtual bool get_lvalue() const; 187 192 188 193 virtual const Expr * accept( Visitor & v ) const override = 0; … … 201 206 ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ); 202 207 208 bool get_lvalue() const final; 209 203 210 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 204 211 private: … … 215 222 UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ) 216 223 : Expr( loc ), func( f ), args( std::move(as) ) {} 224 225 bool get_lvalue() const final; 217 226 218 227 /// Creates a new dereference expression … … 291 300 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {} 292 301 302 bool get_lvalue() const final; 303 293 304 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 294 305 private: … … 338 349 : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); } 339 350 351 bool get_lvalue() const final; 352 340 353 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 341 354 private: … … 352 365 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg ); 353 366 367 bool get_lvalue() const final; 368 354 369 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 355 370 private: 356 371 MemberExpr * clone() const override { return new MemberExpr{ *this }; } 357 372 MUTATE_FRIEND 373 374 // Custructor overload meant only for AST conversion 375 enum NoOpConstruction { NoOpConstructionChosen }; 376 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg, 377 NoOpConstruction overloadSelector ); 378 friend class ::ConverterOldToNew; 379 friend class ::ConverterNewToOld; 358 380 }; 359 381 … … 365 387 VariableExpr( const CodeLocation & loc ); 366 388 VariableExpr( const CodeLocation & loc, const DeclWithType * v ); 389 390 bool get_lvalue() const final; 367 391 368 392 /// generates a function pointer for a given function … … 532 556 533 557 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 534 : Expr( loc ), arg1( a1 ), arg2( a2 ) {} 558 : Expr( loc ), arg1( a1 ), arg2( a2 ) { 559 this->result = a2->result; 560 } 561 562 bool get_lvalue() const final; 535 563 536 564 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 605 633 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i ); 606 634 635 bool get_lvalue() const final; 636 607 637 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 608 638 private: … … 660 690 661 691 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i ); 692 693 bool get_lvalue() const final; 662 694 663 695 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } -
src/AST/Fwd.hpp
r309d814 r4c925cd 10 10 // Created On : Wed May 8 16:05:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jun 24 09:48:00 201913 // Update Count : 112 // Last Modified On : Thr Jul 23 14:15:00 2020 13 // Update Count : 2 14 14 // 15 15 … … 108 108 class FunctionType; 109 109 class ReferenceToType; 110 class StructInstType; 111 class UnionInstType; 112 class EnumInstType; 110 template<typename decl_t> class SueInstType; 111 using StructInstType = SueInstType<StructDecl>; 112 using UnionInstType = SueInstType<UnionDecl>; 113 using EnumInstType = SueInstType<EnumDecl>; 113 114 class TraitInstType; 114 115 class TypeInstType; -
src/AST/GenericSubstitution.cpp
r309d814 r4c925cd 62 62 Pass<GenericSubstitutionBuilder> builder; 63 63 maybe_accept( ty, builder ); 64 return std::move(builder. pass.sub);64 return std::move(builder.core.sub); 65 65 } 66 66 -
src/AST/Init.hpp
r309d814 r4c925cd 25 25 26 26 // Must be included in *all* AST classes; should be #undef'd at the end of the file 27 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 27 #define MUTATE_FRIEND \ 28 template<typename node_t> friend node_t * mutate(const node_t * node); \ 29 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 28 30 29 31 namespace ast { -
src/AST/Node.cpp
r309d814 r4c925cd 9 9 // Author : Thierry Delisle 10 10 // Created On : Thu May 16 14:16:00 2019 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jun 5 10:21:00 2020 13 // Update Count : 1 14 14 // 15 15 … … 17 17 #include "Fwd.hpp" 18 18 19 #include <csignal> // MEMORY DEBUG -- for raise 19 20 #include <iostream> 20 21 … … 29 30 #include "Print.hpp" 30 31 31 template< typename node_t, enum ast::Node::ref_type ref_t > 32 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); } 33 34 template< typename node_t, enum ast::Node::ref_type ref_t > 35 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); } 36 37 template< typename node_t, enum ast::Node::ref_type ref_t > 38 void ast::ptr_base<node_t, ref_t>::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); } 32 /// MEMORY DEBUG -- allows breaking on ref-count changes of dynamically chosen object. 33 /// Process to use in GDB: 34 /// break ast::Node::_trap() 35 /// run 36 /// set variable MEM_TRAP_OBJ = <target> 37 /// disable <first breakpoint> 38 /// continue 39 void * MEM_TRAP_OBJ = nullptr; 40 41 void _trap( const void * node ) { 42 if ( node == MEM_TRAP_OBJ ) std::raise(SIGTRAP); 43 } 44 45 [[noreturn]] static inline void strict_fail(const ast::Node * node) { 46 assertf(node, "strict_as had nullptr input."); 47 const ast::ParseNode * parse = dynamic_cast<const ast::ParseNode *>( node ); 48 if ( nullptr == parse ) { 49 assertf(nullptr, "%s (no location)", toString(node).c_str()); 50 } else if ( parse->location.isUnset() ) { 51 assertf(nullptr, "%s (unset location)", toString(node).c_str()); 52 } else { 53 assertf(nullptr, "%s (at %s:%d)", toString(node).c_str(), 54 parse->location.filename.c_str(), parse->location.first_line); 55 } 56 } 57 58 template< typename node_t, enum ast::Node::ref_type ref_t > 59 void ast::ptr_base<node_t, ref_t>::_strict_fail() const { 60 strict_fail(node); 61 } 62 63 template< typename node_t, enum ast::Node::ref_type ref_t > 64 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { 65 node->increment(ref_t); 66 _trap( node ); 67 } 68 69 template< typename node_t, enum ast::Node::ref_type ref_t > 70 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node, bool do_delete ) { 71 _trap( node ); 72 node->decrement( ref_t, do_delete ); 73 } 74 75 template< typename node_t, enum ast::Node::ref_type ref_t > 76 void ast::ptr_base<node_t, ref_t>::_check() const { 77 // if(node) assert(node->was_ever_strong == false || node->strong_count > 0); 78 } 39 79 40 80 template< typename node_t, enum ast::Node::ref_type ref_t > -
src/AST/Node.hpp
r309d814 r4c925cd 10 10 // Created On : Wed May 8 10:27:04 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jun 3 13:26:00 201913 // Update Count : 512 // Last Modified On : Fri Jun 5 9:47:00 2020 13 // Update Count : 6 14 14 // 15 15 … … 38 38 Node& operator= (const Node&) = delete; 39 39 Node& operator= (Node&&) = delete; 40 virtual ~Node() = default;40 virtual ~Node() {} 41 41 42 42 virtual const Node * accept( Visitor & v ) const = 0; … … 57 57 template<typename node_t> 58 58 friend node_t * mutate(const node_t * node); 59 template<typename node_t> 60 friend node_t * shallowCopy(const node_t * node); 59 61 60 62 mutable size_t strong_count = 0; … … 69 71 } 70 72 71 void decrement(ast::Node::ref_type ref ) const {73 void decrement(ast::Node::ref_type ref, bool do_delete = true) const { 72 74 switch (ref) { 73 75 case ref_type::strong: strong_count--; break; … … 75 77 } 76 78 77 if( !strong_count && !weak_count) {79 if( do_delete && !strong_count && !weak_count) { 78 80 delete this; 79 81 } … … 94 96 assertf( 95 97 node->weak_count == 0, 96 "Error: mutating node with weak references to it will invalid edsome references"98 "Error: mutating node with weak references to it will invalidate some references" 97 99 ); 98 100 return node->clone(); … … 104 106 // skip mutate if equivalent 105 107 if ( node->*field == val ) return node; 106 108 107 109 // mutate and return 108 110 node_t * ret = mutate( node ); … … 123 125 (ret->*field)[i] = std::forward< field_t >( val ); 124 126 return ret; 127 } 128 129 /// Mutate an entire indexed collection by cloning to accepted value 130 template<typename node_t, typename parent_t, typename coll_t> 131 const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) { 132 for ( unsigned i = 0; i < (node->*field).size(); ++i ) { 133 node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) ); 134 } 135 return node; 125 136 } 126 137 … … 219 230 operator const node_t * () const { _check(); return node; } 220 231 232 const node_t * release() { 233 const node_t * ret = node; 234 if ( node ) { 235 _dec(node, false); 236 node = nullptr; 237 } 238 return ret; 239 } 240 221 241 /// wrapper for convenient access to dynamic_cast 222 242 template<typename o_node_t> 223 243 const o_node_t * as() const { _check(); return dynamic_cast<const o_node_t *>(node); } 224 244 225 /// wrapper for convenient access to strict_dynamic_cast245 /// Wrapper that makes sure dynamic_cast returns non-null. 226 246 template<typename o_node_t> 227 const o_node_t * strict_as() const { _check(); return strict_dynamic_cast<const o_node_t *>(node); } 247 const o_node_t * strict_as() const { 248 if (const o_node_t * ret = as<o_node_t>()) return ret; 249 _strict_fail(); 250 } 251 252 /// Wrapper that makes sure dynamic_cast does not fail. 253 template<typename o_node_t, decltype(nullptr) null> 254 const o_node_t * strict_as() const { return node ? strict_as<o_node_t>() : nullptr; } 228 255 229 256 /// Returns a mutable version of the pointer in this node. … … 244 271 245 272 void _inc( const node_t * other ); 246 void _dec( const node_t * other );273 void _dec( const node_t * other, bool do_delete = true ); 247 274 void _check() const; 275 void _strict_fail() const __attribute__((noreturn)); 248 276 249 277 const node_t * node; -
src/AST/Pass.hpp
r309d814 r4c925cd 8 8 // 9 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15: :37::05 201910 // Created On : Thu May 09 15:37:05 2019 11 11 // Last Modified By : 12 12 // Last Modified On : … … 35 35 #include "AST/SymbolTable.hpp" 36 36 37 #include "AST/ForallSubstitutionTable.hpp" 38 37 39 // Private prelude header, needed for some of the magic tricks this class pulls off 38 40 #include "AST/Pass.proto.hpp" … … 46 48 // 47 49 // Several additional features are available through inheritance 48 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the 49 // current expression 50 // | WithStmtsToAdd - provides the ability to insert statements before or after the current 51 // statement by adding new statements into stmtsToAddBefore or 52 // stmtsToAddAfter respectively. 53 // | WithDeclsToAdd - provides the ability to insert declarations before or after the current 54 // declarations by adding new DeclStmt into declsToAddBefore or 55 // declsToAddAfter respectively. 56 // | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children 57 // to false in pre{visit,visit} to skip visiting children 58 // | WithGuards - provides the ability to save/restore data like a LIFO stack; to save, 59 // call GuardValue with the variable to save, the variable will 60 // automatically be restored to its previous value after the corresponding 61 // postvisit/postmutate teminates. 62 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 63 // | WithSymbolTable - provides symbol table functionality 50 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the 51 // current expression 52 // | WithStmtsToAdd - provides the ability to insert statements before or after the current 53 // statement by adding new statements into stmtsToAddBefore or 54 // stmtsToAddAfter respectively. 55 // | WithDeclsToAdd - provides the ability to insert declarations before or after the 56 // current declarations by adding new DeclStmt into declsToAddBefore or 57 // declsToAddAfter respectively. 58 // | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children 59 // to false in pre{visit,visit} to skip visiting children 60 // | WithGuards - provides the ability to save/restore data like a LIFO stack; to save, 61 // call GuardValue with the variable to save, the variable will 62 // automatically be restored to its previous value after the 63 // corresponding postvisit/postmutate teminates. 64 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 65 // | WithSymbolTable - provides symbol table functionality 66 // | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation 64 67 //------------------------------------------------------------------------------------------------- 65 template< typename pass_t >68 template< typename core_t > 66 69 class Pass final : public ast::Visitor { 67 70 public: 71 using core_type = core_t; 72 using type = Pass<core_t>; 73 68 74 /// Forward any arguments to the pass constructor 69 75 /// Propagate 'this' if necessary 70 76 template< typename... Args > 71 77 Pass( Args &&... args) 72 : pass( std::forward<Args>( args )... )78 : core( std::forward<Args>( args )... ) 73 79 { 74 80 // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor 75 typedef Pass<pass_t> this_t; 76 this_t * const * visitor = __pass::visitor(pass, 0); 81 type * const * visitor = __pass::visitor(core, 0); 77 82 if(visitor) { 78 *const_cast<t his_t**>( visitor ) = this;83 *const_cast<type **>( visitor ) = this; 79 84 } 80 85 } … … 82 87 virtual ~Pass() = default; 83 88 89 /// Construct and run a pass on a translation unit. 90 template< typename... Args > 91 static void run( std::list< ptr<Decl> > & decls, Args &&... args ) { 92 Pass<core_t> visitor( std::forward<Args>( args )... ); 93 accept_all( decls, visitor ); 94 } 95 96 template< typename... Args > 97 static void run( std::list< ptr<Decl> > & decls ) { 98 Pass<core_t> visitor; 99 accept_all( decls, visitor ); 100 } 101 84 102 /// Storage for the actual pass 85 pass_t pass;103 core_t core; 86 104 87 105 /// Visit function declarations … … 179 197 const ast::TypeSubstitution * visit( const ast::TypeSubstitution * ) override final; 180 198 181 template<typename pass_type>182 friend void accept_all( std::list< ptr<Decl> > & decls, Pass< pass_type>& visitor );199 template<typename core_type> 200 friend void accept_all( std::list< ptr<Decl> > & decls, Pass<core_type>& visitor ); 183 201 private: 184 202 185 bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children( pass, 0); return ptr ? *ptr : true; }203 bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(core, 0); return ptr ? *ptr : true; } 186 204 187 205 private: … … 202 220 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 203 221 222 /// Mutate forall-list, accounting for presence of type substitution map 223 template<typename node_t> 224 void mutate_forall( const node_t *& ); 225 204 226 public: 205 227 /// Logic to call the accept and mutate the parent if needed, delegates call to accept … … 210 232 /// Internal RAII guard for symbol table features 211 233 struct guard_symtab { 212 guard_symtab( Pass< pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }213 ~guard_symtab() { __pass::symtab::leave(pass , 0); }214 Pass< pass_t> & pass;234 guard_symtab( Pass<core_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.core, 0); } 235 ~guard_symtab() { __pass::symtab::leave(pass.core, 0); } 236 Pass<core_t> & pass; 215 237 }; 216 238 217 239 /// Internal RAII guard for scope features 218 240 struct guard_scope { 219 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); } 220 ~guard_scope() { __pass::scope::leave(pass, 0); } 221 Pass<pass_t> & pass; 241 guard_scope( Pass<core_t> & pass ): pass( pass ) { __pass::scope::enter(pass.core, 0); } 242 ~guard_scope() { __pass::scope::leave(pass.core, 0); } 243 Pass<core_t> & pass; 244 }; 245 246 /// Internal RAII guard for forall substitutions 247 struct guard_forall_subs { 248 guard_forall_subs( Pass<core_t> & pass, const ParameterizedType * type ) 249 : pass( pass ), type( type ) { __pass::forall::enter(pass.core, 0, type ); } 250 ~guard_forall_subs() { __pass::forall::leave(pass.core, 0, type ); } 251 Pass<core_t> & pass; 252 const ParameterizedType * type; 222 253 }; 223 254 … … 227 258 228 259 /// Apply a pass to an entire translation unit 229 template<typename pass_t>230 void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass< pass_t> & visitor );260 template<typename core_t> 261 void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<core_t> & visitor ); 231 262 232 263 //------------------------------------------------------------------------------------------------- … … 268 299 }; 269 300 270 template< typename pass_t>271 friend auto __pass::at_cleanup( pass_t & pass, int ) -> decltype( &pass.at_cleanup );301 template< typename core_t> 302 friend auto __pass::at_cleanup( core_t & core, int ) -> decltype( &core.at_cleanup ); 272 303 public: 273 304 … … 305 336 306 337 /// Used to get a pointer to the pass with its wrapped type 307 template<typename pass_t>338 template<typename core_t> 308 339 struct WithVisitorRef { 309 Pass< pass_t> * const visitor = nullptr;340 Pass<core_t> * const visitor = nullptr; 310 341 }; 311 342 … … 314 345 SymbolTable symtab; 315 346 }; 347 348 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl 349 struct WithForallSubstitutor { 350 ForallSubstitutionTable subs; 351 }; 352 316 353 } 317 354 … … 321 358 extern struct PassVisitorStats { 322 359 size_t depth = 0; 323 Stats::Counters::MaxCounter<double> * max = nullptr;324 Stats::Counters::AverageCounter<double> * avg = nullptr;360 Stats::Counters::MaxCounter<double> * max; 361 Stats::Counters::AverageCounter<double> * avg; 325 362 } pass_visitor_stats; 326 363 } -
src/AST/Pass.impl.hpp
r309d814 r4c925cd 25 25 using namespace ast; \ 26 26 /* back-up the visit children */ \ 27 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children( pass, 0) ); \27 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(core, 0) ); \ 28 28 /* setup the scope for passes that want to run code at exit */ \ 29 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup (pass, 0) ); \ 29 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup (core, 0) ); \ 30 /* begin tracing memory allocation if requested by this pass */ \ 31 __pass::beginTrace( core, 0 ); \ 30 32 /* call the implementation of the previsit of this pass */ \ 31 __pass::previsit( pass, node, 0 );33 __pass::previsit( core, node, 0 ); 32 34 33 35 #define VISIT( code... ) \ … … 40 42 #define VISIT_END( type, node ) \ 41 43 /* call the implementation of the postvisit of this pass */ \ 42 auto __return = __pass::postvisit( pass, node, 0 ); \44 auto __return = __pass::postvisit( core, node, 0 ); \ 43 45 assertf(__return, "post visit should never return null"); \ 46 /* end tracing memory allocation if requested by this pass */ \ 47 __pass::endTrace( core, 0 ); \ 44 48 return __return; 45 49 … … 119 123 } 120 124 121 template< typename pass_t >125 template< typename core_t > 122 126 template< typename node_t > 123 auto ast::Pass< pass_t >::call_accept( const node_t * node )127 auto ast::Pass< core_t >::call_accept( const node_t * node ) 124 128 -> typename std::enable_if< 125 129 !std::is_base_of<ast::Expr, node_t>::value && … … 127 131 , decltype( node->accept(*this) ) 128 132 >::type 129 130 133 { 131 134 __pedantic_pass_assert( __visit_children() ); 132 __pedantic_pass_assert( expr);135 __pedantic_pass_assert( node ); 133 136 134 137 static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR"); … … 138 141 } 139 142 140 template< typename pass_t >141 const ast::Expr * ast::Pass< pass_t >::call_accept( const ast::Expr * expr ) {143 template< typename core_t > 144 const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) { 142 145 __pedantic_pass_assert( __visit_children() ); 143 146 __pedantic_pass_assert( expr ); 144 147 145 const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0);148 const ast::TypeSubstitution ** env_ptr = __pass::env( core, 0); 146 149 if ( env_ptr && expr->env ) { 147 150 *env_ptr = expr->env; … … 151 154 } 152 155 153 template< typename pass_t >154 const ast::Stmt * ast::Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {156 template< typename core_t > 157 const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) { 155 158 __pedantic_pass_assert( __visit_children() ); 156 159 __pedantic_pass_assert( stmt ); … … 160 163 161 164 // get the stmts/decls that will need to be spliced in 162 auto stmts_before = __pass::stmtsToAddBefore( pass, 0);163 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0);164 auto decls_before = __pass::declsToAddBefore( pass, 0);165 auto decls_after = __pass::declsToAddAfter ( pass, 0);165 auto stmts_before = __pass::stmtsToAddBefore( core, 0); 166 auto stmts_after = __pass::stmtsToAddAfter ( core, 0); 167 auto decls_before = __pass::declsToAddBefore( core, 0); 168 auto decls_after = __pass::declsToAddAfter ( core, 0); 166 169 167 170 // These may be modified by subnode but most be restored once we exit this statemnet. 168 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( pass, 0) );171 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( core, 0) ); 169 172 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 170 173 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); … … 202 205 } 203 206 204 template< typename pass_t >207 template< typename core_t > 205 208 template< template <class...> class container_t > 206 container_t< ptr<Stmt> > ast::Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {209 container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 207 210 __pedantic_pass_assert( __visit_children() ); 208 211 if( statements.empty() ) return {}; … … 215 218 216 219 // get the stmts/decls that will need to be spliced in 217 auto stmts_before = __pass::stmtsToAddBefore( pass, 0);218 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0);219 auto decls_before = __pass::declsToAddBefore( pass, 0);220 auto decls_after = __pass::declsToAddAfter ( pass, 0);220 auto stmts_before = __pass::stmtsToAddBefore( core, 0); 221 auto stmts_after = __pass::stmtsToAddAfter ( core, 0); 222 auto decls_before = __pass::declsToAddBefore( core, 0); 223 auto decls_after = __pass::declsToAddAfter ( core, 0); 221 224 222 225 // These may be modified by subnode but most be restored once we exit this statemnet. … … 268 271 } 269 272 270 template< typename pass_t >273 template< typename core_t > 271 274 template< template <class...> class container_t, typename node_t > 272 container_t< ast::ptr<node_t> > ast::Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {275 container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 273 276 __pedantic_pass_assert( __visit_children() ); 274 277 if( container.empty() ) return {}; … … 299 302 } 300 303 301 template< typename pass_t >304 template< typename core_t > 302 305 template<typename node_t, typename parent_t, typename child_t> 303 void ast::Pass< pass_t >::maybe_accept(306 void ast::Pass< core_t >::maybe_accept( 304 307 const node_t * & parent, 305 308 child_t parent_t::*child … … 323 326 } 324 327 328 329 template< typename core_t > 330 template< typename node_t > 331 void ast::Pass< core_t >::mutate_forall( const node_t *& node ) { 332 if ( auto subs = __pass::forall::subs( core, 0 ) ) { 333 // tracking TypeDecl substitution, full clone 334 if ( node->forall.empty() ) return; 335 336 node_t * mut = mutate( node ); 337 mut->forall = subs->clone( node->forall, *this ); 338 node = mut; 339 } else { 340 // not tracking TypeDecl substitution, just mutate 341 maybe_accept( node, &node_t::forall ); 342 } 343 } 325 344 } 326 345 … … 333 352 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 334 353 335 template< typename pass_t >336 inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) {354 template< typename core_t > 355 inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< core_t > & visitor ) { 337 356 // We are going to aggregate errors for all these statements 338 357 SemanticErrorException errors; … … 342 361 343 362 // get the stmts/decls that will need to be spliced in 344 auto decls_before = __pass::declsToAddBefore( visitor. pass, 0);345 auto decls_after = __pass::declsToAddAfter ( visitor. pass, 0);363 auto decls_before = __pass::declsToAddBefore( visitor.core, 0); 364 auto decls_after = __pass::declsToAddAfter ( visitor.core, 0); 346 365 347 366 // update pass statitistics … … 392 411 //-------------------------------------------------------------------------- 393 412 // ObjectDecl 394 template< typename pass_t >395 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {413 template< typename core_t > 414 const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::ObjectDecl * node ) { 396 415 VISIT_START( node ); 397 416 … … 406 425 ) 407 426 408 __pass::symtab::addId( pass, 0, node );427 __pass::symtab::addId( core, 0, node ); 409 428 410 429 VISIT_END( DeclWithType, node ); … … 413 432 //-------------------------------------------------------------------------- 414 433 // FunctionDecl 415 template< typename pass_t >416 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::FunctionDecl * node ) {417 VISIT_START( node ); 418 419 __pass::symtab::addId( pass, 0, node );434 template< typename core_t > 435 const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::FunctionDecl * node ) { 436 VISIT_START( node ); 437 438 __pass::symtab::addId( core, 0, node ); 420 439 421 440 VISIT(maybe_accept( node, &FunctionDecl::withExprs );) … … 425 444 // shadow with exprs and not the other way around. 426 445 guard_symtab guard { *this }; 427 __pass::symtab::addWith( pass, 0, node->withExprs, node );446 __pass::symtab::addWith( core, 0, node->withExprs, node ); 428 447 { 429 448 guard_symtab guard { *this }; 430 449 // implicit add __func__ identifier as specified in the C manual 6.4.2.2 431 static ast:: ObjectDecl func(432 node->location, "__func__",433 new ast::ArrayType (434 new ast::BasicType ( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),450 static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{ 451 CodeLocation{}, "__func__", 452 new ast::ArrayType{ 453 new ast::BasicType{ ast::BasicType::Char, ast::CV::Const }, 435 454 nullptr, VariableLen, DynamicDim 436 )437 );438 __pass::symtab::addId( pass, 0, &func );455 } 456 } }; 457 __pass::symtab::addId( core, 0, func ); 439 458 VISIT( 440 459 maybe_accept( node, &FunctionDecl::type ); … … 454 473 //-------------------------------------------------------------------------- 455 474 // StructDecl 456 template< typename pass_t >457 const ast::Decl * ast::Pass< pass_t >::visit( const ast::StructDecl * node ) {475 template< typename core_t > 476 const ast::Decl * ast::Pass< core_t >::visit( const ast::StructDecl * node ) { 458 477 VISIT_START( node ); 459 478 460 479 // make up a forward declaration and add it before processing the members 461 480 // needs to be on the heap because addStruct saves the pointer 462 __pass::symtab::addStructFwd( pass, 0, node );481 __pass::symtab::addStructFwd( core, 0, node ); 463 482 464 483 VISIT({ … … 469 488 470 489 // this addition replaces the forward declaration 471 __pass::symtab::addStruct( pass, 0, node );490 __pass::symtab::addStruct( core, 0, node ); 472 491 473 492 VISIT_END( Decl, node ); … … 476 495 //-------------------------------------------------------------------------- 477 496 // UnionDecl 478 template< typename pass_t >479 const ast::Decl * ast::Pass< pass_t >::visit( const ast::UnionDecl * node ) {497 template< typename core_t > 498 const ast::Decl * ast::Pass< core_t >::visit( const ast::UnionDecl * node ) { 480 499 VISIT_START( node ); 481 500 482 501 // make up a forward declaration and add it before processing the members 483 __pass::symtab::addUnionFwd( pass, 0, node );502 __pass::symtab::addUnionFwd( core, 0, node ); 484 503 485 504 VISIT({ … … 489 508 }) 490 509 491 __pass::symtab::addUnion( pass, 0, node );510 __pass::symtab::addUnion( core, 0, node ); 492 511 493 512 VISIT_END( Decl, node ); … … 496 515 //-------------------------------------------------------------------------- 497 516 // EnumDecl 498 template< typename pass_t >499 const ast::Decl * ast::Pass< pass_t >::visit( const ast::EnumDecl * node ) {500 VISIT_START( node ); 501 502 __pass::symtab::addEnum( pass, 0, node );517 template< typename core_t > 518 const ast::Decl * ast::Pass< core_t >::visit( const ast::EnumDecl * node ) { 519 VISIT_START( node ); 520 521 __pass::symtab::addEnum( core, 0, node ); 503 522 504 523 VISIT( … … 513 532 //-------------------------------------------------------------------------- 514 533 // TraitDecl 515 template< typename pass_t >516 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TraitDecl * node ) {534 template< typename core_t > 535 const ast::Decl * ast::Pass< core_t >::visit( const ast::TraitDecl * node ) { 517 536 VISIT_START( node ); 518 537 … … 523 542 }) 524 543 525 __pass::symtab::addTrait( pass, 0, node );544 __pass::symtab::addTrait( core, 0, node ); 526 545 527 546 VISIT_END( Decl, node ); … … 530 549 //-------------------------------------------------------------------------- 531 550 // TypeDecl 532 template< typename pass_t >533 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypeDecl * node ) {551 template< typename core_t > 552 const ast::Decl * ast::Pass< core_t >::visit( const ast::TypeDecl * node ) { 534 553 VISIT_START( node ); 535 554 … … 543 562 // note that assertions come after the type is added to the symtab, since they are not part of the type proper 544 563 // and may depend on the type itself 545 __pass::symtab::addType( pass, 0, node );564 __pass::symtab::addType( core, 0, node ); 546 565 547 566 VISIT( … … 559 578 //-------------------------------------------------------------------------- 560 579 // TypedefDecl 561 template< typename pass_t >562 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypedefDecl * node ) {580 template< typename core_t > 581 const ast::Decl * ast::Pass< core_t >::visit( const ast::TypedefDecl * node ) { 563 582 VISIT_START( node ); 564 583 … … 569 588 }) 570 589 571 __pass::symtab::addType( pass, 0, node );590 __pass::symtab::addType( core, 0, node ); 572 591 573 592 VISIT( maybe_accept( node, &TypedefDecl::assertions ); ) … … 578 597 //-------------------------------------------------------------------------- 579 598 // AsmDecl 580 template< typename pass_t >581 const ast::AsmDecl * ast::Pass< pass_t >::visit( const ast::AsmDecl * node ) {599 template< typename core_t > 600 const ast::AsmDecl * ast::Pass< core_t >::visit( const ast::AsmDecl * node ) { 582 601 VISIT_START( node ); 583 602 … … 591 610 //-------------------------------------------------------------------------- 592 611 // StaticAssertDecl 593 template< typename pass_t >594 const ast::StaticAssertDecl * ast::Pass< pass_t >::visit( const ast::StaticAssertDecl * node ) {612 template< typename core_t > 613 const ast::StaticAssertDecl * ast::Pass< core_t >::visit( const ast::StaticAssertDecl * node ) { 595 614 VISIT_START( node ); 596 615 … … 605 624 //-------------------------------------------------------------------------- 606 625 // CompoundStmt 607 template< typename pass_t >608 const ast::CompoundStmt * ast::Pass< pass_t >::visit( const ast::CompoundStmt * node ) {626 template< typename core_t > 627 const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) { 609 628 VISIT_START( node ); 610 629 VISIT({ 611 630 // do not enter a new scope if inFunction is true - needs to check old state before the assignment 612 auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {613 if ( ! inFunction ) __pass::symtab::enter(pass, 0);614 }, [this, inFunction = this->inFunction]() {615 if ( ! inFunction ) __pass::symtab::leave(pass, 0);631 auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() { 632 if ( ! inFunctionCpy ) __pass::symtab::enter(core, 0); 633 }, [this, inFunctionCpy = this->inFunction]() { 634 if ( ! inFunctionCpy ) __pass::symtab::leave(core, 0); 616 635 }); 617 636 ValueGuard< bool > guard2( inFunction ); … … 625 644 //-------------------------------------------------------------------------- 626 645 // ExprStmt 627 template< typename pass_t >628 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ExprStmt * node ) {646 template< typename core_t > 647 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ExprStmt * node ) { 629 648 VISIT_START( node ); 630 649 … … 638 657 //-------------------------------------------------------------------------- 639 658 // AsmStmt 640 template< typename pass_t >641 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::AsmStmt * node ) {659 template< typename core_t > 660 const ast::Stmt * ast::Pass< core_t >::visit( const ast::AsmStmt * node ) { 642 661 VISIT_START( node ) 643 662 … … 654 673 //-------------------------------------------------------------------------- 655 674 // DirectiveStmt 656 template< typename pass_t >657 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DirectiveStmt * node ) {675 template< typename core_t > 676 const ast::Stmt * ast::Pass< core_t >::visit( const ast::DirectiveStmt * node ) { 658 677 VISIT_START( node ) 659 678 … … 663 682 //-------------------------------------------------------------------------- 664 683 // IfStmt 665 template< typename pass_t >666 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::IfStmt * node ) {684 template< typename core_t > 685 const ast::Stmt * ast::Pass< core_t >::visit( const ast::IfStmt * node ) { 667 686 VISIT_START( node ); 668 687 … … 681 700 //-------------------------------------------------------------------------- 682 701 // WhileStmt 683 template< typename pass_t >684 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WhileStmt * node ) {702 template< typename core_t > 703 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileStmt * node ) { 685 704 VISIT_START( node ); 686 705 … … 698 717 //-------------------------------------------------------------------------- 699 718 // ForStmt 700 template< typename pass_t >701 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ForStmt * node ) {719 template< typename core_t > 720 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ForStmt * node ) { 702 721 VISIT_START( node ); 703 722 … … 716 735 //-------------------------------------------------------------------------- 717 736 // SwitchStmt 718 template< typename pass_t >719 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SwitchStmt * node ) {737 template< typename core_t > 738 const ast::Stmt * ast::Pass< core_t >::visit( const ast::SwitchStmt * node ) { 720 739 VISIT_START( node ); 721 740 … … 730 749 //-------------------------------------------------------------------------- 731 750 // CaseStmt 732 template< typename pass_t >733 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CaseStmt * node ) {751 template< typename core_t > 752 const ast::Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt * node ) { 734 753 VISIT_START( node ); 735 754 … … 744 763 //-------------------------------------------------------------------------- 745 764 // BranchStmt 746 template< typename pass_t >747 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::BranchStmt * node ) {765 template< typename core_t > 766 const ast::Stmt * ast::Pass< core_t >::visit( const ast::BranchStmt * node ) { 748 767 VISIT_START( node ); 749 768 VISIT_END( Stmt, node ); … … 752 771 //-------------------------------------------------------------------------- 753 772 // ReturnStmt 754 template< typename pass_t >755 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ReturnStmt * node ) {773 template< typename core_t > 774 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ReturnStmt * node ) { 756 775 VISIT_START( node ); 757 776 … … 765 784 //-------------------------------------------------------------------------- 766 785 // ThrowStmt 767 template< typename pass_t >768 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ThrowStmt * node ) {786 template< typename core_t > 787 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ThrowStmt * node ) { 769 788 VISIT_START( node ); 770 789 … … 779 798 //-------------------------------------------------------------------------- 780 799 // TryStmt 781 template< typename pass_t >782 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::TryStmt * node ) {800 template< typename core_t > 801 const ast::Stmt * ast::Pass< core_t >::visit( const ast::TryStmt * node ) { 783 802 VISIT_START( node ); 784 803 … … 794 813 //-------------------------------------------------------------------------- 795 814 // CatchStmt 796 template< typename pass_t >797 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CatchStmt * node ) {815 template< typename core_t > 816 const ast::Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt * node ) { 798 817 VISIT_START( node ); 799 818 … … 811 830 //-------------------------------------------------------------------------- 812 831 // FinallyStmt 813 template< typename pass_t >814 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::FinallyStmt * node ) {832 template< typename core_t > 833 const ast::Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt * node ) { 815 834 VISIT_START( node ); 816 835 … … 824 843 //-------------------------------------------------------------------------- 825 844 // FinallyStmt 826 template< typename pass_t >827 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SuspendStmt * node ) {845 template< typename core_t > 846 const ast::Stmt * ast::Pass< core_t >::visit( const ast::SuspendStmt * node ) { 828 847 VISIT_START( node ); 829 848 … … 837 856 //-------------------------------------------------------------------------- 838 857 // WaitForStmt 839 template< typename pass_t >840 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WaitForStmt * node ) {858 template< typename core_t > 859 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitForStmt * node ) { 841 860 VISIT_START( node ); 842 861 // for( auto & clause : node->clauses ) { … … 906 925 //-------------------------------------------------------------------------- 907 926 // WithStmt 908 template< typename pass_t >909 const ast::Decl * ast::Pass< pass_t >::visit( const ast::WithStmt * node ) {927 template< typename core_t > 928 const ast::Decl * ast::Pass< core_t >::visit( const ast::WithStmt * node ) { 910 929 VISIT_START( node ); 911 930 … … 915 934 // catch statements introduce a level of scope (for the caught exception) 916 935 guard_symtab guard { *this }; 917 __pass::symtab::addWith( pass, 0, node->exprs, node );936 __pass::symtab::addWith( core, 0, node->exprs, node ); 918 937 maybe_accept( node, &WithStmt::stmt ); 919 938 } … … 924 943 //-------------------------------------------------------------------------- 925 944 // NullStmt 926 template< typename pass_t >927 const ast::NullStmt * ast::Pass< pass_t >::visit( const ast::NullStmt * node ) {945 template< typename core_t > 946 const ast::NullStmt * ast::Pass< core_t >::visit( const ast::NullStmt * node ) { 928 947 VISIT_START( node ); 929 948 VISIT_END( NullStmt, node ); … … 932 951 //-------------------------------------------------------------------------- 933 952 // DeclStmt 934 template< typename pass_t >935 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DeclStmt * node ) {953 template< typename core_t > 954 const ast::Stmt * ast::Pass< core_t >::visit( const ast::DeclStmt * node ) { 936 955 VISIT_START( node ); 937 956 … … 945 964 //-------------------------------------------------------------------------- 946 965 // ImplicitCtorDtorStmt 947 template< typename pass_t >948 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {966 template< typename core_t > 967 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ImplicitCtorDtorStmt * node ) { 949 968 VISIT_START( node ); 950 969 951 970 // For now this isn't visited, it is unclear if this causes problem 952 971 // if all tests are known to pass, remove this code 953 //VISIT(954 //maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );955 //)972 VISIT( 973 maybe_accept( node, &ImplicitCtorDtorStmt::callStmt ); 974 ) 956 975 957 976 VISIT_END( Stmt, node ); … … 960 979 //-------------------------------------------------------------------------- 961 980 // ApplicationExpr 962 template< typename pass_t >963 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ApplicationExpr * node ) {981 template< typename core_t > 982 const ast::Expr * ast::Pass< core_t >::visit( const ast::ApplicationExpr * node ) { 964 983 VISIT_START( node ); 965 984 … … 978 997 //-------------------------------------------------------------------------- 979 998 // UntypedExpr 980 template< typename pass_t >981 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedExpr * node ) {999 template< typename core_t > 1000 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedExpr * node ) { 982 1001 VISIT_START( node ); 983 1002 … … 996 1015 //-------------------------------------------------------------------------- 997 1016 // NameExpr 998 template< typename pass_t >999 const ast::Expr * ast::Pass< pass_t >::visit( const ast::NameExpr * node ) {1017 template< typename core_t > 1018 const ast::Expr * ast::Pass< core_t >::visit( const ast::NameExpr * node ) { 1000 1019 VISIT_START( node ); 1001 1020 … … 1010 1029 //-------------------------------------------------------------------------- 1011 1030 // CastExpr 1012 template< typename pass_t >1013 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CastExpr * node ) {1031 template< typename core_t > 1032 const ast::Expr * ast::Pass< core_t >::visit( const ast::CastExpr * node ) { 1014 1033 VISIT_START( node ); 1015 1034 … … 1026 1045 //-------------------------------------------------------------------------- 1027 1046 // KeywordCastExpr 1028 template< typename pass_t >1029 const ast::Expr * ast::Pass< pass_t >::visit( const ast::KeywordCastExpr * node ) {1047 template< typename core_t > 1048 const ast::Expr * ast::Pass< core_t >::visit( const ast::KeywordCastExpr * node ) { 1030 1049 VISIT_START( node ); 1031 1050 … … 1042 1061 //-------------------------------------------------------------------------- 1043 1062 // VirtualCastExpr 1044 template< typename pass_t >1045 const ast::Expr * ast::Pass< pass_t >::visit( const ast::VirtualCastExpr * node ) {1063 template< typename core_t > 1064 const ast::Expr * ast::Pass< core_t >::visit( const ast::VirtualCastExpr * node ) { 1046 1065 VISIT_START( node ); 1047 1066 … … 1058 1077 //-------------------------------------------------------------------------- 1059 1078 // AddressExpr 1060 template< typename pass_t >1061 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AddressExpr * node ) {1079 template< typename core_t > 1080 const ast::Expr * ast::Pass< core_t >::visit( const ast::AddressExpr * node ) { 1062 1081 VISIT_START( node ); 1063 1082 … … 1074 1093 //-------------------------------------------------------------------------- 1075 1094 // LabelAddressExpr 1076 template< typename pass_t >1077 const ast::Expr * ast::Pass< pass_t >::visit( const ast::LabelAddressExpr * node ) {1095 template< typename core_t > 1096 const ast::Expr * ast::Pass< core_t >::visit( const ast::LabelAddressExpr * node ) { 1078 1097 VISIT_START( node ); 1079 1098 … … 1088 1107 //-------------------------------------------------------------------------- 1089 1108 // UntypedMemberExpr 1090 template< typename pass_t >1091 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedMemberExpr * node ) {1109 template< typename core_t > 1110 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedMemberExpr * node ) { 1092 1111 VISIT_START( node ); 1093 1112 … … 1105 1124 //-------------------------------------------------------------------------- 1106 1125 // MemberExpr 1107 template< typename pass_t >1108 const ast::Expr * ast::Pass< pass_t >::visit( const ast::MemberExpr * node ) {1126 template< typename core_t > 1127 const ast::Expr * ast::Pass< core_t >::visit( const ast::MemberExpr * node ) { 1109 1128 VISIT_START( node ); 1110 1129 … … 1121 1140 //-------------------------------------------------------------------------- 1122 1141 // VariableExpr 1123 template< typename pass_t >1124 const ast::Expr * ast::Pass< pass_t >::visit( const ast::VariableExpr * node ) {1142 template< typename core_t > 1143 const ast::Expr * ast::Pass< core_t >::visit( const ast::VariableExpr * node ) { 1125 1144 VISIT_START( node ); 1126 1145 … … 1135 1154 //-------------------------------------------------------------------------- 1136 1155 // ConstantExpr 1137 template< typename pass_t >1138 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstantExpr * node ) {1156 template< typename core_t > 1157 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstantExpr * node ) { 1139 1158 VISIT_START( node ); 1140 1159 … … 1149 1168 //-------------------------------------------------------------------------- 1150 1169 // SizeofExpr 1151 template< typename pass_t >1152 const ast::Expr * ast::Pass< pass_t >::visit( const ast::SizeofExpr * node ) {1170 template< typename core_t > 1171 const ast::Expr * ast::Pass< core_t >::visit( const ast::SizeofExpr * node ) { 1153 1172 VISIT_START( node ); 1154 1173 … … 1169 1188 //-------------------------------------------------------------------------- 1170 1189 // AlignofExpr 1171 template< typename pass_t >1172 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AlignofExpr * node ) {1190 template< typename core_t > 1191 const ast::Expr * ast::Pass< core_t >::visit( const ast::AlignofExpr * node ) { 1173 1192 VISIT_START( node ); 1174 1193 … … 1189 1208 //-------------------------------------------------------------------------- 1190 1209 // UntypedOffsetofExpr 1191 template< typename pass_t >1192 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedOffsetofExpr * node ) {1210 template< typename core_t > 1211 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedOffsetofExpr * node ) { 1193 1212 VISIT_START( node ); 1194 1213 … … 1205 1224 //-------------------------------------------------------------------------- 1206 1225 // OffsetofExpr 1207 template< typename pass_t >1208 const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetofExpr * node ) {1226 template< typename core_t > 1227 const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetofExpr * node ) { 1209 1228 VISIT_START( node ); 1210 1229 … … 1221 1240 //-------------------------------------------------------------------------- 1222 1241 // OffsetPackExpr 1223 template< typename pass_t >1224 const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetPackExpr * node ) {1242 template< typename core_t > 1243 const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetPackExpr * node ) { 1225 1244 VISIT_START( node ); 1226 1245 … … 1237 1256 //-------------------------------------------------------------------------- 1238 1257 // LogicalExpr 1239 template< typename pass_t >1240 const ast::Expr * ast::Pass< pass_t >::visit( const ast::LogicalExpr * node ) {1258 template< typename core_t > 1259 const ast::Expr * ast::Pass< core_t >::visit( const ast::LogicalExpr * node ) { 1241 1260 VISIT_START( node ); 1242 1261 … … 1254 1273 //-------------------------------------------------------------------------- 1255 1274 // ConditionalExpr 1256 template< typename pass_t >1257 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConditionalExpr * node ) {1275 template< typename core_t > 1276 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConditionalExpr * node ) { 1258 1277 VISIT_START( node ); 1259 1278 … … 1272 1291 //-------------------------------------------------------------------------- 1273 1292 // CommaExpr 1274 template< typename pass_t >1275 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CommaExpr * node ) {1293 template< typename core_t > 1294 const ast::Expr * ast::Pass< core_t >::visit( const ast::CommaExpr * node ) { 1276 1295 VISIT_START( node ); 1277 1296 … … 1289 1308 //-------------------------------------------------------------------------- 1290 1309 // TypeExpr 1291 template< typename pass_t >1292 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TypeExpr * node ) {1310 template< typename core_t > 1311 const ast::Expr * ast::Pass< core_t >::visit( const ast::TypeExpr * node ) { 1293 1312 VISIT_START( node ); 1294 1313 … … 1305 1324 //-------------------------------------------------------------------------- 1306 1325 // AsmExpr 1307 template< typename pass_t >1308 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AsmExpr * node ) {1326 template< typename core_t > 1327 const ast::Expr * ast::Pass< core_t >::visit( const ast::AsmExpr * node ) { 1309 1328 VISIT_START( node ); 1310 1329 … … 1322 1341 //-------------------------------------------------------------------------- 1323 1342 // ImplicitCopyCtorExpr 1324 template< typename pass_t >1325 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {1343 template< typename core_t > 1344 const ast::Expr * ast::Pass< core_t >::visit( const ast::ImplicitCopyCtorExpr * node ) { 1326 1345 VISIT_START( node ); 1327 1346 … … 1338 1357 //-------------------------------------------------------------------------- 1339 1358 // ConstructorExpr 1340 template< typename pass_t >1341 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstructorExpr * node ) {1359 template< typename core_t > 1360 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstructorExpr * node ) { 1342 1361 VISIT_START( node ); 1343 1362 … … 1354 1373 //-------------------------------------------------------------------------- 1355 1374 // CompoundLiteralExpr 1356 template< typename pass_t >1357 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CompoundLiteralExpr * node ) {1375 template< typename core_t > 1376 const ast::Expr * ast::Pass< core_t >::visit( const ast::CompoundLiteralExpr * node ) { 1358 1377 VISIT_START( node ); 1359 1378 … … 1370 1389 //-------------------------------------------------------------------------- 1371 1390 // RangeExpr 1372 template< typename pass_t >1373 const ast::Expr * ast::Pass< pass_t >::visit( const ast::RangeExpr * node ) {1391 template< typename core_t > 1392 const ast::Expr * ast::Pass< core_t >::visit( const ast::RangeExpr * node ) { 1374 1393 VISIT_START( node ); 1375 1394 … … 1387 1406 //-------------------------------------------------------------------------- 1388 1407 // UntypedTupleExpr 1389 template< typename pass_t >1390 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedTupleExpr * node ) {1408 template< typename core_t > 1409 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedTupleExpr * node ) { 1391 1410 VISIT_START( node ); 1392 1411 … … 1403 1422 //-------------------------------------------------------------------------- 1404 1423 // TupleExpr 1405 template< typename pass_t >1406 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleExpr * node ) {1424 template< typename core_t > 1425 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleExpr * node ) { 1407 1426 VISIT_START( node ); 1408 1427 … … 1419 1438 //-------------------------------------------------------------------------- 1420 1439 // TupleIndexExpr 1421 template< typename pass_t >1422 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleIndexExpr * node ) {1440 template< typename core_t > 1441 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleIndexExpr * node ) { 1423 1442 VISIT_START( node ); 1424 1443 … … 1435 1454 //-------------------------------------------------------------------------- 1436 1455 // TupleAssignExpr 1437 template< typename pass_t >1438 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleAssignExpr * node ) {1456 template< typename core_t > 1457 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleAssignExpr * node ) { 1439 1458 VISIT_START( node ); 1440 1459 … … 1451 1470 //-------------------------------------------------------------------------- 1452 1471 // StmtExpr 1453 template< typename pass_t >1454 const ast::Expr * ast::Pass< pass_t >::visit( const ast::StmtExpr * node ) {1472 template< typename core_t > 1473 const ast::Expr * ast::Pass< core_t >::visit( const ast::StmtExpr * node ) { 1455 1474 VISIT_START( node ); 1456 1475 1457 1476 VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr 1458 1477 // get the stmts that will need to be spliced in 1459 auto stmts_before = __pass::stmtsToAddBefore( pass, 0);1460 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0);1478 auto stmts_before = __pass::stmtsToAddBefore( core, 0); 1479 auto stmts_after = __pass::stmtsToAddAfter ( core, 0); 1461 1480 1462 1481 // These may be modified by subnode but most be restored once we exit this statemnet. 1463 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( pass, 0) );1482 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( core, 0) ); 1464 1483 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 1465 1484 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); … … 1479 1498 //-------------------------------------------------------------------------- 1480 1499 // UniqueExpr 1481 template< typename pass_t >1482 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UniqueExpr * node ) {1500 template< typename core_t > 1501 const ast::Expr * ast::Pass< core_t >::visit( const ast::UniqueExpr * node ) { 1483 1502 VISIT_START( node ); 1484 1503 … … 1495 1514 //-------------------------------------------------------------------------- 1496 1515 // UntypedInitExpr 1497 template< typename pass_t >1498 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedInitExpr * node ) {1516 template< typename core_t > 1517 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedInitExpr * node ) { 1499 1518 VISIT_START( node ); 1500 1519 … … 1512 1531 //-------------------------------------------------------------------------- 1513 1532 // InitExpr 1514 template< typename pass_t >1515 const ast::Expr * ast::Pass< pass_t >::visit( const ast::InitExpr * node ) {1533 template< typename core_t > 1534 const ast::Expr * ast::Pass< core_t >::visit( const ast::InitExpr * node ) { 1516 1535 VISIT_START( node ); 1517 1536 … … 1529 1548 //-------------------------------------------------------------------------- 1530 1549 // DeletedExpr 1531 template< typename pass_t >1532 const ast::Expr * ast::Pass< pass_t >::visit( const ast::DeletedExpr * node ) {1550 template< typename core_t > 1551 const ast::Expr * ast::Pass< core_t >::visit( const ast::DeletedExpr * node ) { 1533 1552 VISIT_START( node ); 1534 1553 … … 1546 1565 //-------------------------------------------------------------------------- 1547 1566 // DefaultArgExpr 1548 template< typename pass_t >1549 const ast::Expr * ast::Pass< pass_t >::visit( const ast::DefaultArgExpr * node ) {1567 template< typename core_t > 1568 const ast::Expr * ast::Pass< core_t >::visit( const ast::DefaultArgExpr * node ) { 1550 1569 VISIT_START( node ); 1551 1570 … … 1562 1581 //-------------------------------------------------------------------------- 1563 1582 // GenericExpr 1564 template< typename pass_t >1565 const ast::Expr * ast::Pass< pass_t >::visit( const ast::GenericExpr * node ) {1583 template< typename core_t > 1584 const ast::Expr * ast::Pass< core_t >::visit( const ast::GenericExpr * node ) { 1566 1585 VISIT_START( node ); 1567 1586 … … 1602 1621 //-------------------------------------------------------------------------- 1603 1622 // VoidType 1604 template< typename pass_t >1605 const ast::Type * ast::Pass< pass_t >::visit( const ast::VoidType * node ) {1623 template< typename core_t > 1624 const ast::Type * ast::Pass< core_t >::visit( const ast::VoidType * node ) { 1606 1625 VISIT_START( node ); 1607 1626 … … 1611 1630 //-------------------------------------------------------------------------- 1612 1631 // BasicType 1613 template< typename pass_t >1614 const ast::Type * ast::Pass< pass_t >::visit( const ast::BasicType * node ) {1632 template< typename core_t > 1633 const ast::Type * ast::Pass< core_t >::visit( const ast::BasicType * node ) { 1615 1634 VISIT_START( node ); 1616 1635 … … 1620 1639 //-------------------------------------------------------------------------- 1621 1640 // PointerType 1622 template< typename pass_t >1623 const ast::Type * ast::Pass< pass_t >::visit( const ast::PointerType * node ) {1641 template< typename core_t > 1642 const ast::Type * ast::Pass< core_t >::visit( const ast::PointerType * node ) { 1624 1643 VISIT_START( node ); 1625 1644 … … 1634 1653 //-------------------------------------------------------------------------- 1635 1654 // ArrayType 1636 template< typename pass_t >1637 const ast::Type * ast::Pass< pass_t >::visit( const ast::ArrayType * node ) {1655 template< typename core_t > 1656 const ast::Type * ast::Pass< core_t >::visit( const ast::ArrayType * node ) { 1638 1657 VISIT_START( node ); 1639 1658 … … 1648 1667 //-------------------------------------------------------------------------- 1649 1668 // ReferenceType 1650 template< typename pass_t >1651 const ast::Type * ast::Pass< pass_t >::visit( const ast::ReferenceType * node ) {1669 template< typename core_t > 1670 const ast::Type * ast::Pass< core_t >::visit( const ast::ReferenceType * node ) { 1652 1671 VISIT_START( node ); 1653 1672 … … 1661 1680 //-------------------------------------------------------------------------- 1662 1681 // QualifiedType 1663 template< typename pass_t >1664 const ast::Type * ast::Pass< pass_t >::visit( const ast::QualifiedType * node ) {1682 template< typename core_t > 1683 const ast::Type * ast::Pass< core_t >::visit( const ast::QualifiedType * node ) { 1665 1684 VISIT_START( node ); 1666 1685 … … 1675 1694 //-------------------------------------------------------------------------- 1676 1695 // FunctionType 1677 template< typename pass_t > 1678 const ast::Type * ast::Pass< pass_t >::visit( const ast::FunctionType * node ) { 1679 VISIT_START( node ); 1680 1681 VISIT( 1682 maybe_accept( node, &FunctionType::forall ); 1696 template< typename core_t > 1697 const ast::Type * ast::Pass< core_t >::visit( const ast::FunctionType * node ) { 1698 VISIT_START( node ); 1699 1700 VISIT({ 1701 guard_forall_subs forall_guard { *this, node }; 1702 mutate_forall( node ); 1683 1703 maybe_accept( node, &FunctionType::returns ); 1684 1704 maybe_accept( node, &FunctionType::params ); 1685 )1705 }) 1686 1706 1687 1707 VISIT_END( Type, node ); … … 1690 1710 //-------------------------------------------------------------------------- 1691 1711 // StructInstType 1692 template< typename pass_t >1693 const ast::Type * ast::Pass< pass_t >::visit( const ast::StructInstType * node ) {1694 VISIT_START( node ); 1695 1696 __pass::symtab::addStruct( pass, 0, node->name );1712 template< typename core_t > 1713 const ast::Type * ast::Pass< core_t >::visit( const ast::StructInstType * node ) { 1714 VISIT_START( node ); 1715 1716 __pass::symtab::addStruct( core, 0, node->name ); 1697 1717 1698 1718 VISIT({ 1699 1719 guard_symtab guard { *this }; 1700 maybe_accept( node, &StructInstType::forall ); 1720 guard_forall_subs forall_guard { *this, node }; 1721 mutate_forall( node ); 1701 1722 maybe_accept( node, &StructInstType::params ); 1702 1723 }) … … 1707 1728 //-------------------------------------------------------------------------- 1708 1729 // UnionInstType 1709 template< typename pass_t >1710 const ast::Type * ast::Pass< pass_t >::visit( const ast::UnionInstType * node ) {1711 VISIT_START( node ); 1712 1713 __pass::symtab::add Struct( pass, 0, node->name );1714 1715 {1730 template< typename core_t > 1731 const ast::Type * ast::Pass< core_t >::visit( const ast::UnionInstType * node ) { 1732 VISIT_START( node ); 1733 1734 __pass::symtab::addUnion( core, 0, node->name ); 1735 1736 VISIT({ 1716 1737 guard_symtab guard { *this }; 1717 maybe_accept( node, &UnionInstType::forall ); 1738 guard_forall_subs forall_guard { *this, node }; 1739 mutate_forall( node ); 1718 1740 maybe_accept( node, &UnionInstType::params ); 1719 } 1741 }) 1720 1742 1721 1743 VISIT_END( Type, node ); … … 1724 1746 //-------------------------------------------------------------------------- 1725 1747 // EnumInstType 1726 template< typename pass_t > 1727 const ast::Type * ast::Pass< pass_t >::visit( const ast::EnumInstType * node ) { 1728 VISIT_START( node ); 1729 1730 VISIT( 1731 maybe_accept( node, &EnumInstType::forall ); 1748 template< typename core_t > 1749 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumInstType * node ) { 1750 VISIT_START( node ); 1751 1752 VISIT({ 1753 guard_forall_subs forall_guard { *this, node }; 1754 mutate_forall( node ); 1732 1755 maybe_accept( node, &EnumInstType::params ); 1733 )1756 }) 1734 1757 1735 1758 VISIT_END( Type, node ); … … 1738 1761 //-------------------------------------------------------------------------- 1739 1762 // TraitInstType 1740 template< typename pass_t > 1741 const ast::Type * ast::Pass< pass_t >::visit( const ast::TraitInstType * node ) { 1742 VISIT_START( node ); 1743 1744 VISIT( 1745 maybe_accept( node, &TraitInstType::forall ); 1763 template< typename core_t > 1764 const ast::Type * ast::Pass< core_t >::visit( const ast::TraitInstType * node ) { 1765 VISIT_START( node ); 1766 1767 VISIT({ 1768 guard_forall_subs forall_guard { *this, node }; 1769 mutate_forall( node ); 1746 1770 maybe_accept( node, &TraitInstType::params ); 1747 )1771 }) 1748 1772 1749 1773 VISIT_END( Type, node ); … … 1752 1776 //-------------------------------------------------------------------------- 1753 1777 // TypeInstType 1754 template< typename pass_t > 1755 const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeInstType * node ) { 1756 VISIT_START( node ); 1757 1758 VISIT( 1759 maybe_accept( node, &TypeInstType::forall ); 1760 maybe_accept( node, &TypeInstType::params ); 1778 template< typename core_t > 1779 const ast::Type * ast::Pass< core_t >::visit( const ast::TypeInstType * node ) { 1780 VISIT_START( node ); 1781 1782 VISIT( 1783 { 1784 guard_forall_subs forall_guard { *this, node }; 1785 mutate_forall( node ); 1786 maybe_accept( node, &TypeInstType::params ); 1787 } 1788 // ensure that base re-bound if doing substitution 1789 __pass::forall::replace( core, 0, node ); 1761 1790 ) 1762 1791 … … 1766 1795 //-------------------------------------------------------------------------- 1767 1796 // TupleType 1768 template< typename pass_t >1769 const ast::Type * ast::Pass< pass_t >::visit( const ast::TupleType * node ) {1797 template< typename core_t > 1798 const ast::Type * ast::Pass< core_t >::visit( const ast::TupleType * node ) { 1770 1799 VISIT_START( node ); 1771 1800 … … 1780 1809 //-------------------------------------------------------------------------- 1781 1810 // TypeofType 1782 template< typename pass_t >1783 const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeofType * node ) {1811 template< typename core_t > 1812 const ast::Type * ast::Pass< core_t >::visit( const ast::TypeofType * node ) { 1784 1813 VISIT_START( node ); 1785 1814 … … 1793 1822 //-------------------------------------------------------------------------- 1794 1823 // VarArgsType 1795 template< typename pass_t >1796 const ast::Type * ast::Pass< pass_t >::visit( const ast::VarArgsType * node ) {1824 template< typename core_t > 1825 const ast::Type * ast::Pass< core_t >::visit( const ast::VarArgsType * node ) { 1797 1826 VISIT_START( node ); 1798 1827 … … 1802 1831 //-------------------------------------------------------------------------- 1803 1832 // ZeroType 1804 template< typename pass_t >1805 const ast::Type * ast::Pass< pass_t >::visit( const ast::ZeroType * node ) {1833 template< typename core_t > 1834 const ast::Type * ast::Pass< core_t >::visit( const ast::ZeroType * node ) { 1806 1835 VISIT_START( node ); 1807 1836 … … 1811 1840 //-------------------------------------------------------------------------- 1812 1841 // OneType 1813 template< typename pass_t >1814 const ast::Type * ast::Pass< pass_t >::visit( const ast::OneType * node ) {1842 template< typename core_t > 1843 const ast::Type * ast::Pass< core_t >::visit( const ast::OneType * node ) { 1815 1844 VISIT_START( node ); 1816 1845 … … 1820 1849 //-------------------------------------------------------------------------- 1821 1850 // GlobalScopeType 1822 template< typename pass_t >1823 const ast::Type * ast::Pass< pass_t >::visit( const ast::GlobalScopeType * node ) {1851 template< typename core_t > 1852 const ast::Type * ast::Pass< core_t >::visit( const ast::GlobalScopeType * node ) { 1824 1853 VISIT_START( node ); 1825 1854 … … 1830 1859 //-------------------------------------------------------------------------- 1831 1860 // Designation 1832 template< typename pass_t >1833 const ast::Designation * ast::Pass< pass_t >::visit( const ast::Designation * node ) {1861 template< typename core_t > 1862 const ast::Designation * ast::Pass< core_t >::visit( const ast::Designation * node ) { 1834 1863 VISIT_START( node ); 1835 1864 … … 1841 1870 //-------------------------------------------------------------------------- 1842 1871 // SingleInit 1843 template< typename pass_t >1844 const ast::Init * ast::Pass< pass_t >::visit( const ast::SingleInit * node ) {1872 template< typename core_t > 1873 const ast::Init * ast::Pass< core_t >::visit( const ast::SingleInit * node ) { 1845 1874 VISIT_START( node ); 1846 1875 … … 1854 1883 //-------------------------------------------------------------------------- 1855 1884 // ListInit 1856 template< typename pass_t >1857 const ast::Init * ast::Pass< pass_t >::visit( const ast::ListInit * node ) {1885 template< typename core_t > 1886 const ast::Init * ast::Pass< core_t >::visit( const ast::ListInit * node ) { 1858 1887 VISIT_START( node ); 1859 1888 … … 1868 1897 //-------------------------------------------------------------------------- 1869 1898 // ConstructorInit 1870 template< typename pass_t >1871 const ast::Init * ast::Pass< pass_t >::visit( const ast::ConstructorInit * node ) {1899 template< typename core_t > 1900 const ast::Init * ast::Pass< core_t >::visit( const ast::ConstructorInit * node ) { 1872 1901 VISIT_START( node ); 1873 1902 … … 1883 1912 //-------------------------------------------------------------------------- 1884 1913 // Attribute 1885 template< typename pass_t >1886 const ast::Attribute * ast::Pass< pass_t >::visit( const ast::Attribute * node ) {1914 template< typename core_t > 1915 const ast::Attribute * ast::Pass< core_t >::visit( const ast::Attribute * node ) { 1887 1916 VISIT_START( node ); 1888 1917 … … 1896 1925 //-------------------------------------------------------------------------- 1897 1926 // TypeSubstitution 1898 template< typename pass_t >1899 const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {1927 template< typename core_t > 1928 const ast::TypeSubstitution * ast::Pass< core_t >::visit( const ast::TypeSubstitution * node ) { 1900 1929 VISIT_START( node ); 1901 1930 … … 1907 1936 guard_symtab guard { *this }; 1908 1937 auto new_node = p.second->accept( *this ); 1909 if (new_node != p.second) mutated = false;1938 if (new_node != p.second) mutated = true; 1910 1939 new_map.insert({ p.first, new_node }); 1911 1940 } … … 1923 1952 guard_symtab guard { *this }; 1924 1953 auto new_node = p.second->accept( *this ); 1925 if (new_node != p.second) mutated = false;1954 if (new_node != p.second) mutated = true; 1926 1955 new_map.insert({ p.first, new_node }); 1927 1956 } -
src/AST/Pass.proto.hpp
r309d814 r4c925cd 17 17 // IWYU pragma: private, include "Pass.hpp" 18 18 19 #include "Common/Stats/Heap.h" 20 19 21 namespace ast { 20 template<typename pass_type>22 template<typename core_t> 21 23 class Pass; 22 24 … … 82 84 }; 83 85 84 std::stack< cleanup_t > cleanups;86 std::stack< cleanup_t, std::vector<cleanup_t> > cleanups; 85 87 }; 86 88 … … 111 113 /// "Short hand" to check if this is a valid previsit function 112 114 /// Mostly used to make the static_assert look (and print) prettier 113 template<typename pass_t, typename node_t>115 template<typename core_t, typename node_t> 114 116 struct is_valid_previsit { 115 using ret_t = decltype( (( pass_t*)nullptr)->previsit( (const node_t *)nullptr ) );117 using ret_t = decltype( ((core_t*)nullptr)->previsit( (const node_t *)nullptr ) ); 116 118 117 119 static constexpr bool value = std::is_void< ret_t >::value || … … 127 129 template<> 128 130 struct __assign<true> { 129 template<typename pass_t, typename node_t>130 static inline void result( pass_t & pass, const node_t * & node ) {131 pass.previsit( node );131 template<typename core_t, typename node_t> 132 static inline void result( core_t & core, const node_t * & node ) { 133 core.previsit( node ); 132 134 } 133 135 }; … … 135 137 template<> 136 138 struct __assign<false> { 137 template<typename pass_t, typename node_t>138 static inline void result( pass_t & pass, const node_t * & node ) {139 node = pass.previsit( node );139 template<typename core_t, typename node_t> 140 static inline void result( core_t & core, const node_t * & node ) { 141 node = core.previsit( node ); 140 142 assertf(node, "Previsit must not return NULL"); 141 143 } … … 150 152 template<> 151 153 struct __return<true> { 152 template<typename pass_t, typename node_t>153 static inline const node_t * result( pass_t & pass, const node_t * & node ) {154 pass.postvisit( node );154 template<typename core_t, typename node_t> 155 static inline const node_t * result( core_t & core, const node_t * & node ) { 156 core.postvisit( node ); 155 157 return node; 156 158 } … … 159 161 template<> 160 162 struct __return<false> { 161 template<typename pass_t, typename node_t>162 static inline auto result( pass_t & pass, const node_t * & node ) {163 return pass.postvisit( node );163 template<typename core_t, typename node_t> 164 static inline auto result( core_t & core, const node_t * & node ) { 165 return core.postvisit( node ); 164 166 } 165 167 }; … … 180 182 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 181 183 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 182 template<typename pass_t, typename node_t>183 static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) {184 template<typename core_t, typename node_t> 185 static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) { 184 186 static_assert( 185 is_valid_previsit< pass_t, node_t>::value,187 is_valid_previsit<core_t, node_t>::value, 186 188 "Previsit may not change the type of the node. It must return its paremeter or void." 187 189 ); … … 189 191 __assign< 190 192 std::is_void< 191 decltype( pass.previsit( node ) )193 decltype( core.previsit( node ) ) 192 194 >::value 193 >::result( pass, node );195 >::result( core, node ); 194 196 } 195 197 196 template<typename pass_t, typename node_t>197 static inline auto previsit( pass_t &, const node_t *, long ) {}198 template<typename core_t, typename node_t> 199 static inline auto previsit( core_t &, const node_t *, long ) {} 198 200 199 201 // PostVisit : never mutates the passed pointer but may return a different node 200 template<typename pass_t, typename node_t>201 static inline auto postvisit( pass_t & pass, const node_t * node, int ) ->202 decltype( pass.postvisit( node ), node->accept( *(Visitor*)nullptr ) )202 template<typename core_t, typename node_t> 203 static inline auto postvisit( core_t & core, const node_t * node, int ) -> 204 decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) ) 203 205 { 204 206 return __return< 205 207 std::is_void< 206 decltype( pass.postvisit( node ) )208 decltype( core.postvisit( node ) ) 207 209 >::value 208 >::result( pass, node );210 >::result( core, node ); 209 211 } 210 212 211 template<typename pass_t, typename node_t>212 static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; }213 template<typename core_t, typename node_t> 214 static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; } 213 215 214 216 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- … … 225 227 // The type is not strictly enforced but does match the accessory 226 228 #define FIELD_PTR( name, default_type ) \ 227 template< typename pass_t > \228 static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \229 template< typename core_t > \ 230 static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \ 229 231 \ 230 template< typename pass_t > \231 static inline default_type * name( pass_t &, long ) { return nullptr; }232 template< typename core_t > \ 233 static inline default_type * name( core_t &, long ) { return nullptr; } 232 234 233 235 // List of fields and their expected types … … 239 241 FIELD_PTR( visit_children, __pass::bool_ref ) 240 242 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 241 FIELD_PTR( visitor, ast::Pass< pass_t> * const )243 FIELD_PTR( visitor, ast::Pass<core_t> * const ) 242 244 243 245 // Remove the macro to make sure we don't clash 244 246 #undef FIELD_PTR 247 248 template< typename core_t > 249 static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 250 // Stats::Heap::stacktrace_push(core_t::traceId); 251 } 252 253 template< typename core_t > 254 static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 255 // Stats::Heap::stacktrace_pop(); 256 } 257 258 template< typename core_t > 259 static void beginTrace(core_t &, long) {} 260 261 template< typename core_t > 262 static void endTrace(core_t &, long) {} 245 263 246 264 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. … … 248 266 // detect it using the same strategy 249 267 namespace scope { 250 template<typename pass_t>251 static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) {252 pass.beginScope();253 } 254 255 template<typename pass_t>256 static inline void enter( pass_t &, long ) {}257 258 template<typename pass_t>259 static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) {260 pass.endScope();261 } 262 263 template<typename pass_t>264 static inline void leave( pass_t &, long ) {}265 } ;266 267 // Finally certain pass desire an up to date symbol table automatically268 template<typename core_t> 269 static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) { 270 core.beginScope(); 271 } 272 273 template<typename core_t> 274 static inline void enter( core_t &, long ) {} 275 276 template<typename core_t> 277 static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) { 278 core.endScope(); 279 } 280 281 template<typename core_t> 282 static inline void leave( core_t &, long ) {} 283 } // namespace scope 284 285 // Certain passes desire an up to date symbol table automatically 268 286 // detect the presence of a member name `symtab` and call all the members appropriately 269 287 namespace symtab { 270 288 // Some simple scoping rules 271 template<typename pass_t>272 static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) {273 pass.symtab.enterScope();274 } 275 276 template<typename pass_t>277 static inline auto enter( pass_t &, long ) {}278 279 template<typename pass_t>280 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) {281 pass.symtab.leaveScope();282 } 283 284 template<typename pass_t>285 static inline auto leave( pass_t &, long ) {}289 template<typename core_t> 290 static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) { 291 core.symtab.enterScope(); 292 } 293 294 template<typename core_t> 295 static inline auto enter( core_t &, long ) {} 296 297 template<typename core_t> 298 static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) { 299 core.symtab.leaveScope(); 300 } 301 302 template<typename core_t> 303 static inline auto leave( core_t &, long ) {} 286 304 287 305 // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments 288 306 // Create macro to condense these common patterns 289 307 #define SYMTAB_FUNC1( func, type ) \ 290 template<typename pass_t> \291 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.symtab.func( arg ), void() ) {\292 pass.symtab.func( arg ); \308 template<typename core_t> \ 309 static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\ 310 core.symtab.func( arg ); \ 293 311 } \ 294 312 \ 295 template<typename pass_t> \296 static inline void func( pass_t &, long, type ) {}313 template<typename core_t> \ 314 static inline void func( core_t &, long, type ) {} 297 315 298 316 #define SYMTAB_FUNC2( func, type1, type2 ) \ 299 template<typename pass_t> \300 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.symtab.func( arg1, arg2 ), void () ) {\301 pass.symtab.func( arg1, arg2 ); \317 template<typename core_t> \ 318 static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\ 319 core.symtab.func( arg1, arg2 ); \ 302 320 } \ 303 321 \ 304 template<typename pass_t> \305 static inline void func( pass_t &, long, type1, type2 ) {}322 template<typename core_t> \ 323 static inline void func( core_t &, long, type1, type2 ) {} 306 324 307 325 SYMTAB_FUNC1( addId , const DeclWithType * ); … … 311 329 SYMTAB_FUNC1( addUnion , const UnionDecl * ); 312 330 SYMTAB_FUNC1( addTrait , const TraitDecl * ); 313 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Node* );331 SYMTAB_FUNC2( addWith , const std::vector< ptr<Expr> > &, const Decl * ); 314 332 315 333 // A few extra functions have more complicated behaviour, they are hand written 316 template<typename pass_t>317 static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.symtab.addStruct( decl ), void() ) {334 template<typename core_t> 335 static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) { 318 336 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 319 337 fwd->params = decl->params; 320 pass.symtab.addStruct( fwd );321 } 322 323 template<typename pass_t>324 static inline void addStructFwd( pass_t &, long, const ast::StructDecl * ) {}325 326 template<typename pass_t>327 static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.symtab.addUnion( decl ), void() ) {338 core.symtab.addStruct( fwd ); 339 } 340 341 template<typename core_t> 342 static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {} 343 344 template<typename core_t> 345 static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) { 328 346 UnionDecl * fwd = new UnionDecl( decl->location, decl->name ); 329 347 fwd->params = decl->params; 330 pass.symtab.addUnion( fwd );331 } 332 333 template<typename pass_t>334 static inline void addUnionFwd( pass_t &, long, const ast::UnionDecl * ) {}335 336 template<typename pass_t>337 static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addStruct( str ), void() ) {338 if ( ! pass.symtab.lookupStruct( str ) ) {339 pass.symtab.addStruct( str );348 core.symtab.addUnion( fwd ); 349 } 350 351 template<typename core_t> 352 static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {} 353 354 template<typename core_t> 355 static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) { 356 if ( ! core.symtab.lookupStruct( str ) ) { 357 core.symtab.addStruct( str ); 340 358 } 341 359 } 342 360 343 template<typename pass_t>344 static inline void addStruct( pass_t &, long, const std::string & ) {}345 346 template<typename pass_t>347 static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addUnion( str ), void() ) {348 if ( ! pass.symtab.lookupUnion( str ) ) {349 pass.symtab.addUnion( str );361 template<typename core_t> 362 static inline void addStruct( core_t &, long, const std::string & ) {} 363 364 template<typename core_t> 365 static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) { 366 if ( ! core.symtab.lookupUnion( str ) ) { 367 core.symtab.addUnion( str ); 350 368 } 351 369 } 352 370 353 template<typename pass_t>354 static inline void addUnion( pass_t &, long, const std::string & ) {}371 template<typename core_t> 372 static inline void addUnion( core_t &, long, const std::string & ) {} 355 373 356 374 #undef SYMTAB_FUNC1 357 375 #undef SYMTAB_FUNC2 358 }; 359 }; 360 }; 376 } // namespace symtab 377 378 // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType. 379 // Detect the presence of a member name `subs` and call all members appropriately 380 namespace forall { 381 // Some simple scoping rules 382 template<typename core_t> 383 static inline auto enter( core_t & core, int, const ast::ParameterizedType * type ) 384 -> decltype( core.subs, void() ) { 385 if ( ! type->forall.empty() ) core.subs.beginScope(); 386 } 387 388 template<typename core_t> 389 static inline auto enter( core_t &, long, const ast::ParameterizedType * ) {} 390 391 template<typename core_t> 392 static inline auto leave( core_t & core, int, const ast::ParameterizedType * type ) 393 -> decltype( core.subs, void() ) { 394 if ( ! type->forall.empty() ) { core.subs.endScope(); } 395 } 396 397 template<typename core_t> 398 static inline auto leave( core_t &, long, const ast::ParameterizedType * ) {} 399 400 // Get the substitution table, if present 401 template<typename core_t> 402 static inline auto subs( core_t & core, int ) -> decltype( &core.subs ) { 403 return &core.subs; 404 } 405 406 template<typename core_t> 407 static inline ast::ForallSubstitutionTable * subs( core_t &, long ) { return nullptr; } 408 409 // Replaces a TypeInstType's base TypeDecl according to the table 410 template<typename core_t> 411 static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst ) 412 -> decltype( core.subs, void() ) { 413 inst = ast::mutate_field( 414 inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) ); 415 } 416 417 template<typename core_t> 418 static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {} 419 420 } // namespace forall 421 } // namespace __pass 422 } // namespace ast -
src/AST/Print.cpp
r309d814 r4c925cd 29 29 30 30 template <typename C, typename... T> 31 constexpr auto make_array(T&&... values) -> 32 array<C,sizeof...(T)> 31 constexpr array<C,sizeof...(T)> make_array(T&&... values) 33 32 { 34 33 return array<C,sizeof...(T)>{ … … 129 128 130 129 void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) { 131 switch ( inferred.mode ) { 132 case ast::Expr::InferUnion::Empty: return; 133 case ast::Expr::InferUnion::Slots: { 134 os << indent << "with " << inferred.data.resnSlots.size() 130 if (inferred.data.resnSlots && !inferred.data.resnSlots->empty()) { 131 os << indent << "with " << inferred.data.resnSlots->size() 135 132 << " pending inference slots" << endl; 136 return; 137 } 138 case ast::Expr::InferUnion::Params: { 133 } 134 if (inferred.data.inferParams && !inferred.data.inferParams->empty()) { 139 135 os << indent << "with inferred parameters " << level << ":" << endl; 140 136 ++indent; 141 for ( const auto & i : inferred.data.inferParams ) {137 for ( const auto & i : *inferred.data.inferParams ) { 142 138 os << indent; 143 short_print( Decl::fromId( i.second.decl ));139 short_print( i.second.declptr ); 144 140 os << endl; 145 141 print( i.second.expr->inferred, level+1 ); 146 142 } 147 143 --indent; 148 return;149 }150 144 } 151 145 } … … 233 227 } 234 228 235 if ( ! short_mode && !node->assertions.empty() ) {229 if ( ! node->assertions.empty() ) { 236 230 os << endl << indent << "... with assertions" << endl; 237 231 ++indent; … … 842 836 virtual const ast::Expr * visit( const ast::CastExpr * node ) override final { 843 837 ++indent; 844 os << (node->isGenerated ? "Generated" : "Explicit") << " cast of:" << endl << indent;838 os << (node->isGenerated ? "Generated" : "Explicit") << " Cast of:" << endl << indent; 845 839 safe_print( node->arg ); 846 840 os << endl << indent-1 << "... to:"; -
src/AST/Stmt.hpp
r309d814 r4c925cd 27 27 28 28 // Must be included in *all* AST classes; should be #undef'd at the end of the file 29 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 29 #define MUTATE_FRIEND \ 30 template<typename node_t> friend node_t * mutate(const node_t * node); \ 31 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 30 32 31 33 namespace ast { … … 412 414 class ImplicitCtorDtorStmt final : public Stmt { 413 415 public: 414 readonly<Stmt> callStmt;416 ptr<Stmt> callStmt; 415 417 416 418 ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt, -
src/AST/Type.cpp
r309d814 r4c925cd 9 9 // Author : Aaron B. Moss 10 10 // Created On : Mon May 13 15:00:00 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sun Dec 15 16:56:28 201913 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Jul 23 14:16:00 2020 13 // Update Count : 5 14 14 // 15 15 … … 21 21 22 22 #include "Decl.hpp" 23 #include "ForallSubstitutor.hpp" // for substituteForall 23 24 #include "Init.hpp" 25 #include "Common/utility.h" // for copy, move 24 26 #include "InitTweak/InitTweak.h" // for getPointerBase 25 27 #include "Tuples/Tuples.h" // for isTtype … … 90 92 // GENERATED END 91 93 94 // --- ParameterizedType 95 96 void ParameterizedType::initWithSub( 97 const ParameterizedType & o, Pass< ForallSubstitutor > & sub 98 ) { 99 forall = sub.core( o.forall ); 100 } 101 92 102 // --- FunctionType 103 104 FunctionType::FunctionType( const FunctionType & o ) 105 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(), 106 isVarArgs( o.isVarArgs ) { 107 Pass< ForallSubstitutor > sub; 108 initWithSub( o, sub ); // initialize substitution map 109 returns = sub.core( o.returns ); // apply to return and parameter types 110 params = sub.core( o.params ); 111 } 93 112 94 113 namespace { … … 106 125 107 126 // --- ReferenceToType 127 128 void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) { 129 ParameterizedType::initWithSub( o, sub ); // initialize substitution 130 params = sub.core( o.params ); // apply to parameters 131 } 132 133 ReferenceToType::ReferenceToType( const ReferenceToType & o ) 134 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ), 135 hoistType( o.hoistType ) { 136 Pass< ForallSubstitutor > sub; 137 initWithSub( o, sub ); 138 } 139 108 140 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const { 109 141 assertf( aggr(), "Must have aggregate to perform lookup" ); … … 116 148 } 117 149 118 // --- StructInstType 119 120 StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q, 121 std::vector<ptr<Attribute>>&& as ) 122 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {} 123 124 bool StructInstType::isComplete() const { return base ? base->body : false; } 125 126 // --- UnionInstType 127 128 UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q, 129 std::vector<ptr<Attribute>>&& as ) 130 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {} 131 132 bool UnionInstType::isComplete() const { return base ? base->body : false; } 133 134 // --- EnumInstType 135 136 EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q, 137 std::vector<ptr<Attribute>>&& as ) 138 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {} 139 140 bool EnumInstType::isComplete() const { return base ? base->body : false; } 150 // --- SueInstType (StructInstType, UnionInstType, EnumInstType) 151 152 template<typename decl_t> 153 SueInstType<decl_t>::SueInstType( 154 const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as ) 155 : ReferenceToType( b->name, q, move(as) ), base( b ) {} 156 157 template<typename decl_t> 158 bool SueInstType<decl_t>::isComplete() const { 159 return base ? base->body : false; 160 } 161 162 template class SueInstType<StructDecl>; 163 template class SueInstType<UnionDecl>; 164 template class SueInstType<EnumDecl>; 141 165 142 166 // --- TraitInstType 143 167 144 TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,145 std::vector<ptr<Attribute>>&& as )146 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}168 TraitInstType::TraitInstType( 169 const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as ) 170 : ReferenceToType( b->name, q, move(as) ), base( b ) {} 147 171 148 172 // --- TypeInstType 173 174 TypeInstType::TypeInstType( const TypeInstType & o ) 175 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) { 176 Pass< ForallSubstitutor > sub; 177 initWithSub( o, sub ); // initialize substitution 178 base = sub.core( o.base ); // apply to base type 179 } 149 180 150 181 void TypeInstType::set_base( const TypeDecl * b ) { … … 158 189 159 190 TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q ) 160 : Type( q ), types( std::move(ts) ), members() {191 : Type( q ), types( move(ts) ), members() { 161 192 // This constructor is awkward. `TupleType` needs to contain objects so that members can be 162 193 // named, but members without initializer nodes end up getting constructors, which breaks -
src/AST/Type.hpp
r309d814 r4c925cd 9 9 // Author : Aaron B. Moss 10 10 // Created On : Thu May 9 10:00:00 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Dec 11 21:56:46 201913 // Update Count : 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Jul 23 14:15:00 2020 13 // Update Count : 6 14 14 // 15 15 … … 29 29 30 30 // Must be included in *all* AST classes; should be #undef'd at the end of the file 31 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 31 #define MUTATE_FRIEND \ 32 template<typename node_t> friend node_t * mutate(const node_t * node); \ 33 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 32 34 33 35 namespace ast { 36 37 template< typename T > class Pass; 38 39 struct ForallSubstitutor; 34 40 35 41 class Type : public Node { … … 44 50 bool is_volatile() const { return qualifiers.is_volatile; } 45 51 bool is_restrict() const { return qualifiers.is_restrict; } 46 bool is_lvalue() const { return qualifiers.is_lvalue; }47 52 bool is_mutex() const { return qualifiers.is_mutex; } 48 53 bool is_atomic() const { return qualifiers.is_atomic; } … … 51 56 Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; } 52 57 Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; } 53 Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }54 58 Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; } 55 59 Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; } … … 163 167 static const char *typeNames[]; 164 168 165 BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 169 BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 166 170 : Type(q, std::move(as)), kind(k) {} 167 171 … … 265 269 /// Base type for potentially forall-qualified types 266 270 class ParameterizedType : public Type { 271 protected: 272 /// initializes forall with substitutor 273 void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub ); 267 274 public: 268 275 using ForallList = std::vector<ptr<TypeDecl>>; … … 276 283 ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} ) 277 284 : Type(q, std::move(as)), forall() {} 285 286 // enforce use of ForallSubstitutor to copy parameterized type 287 ParameterizedType( const ParameterizedType & ) = delete; 288 289 ParameterizedType( ParameterizedType && ) = default; 290 291 // no need to change destructor, and operator= deleted in Node 278 292 279 293 private: … … 301 315 : ParameterizedType(q), returns(), params(), isVarArgs(va) {} 302 316 317 FunctionType( const FunctionType & o ); 318 303 319 /// true if either the parameters or return values contain a tttype 304 320 bool isTtype() const; … … 314 330 /// base class for types that refer to types declared elsewhere (aggregates and typedefs) 315 331 class ReferenceToType : public ParameterizedType { 332 protected: 333 /// Initializes forall and parameters based on substitutor 334 void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ); 316 335 public: 317 336 std::vector<ptr<Expr>> params; … … 319 338 bool hoistType = false; 320 339 321 ReferenceToType( const std::string& n, CV::Qualifiers q = {},322 std::vector<ptr<Attribute>> && as = {} )340 ReferenceToType( 341 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 323 342 : ParameterizedType(q, std::move(as)), params(), name(n) {} 343 344 ReferenceToType( const ReferenceToType & o ); 324 345 325 346 /// Gets aggregate declaration this type refers to … … 333 354 }; 334 355 335 /// instance of struct type 336 class StructInstType final : public ReferenceToType { 337 public: 338 readonly<StructDecl> base; 339 340 StructInstType( const std::string& n, CV::Qualifiers q = {}, 341 std::vector<ptr<Attribute>> && as = {} ) 356 // Common implementation for the SUE instance types. Not to be used directly. 357 template<typename decl_t> 358 class SueInstType final : public ReferenceToType { 359 public: 360 using base_type = decl_t; 361 readonly<decl_t> base; 362 363 SueInstType( 364 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 342 365 : ReferenceToType( n, q, std::move(as) ), base() {} 343 StructInstType( const StructDecl * b, CV::Qualifiers q = {}, 344 std::vector<ptr<Attribute>> && as = {} ); 366 367 SueInstType( 368 const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ); 345 369 346 370 bool isComplete() const override; 347 371 348 const StructDecl * aggr() const override { return base; } 349 350 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 351 private: 352 StructInstType * clone() const override { return new StructInstType{ *this }; } 353 MUTATE_FRIEND 354 }; 355 356 /// instance of union type 357 class UnionInstType final : public ReferenceToType { 358 public: 359 readonly<UnionDecl> base; 360 361 UnionInstType( const std::string& n, CV::Qualifiers q = {}, 362 std::vector<ptr<Attribute>> && as = {} ) 372 const decl_t * aggr() const override { return base; } 373 374 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 375 private: 376 SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; } 377 MUTATE_FRIEND 378 }; 379 380 /// An instance of a struct type. 381 using StructInstType = SueInstType<StructDecl>; 382 383 /// An instance of a union type. 384 using UnionInstType = SueInstType<UnionDecl>; 385 386 /// An instance of an enum type. 387 using EnumInstType = SueInstType<EnumDecl>; 388 389 /// An instance of a trait type. 390 class TraitInstType final : public ReferenceToType { 391 public: 392 readonly<TraitDecl> base; 393 394 TraitInstType( 395 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 363 396 : ReferenceToType( n, q, std::move(as) ), base() {} 364 UnionInstType( const UnionDecl * b, CV::Qualifiers q = {}, 365 std::vector<ptr<Attribute>> && as = {} ); 366 367 bool isComplete() const override; 368 369 const UnionDecl * aggr() const override { return base; } 370 371 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 372 private: 373 UnionInstType * clone() const override { return new UnionInstType{ *this }; } 374 MUTATE_FRIEND 375 }; 376 377 /// instance of enum type 378 class EnumInstType final : public ReferenceToType { 379 public: 380 readonly<EnumDecl> base; 381 382 EnumInstType( const std::string& n, CV::Qualifiers q = {}, 383 std::vector<ptr<Attribute>> && as = {} ) 384 : ReferenceToType( n, q, std::move(as) ), base() {} 385 EnumInstType( const EnumDecl * b, CV::Qualifiers q = {}, 386 std::vector<ptr<Attribute>> && as = {} ); 387 388 bool isComplete() const override; 389 390 const EnumDecl * aggr() const override { return base; } 391 392 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 393 private: 394 EnumInstType * clone() const override { return new EnumInstType{ *this }; } 395 MUTATE_FRIEND 396 }; 397 398 /// instance of trait type 399 class TraitInstType final : public ReferenceToType { 400 public: 401 readonly<TraitDecl> base; 402 403 TraitInstType( const std::string& n, CV::Qualifiers q = {}, 404 std::vector<ptr<Attribute>> && as = {} ) 405 : ReferenceToType( n, q, std::move(as) ), base() {} 406 TraitInstType( const TraitDecl * b, CV::Qualifiers q = {}, 407 std::vector<ptr<Attribute>> && as = {} ); 397 398 TraitInstType( 399 const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ); 408 400 409 401 // not meaningful for TraitInstType … … 424 416 TypeDecl::Kind kind; 425 417 426 TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 418 TypeInstType( 419 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 427 420 std::vector<ptr<Attribute>> && as = {} ) 428 421 : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {} … … 431 424 : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {} 432 425 426 TypeInstType( const TypeInstType & o ); 427 433 428 /// sets `base`, updating `kind` correctly 434 429 void set_base( const TypeDecl * ); -
src/AST/TypeEnvironment.cpp
r309d814 r4c925cd 59 59 std::copy( clz.vars.begin(), clz.vars.end(), std::ostream_iterator< std::string >( out, " " ) ); 60 60 out << ")"; 61 61 62 62 if ( clz.bound ) { 63 63 out << " -> "; … … 92 92 } 93 93 } 94 94 95 95 i = next; // go to next node even if this removed 96 96 } … … 161 161 Pass<Occurs> occur{ var, env }; 162 162 maybe_accept( ty, occur ); 163 return occur. pass.result;164 } 165 } 166 167 bool TypeEnvironment::combine( 163 return occur.core.result; 164 } 165 } 166 167 bool TypeEnvironment::combine( 168 168 const TypeEnvironment & o, OpenVarSet & open, const SymbolTable & symtab ) { 169 169 // short-circuit easy cases … … 199 199 auto st = internal_lookup( *vt ); 200 200 if ( st == env.end() ) { 201 // unbound, safe to add if occurs 201 // unbound, safe to add if occurs 202 202 if ( r.bound && occurs( r.bound, *vt, *this ) ) return false; 203 203 r.vars.emplace( *vt ); … … 266 266 } 267 267 268 bool TypeEnvironment::bindVar( 269 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 270 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 271 const SymbolTable & symtab 268 bool TypeEnvironment::bindVar( 269 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 270 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 271 const SymbolTable & symtab 272 272 ) { 273 273 // remove references from bound type, so that type variables can only bind to value types … … 286 286 ptr<Type> newType = it->bound; 287 287 reset_qualifiers( newType, typeInst->qualifiers ); 288 if ( unifyInexact( 289 newType, target, *this, need, have, open, 288 if ( unifyInexact( 289 newType, target, *this, need, have, open, 290 290 widen & WidenMode{ it->allowWidening, true }, symtab, common ) ) { 291 291 if ( common ) { … … 300 300 } 301 301 } else { 302 env.emplace_back( 302 env.emplace_back( 303 303 typeInst->name, target, widen.first && widen.second, data ); 304 304 } … … 306 306 } 307 307 308 bool TypeEnvironment::bindVarToVar( 309 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 310 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 311 WidenMode widen, const SymbolTable & symtab 308 bool TypeEnvironment::bindVarToVar( 309 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 310 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 311 WidenMode widen, const SymbolTable & symtab 312 312 ) { 313 313 auto c1 = internal_lookup( var1->name ); 314 314 auto c2 = internal_lookup( var2->name ); 315 315 316 316 // exit early if variables already bound together 317 317 if ( c1 != env.end() && c1 == c2 ) { … … 396 396 } 397 397 398 bool TypeEnvironment::mergeBound( 398 bool TypeEnvironment::mergeBound( 399 399 EqvClass & to, const EqvClass & from, OpenVarSet & open, const SymbolTable & symtab ) { 400 400 if ( from.bound ) { … … 406 406 AssertionSet need, have; 407 407 408 if ( unifyInexact( 408 if ( unifyInexact( 409 409 toType, fromType, *this, need, have, open, widen, symtab, common ) ) { 410 410 // unifies, set common type if necessary … … 424 424 } 425 425 426 bool TypeEnvironment::mergeClasses( 426 bool TypeEnvironment::mergeClasses( 427 427 ClassList::iterator to, ClassList::iterator from, OpenVarSet & open, const SymbolTable & symtab 428 428 ) { -
src/AST/TypeEnvironment.hpp
r309d814 r4c925cd 37 37 /// Adding this comparison operator significantly improves assertion satisfaction run time for 38 38 /// some cases. The current satisfaction algorithm's speed partially depends on the order of 39 /// assertions. Assertions which have fewer possible matches should appear before assertions 40 /// which have more possible matches. This seems to imply that this could be further improved 41 /// by providing an indexer as an additional argument and ordering based on the number of 39 /// assertions. Assertions which have fewer possible matches should appear before assertions 40 /// which have more possible matches. This seems to imply that this could be further improved 41 /// by providing an indexer as an additional argument and ordering based on the number of 42 42 /// matches of the same kind (object, function) for the names of the declarations. 43 43 /// 44 /// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 44 /// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 45 45 /// comparator. 46 46 /// 47 /// Note: since this compares pointers for position, minor changes in the source file that 48 /// affect memory layout can alter compilation time in unpredictable ways. For example, the 49 /// placement of a line directive can reorder type pointers with respect to each other so that 50 /// assertions are seen in different orders, causing a potentially different number of 51 /// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27 52 /// seconds by reordering line directives alone, so it would be nice to fix this comparison so 53 /// that assertions compare more consistently. I've tried to modify this to compare on mangle 54 /// name instead of type as the second comparator, but this causes some assertions to never be 47 /// Note: since this compares pointers for position, minor changes in the source file that 48 /// affect memory layout can alter compilation time in unpredictable ways. For example, the 49 /// placement of a line directive can reorder type pointers with respect to each other so that 50 /// assertions are seen in different orders, causing a potentially different number of 51 /// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27 52 /// seconds by reordering line directives alone, so it would be nice to fix this comparison so 53 /// that assertions compare more consistently. I've tried to modify this to compare on mangle 54 /// name instead of type as the second comparator, but this causes some assertions to never be 55 55 /// recorded. More investigation is needed. 56 56 struct AssertCompare { … … 86 86 void print( std::ostream &, const OpenVarSet &, Indenter indent = {} ); 87 87 88 /// Represents an equivalence class of bound type variables, optionally with the concrete type 88 /// Represents an equivalence class of bound type variables, optionally with the concrete type 89 89 /// they bind to. 90 90 struct EqvClass { … … 95 95 96 96 EqvClass() : vars(), bound(), allowWidening( true ), data() {} 97 97 98 98 /// Copy-with-bound constructor 99 EqvClass( const EqvClass & o, const Type * b ) 99 EqvClass( const EqvClass & o, const Type * b ) 100 100 : vars( o.vars ), bound( b ), allowWidening( o.allowWidening ), data( o.data ) {} 101 101 … … 142 142 void writeToSubstitution( TypeSubstitution & sub ) const; 143 143 144 template< typename node_t , enum Node::ref_type ref_t>145 int apply( ptr_base< node_t, ref_t >& type ) const {144 template< typename node_t > 145 auto apply( node_t && type ) const { 146 146 TypeSubstitution sub; 147 147 writeToSubstitution( sub ); 148 return sub.apply( type);149 } 150 151 template< typename node_t , enum Node::ref_type ref_t>152 int applyFree( ptr_base< node_t, ref_t >& type ) const {148 return sub.apply( std::forward<node_t>(type) ); 149 } 150 151 template< typename node_t > 152 auto applyFree( node_t && type ) const { 153 153 TypeSubstitution sub; 154 154 writeToSubstitution( sub ); 155 return sub.applyFree( type);155 return sub.applyFree( std::forward<node_t>(type) ); 156 156 } 157 157 … … 172 172 void addActual( const TypeEnvironment & actualEnv, OpenVarSet & openVars ); 173 173 174 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if 174 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if 175 175 /// needed. Returns false on failure. 176 bool bindVar( 177 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 178 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 176 bool bindVar( 177 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 178 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 179 179 ResolvExpr::WidenMode widen, const SymbolTable & symtab ); 180 181 /// Binds the type classes represented by `var1` and `var2` together; will add one or both 180 181 /// Binds the type classes represented by `var1` and `var2` together; will add one or both 182 182 /// classes if needed. Returns false on failure. 183 bool bindVarToVar( 184 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 185 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 183 bool bindVarToVar( 184 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 185 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 186 186 ResolvExpr::WidenMode widen, const SymbolTable & symtab ); 187 187 … … 198 198 199 199 /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails 200 bool mergeBound( 200 bool mergeBound( 201 201 EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab ); 202 202 203 203 /// Merges two type classes from local environment, returning false if fails 204 bool mergeClasses( 205 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 204 bool mergeClasses( 205 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 206 206 const SymbolTable & symtab ); 207 207 -
src/AST/TypeSubstitution.cpp
r309d814 r4c925cd 18 18 19 19 namespace ast { 20 21 22 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution"); 20 23 21 24 TypeSubstitution::TypeSubstitution() { … … 92 95 namespace { 93 96 struct EnvTrimmer { 94 ptr<TypeSubstitution>env;97 const TypeSubstitution * env; 95 98 TypeSubstitution * newEnv; 96 99 EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} … … 108 111 if ( env ) { 109 112 TypeSubstitution * newEnv = new TypeSubstitution(); 110 #if TIME_TO_CONVERT_PASSES111 113 Pass<EnvTrimmer> trimmer( env, newEnv ); 112 114 expr->accept( trimmer ); 113 #else114 (void)expr;115 (void)env;116 #endif117 115 return newEnv; 118 116 } … … 121 119 122 120 void TypeSubstitution::normalize() { 123 #if TIME_TO_CONVERT_PASSES 124 PassVisitor<Substituter> sub( *this, true ); 121 Pass<Substituter> sub( *this, true ); 125 122 do { 126 sub. pass.subCount = 0;127 sub. pass.freeOnly = true;123 sub.core.subCount = 0; 124 sub.core.freeOnly = true; 128 125 for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) { 129 i->second = i->second->acceptMutator( sub ); 130 } 131 } while ( sub.pass.subCount ); 132 #endif 133 } 134 135 #if TIME_TO_CONVERT_PASSES 136 137 Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) { 126 i->second = i->second->accept( sub ); 127 } 128 } while ( sub.core.subCount ); 129 } 130 131 const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) { 138 132 BoundVarsType::const_iterator bound = boundVars.find( inst->name ); 139 133 if ( bound != boundVars.end() ) return inst; … … 146 140 // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here. 147 141 // TODO: investigate preventing type variables from being bound to themselves in the first place. 148 if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {142 if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) { 149 143 if ( inst->name == replacement->name ) { 150 144 return inst; … … 153 147 // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl; 154 148 subCount++; 155 Type * newtype = i->second->clone(); 156 newtype->get_qualifiers() |= inst->get_qualifiers(); 157 delete inst; 158 // Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode. 159 return newtype->acceptMutator( *visitor ); 160 } // if 161 } 162 163 Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) { 149 ptr<Type> newType = i->second; // force clone if needed 150 add_qualifiers( newType, inst->qualifiers ); 151 // Note: need to recursively apply substitution to the new type because normalize does not 152 // substitute bound vars, but bound vars must be substituted when not in freeOnly mode. 153 newType = newType->accept( *visitor ); 154 return newType.release(); 155 } // if 156 } 157 158 const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) { 164 159 VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name ); 165 160 if ( i == sub.varEnv.end() ) { … … 167 162 } else { 168 163 subCount++; 169 delete nameExpr; 170 return i->second->clone(); 171 } // if 172 } 173 174 void TypeSubstitution::Substituter::premutate( Type * type ) { 164 return i->second; 165 } // if 166 } 167 168 void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) { 175 169 GuardValue( boundVars ); 176 170 // bind type variables from forall-qualifiers 177 171 if ( freeOnly ) { 178 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar) {179 boundVars.insert( (*tyvar)->name );172 for ( const TypeDecl * tyvar : ptype->forall ) { 173 boundVars.insert( tyvar->name ); 180 174 } // for 181 175 } // if 182 176 } 183 177 184 template< typename TypeClass > 185 void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) { 178 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) { 186 179 GuardValue( boundVars ); 187 180 // bind type variables from forall-qualifiers 188 181 if ( freeOnly ) { 189 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar) {190 boundVars.insert( (*tyvar)->name );182 for ( const TypeDecl * tyvar : type->forall ) { 183 boundVars.insert( tyvar->name ); 191 184 } // for 192 185 // bind type variables from generic type instantiations 193 std::list< TypeDecl* > *baseParameters = type->get_baseParameters(); 194 if ( baseParameters && ! type->parameters.empty() ) { 195 for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) { 196 boundVars.insert( (*tyvar)->name ); 197 } // for 198 } // if 199 } // if 200 } 201 202 void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) { 186 if ( auto decl = type->aggr() ) { 187 if ( ! type->params.empty() ) { 188 for ( const TypeDecl * tyvar : decl->params ) { 189 boundVars.insert( tyvar->name ); 190 } // for 191 } // if 192 } 193 } // if 194 } 195 196 void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) { 203 197 handleAggregateType( aggregateUseType ); 204 198 } 205 199 206 void TypeSubstitution::Substituter::pre mutate(UnionInstType *aggregateUseType ) {200 void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) { 207 201 handleAggregateType( aggregateUseType ); 208 202 } 209 210 #endif211 203 212 204 } // namespace ast -
src/AST/TypeSubstitution.hpp
r309d814 r4c925cd 44 44 TypeSubstitution &operator=( const TypeSubstitution &other ); 45 45 46 template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const; 47 template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const; 46 template< typename SynTreeClass > 47 struct ApplyResult { 48 // const SynTreeClass * node; 49 ast::ptr<SynTreeClass> node; 50 int count; 51 }; 52 53 template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const; 54 template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const; 48 55 49 56 template< typename node_t, enum Node::ref_type ref_t > 50 57 int apply( ptr_base< node_t, ref_t > & input ) const { 51 58 const node_t * p = input.get(); 52 intret = apply(p);53 input = p;54 return ret ;59 auto ret = apply(p); 60 input = ret.node; 61 return ret.count; 55 62 } 56 63 … … 58 65 int applyFree( ptr_base< node_t, ref_t > & input ) const { 59 66 const node_t * p = input.get(); 60 intret = applyFree(p);61 input = p;62 return ret ;67 auto ret = applyFree(p); 68 input = ret.node; 69 return ret.count; 63 70 } 64 71 … … 92 99 void initialize( const TypeSubstitution &src, TypeSubstitution &dest ); 93 100 94 template<typename pass_type>101 template<typename core_t> 95 102 friend class Pass; 96 103 … … 147 154 // PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals. 148 155 #include "Pass.hpp" 156 #include "Copy.hpp" 149 157 150 158 namespace ast { … … 152 160 // definitition must happen after PassVisitor is included so that WithGuards can be used 153 161 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> { 162 static size_t traceId; 154 163 155 164 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {} 156 165 157 #if TIME_TO_CONVERT_PASSES 158 159 Type * postmutate( TypeInstType * aggregateUseType ); 160 Expression * postmutate( NameExpr * nameExpr ); 166 const Type * postvisit( const TypeInstType * aggregateUseType ); 167 const Expr * postvisit( const NameExpr * nameExpr ); 161 168 162 169 /// Records type variable bindings from forall-statements 163 void pre mutate(Type * type );170 void previsit( const ParameterizedType * type ); 164 171 /// Records type variable bindings from forall-statements and instantiations of generic types 165 template< typename TypeClass > void handleAggregateType( TypeClass * type ); 166 167 void premutate( StructInstType * aggregateUseType ); 168 void premutate( UnionInstType * aggregateUseType ); 169 170 #endif 172 void handleAggregateType( const ReferenceToType * type ); 173 174 void previsit( const StructInstType * aggregateUseType ); 175 void previsit( const UnionInstType * aggregateUseType ); 171 176 172 177 const TypeSubstitution & sub; … … 179 184 180 185 template< typename SynTreeClass > 181 int TypeSubstitution::apply( const SynTreeClass *&input ) const {186 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const { 182 187 assert( input ); 183 188 Pass<Substituter> sub( *this, false ); 184 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) ); 185 /// std::cerr << "substitution result is: "; 186 /// newType->print( std::cerr ); 187 /// std::cerr << std::endl; 188 return sub.pass.subCount; 189 input = strict_dynamic_cast< const SynTreeClass * >( deepCopy(input)->accept( sub ) ); 190 return { input, sub.core.subCount }; 189 191 } 190 192 191 193 template< typename SynTreeClass > 192 int TypeSubstitution::applyFree( const SynTreeClass *&input ) const {194 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const { 193 195 assert( input ); 194 196 Pass<Substituter> sub( *this, true ); 195 197 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) ); 196 /// std::cerr << "substitution result is: "; 197 /// newType->print( std::cerr ); 198 /// std::cerr << std::endl; 199 return sub.pass.subCount; 198 return { input, sub.core.subCount }; 200 199 } 201 200 -
src/AST/module.mk
r309d814 r4c925cd 22 22 AST/DeclReplacer.cpp \ 23 23 AST/Expr.cpp \ 24 AST/ForallSubstitutionTable.cpp \ 24 25 AST/GenericSubstitution.cpp \ 25 26 AST/Init.cpp \ -
src/AST/porting.md
r309d814 r4c925cd 47 47 template<typename node_t> 48 48 friend node_t * mutate(const node_t * node); 49 template<typename node_t> 50 friend node_t * shallowCopy(const node_t * node); 51 or equilant. 52 * You should use the `mutate` function where possible as it avoids extra copies. 53 * If you must copy use `shallowCopy` or `deepCopy` as required. 49 54 50 55 All leaves of the `Node` inheritance tree are now declared `final` -
src/Common/Eval.cc
r309d814 r4c925cd 168 168 if (expr) { 169 169 expr->accept(ev); 170 return std::make_pair(ev. pass.value, ev.pass.valid);170 return std::make_pair(ev.core.value, ev.core.valid); 171 171 } else { 172 172 return std::make_pair(0, false); -
src/Common/ScopedMap.h
r309d814 r4c925cd 249 249 250 250 /// Gets the note at the given scope 251 Note& getNote() { return scopes.back().note; } 252 const Note& getNote() const { return scopes.back().note; } 251 253 Note& getNote( size_type i ) { return scopes[i].note; } 252 254 const Note& getNote( size_type i ) const { return scopes[i].note; } -
src/Common/Stats/Heap.cc
r309d814 r4c925cd 53 53 const size_t passes_size = sizeof(passes) / sizeof(passes[0]); 54 54 size_t passes_cnt = 1; 55 56 StatBlock stacktrace_stats[100]; 57 size_t stacktrace_stats_count = 0; 58 bool stacktrace_stats_enabled = true; 59 60 size_t trace[1000]; 61 const size_t stacktrace_max_depth = sizeof(trace) / sizeof(size_t); 62 size_t stacktrace_depth; 63 64 size_t new_stacktrace_id(const char * const name) { 65 stacktrace_stats[stacktrace_stats_count].name = name; 66 return stacktrace_stats_count++; 67 } 68 69 void stacktrace_push(size_t id) { 70 ++stacktrace_depth; 71 assertf(stacktrace_depth < stacktrace_max_depth, "Stack trace too deep: increase size of array in Heap.cc"); 72 trace[stacktrace_depth] = id; 73 } 74 75 void stacktrace_pop() { 76 assertf(stacktrace_depth > 0, "Invalid stack tracing operation: trace is empty"); 77 --stacktrace_depth; 78 } 55 79 56 80 void newPass( const char * const name ) { … … 116 140 for(size_t i = 0; i < passes_cnt; i++) { 117 141 print(passes[i], nc, total_mallocs, total_frees, overall_peak); 142 } 143 144 print('-', nct); 145 std::cerr << std::setw(nc) << "Trace"; 146 std::cerr << " | Malloc Count | Free Count | Peak Allocs |" << std::endl; 147 148 print('-', nct); 149 for (size_t i = 0; i < stacktrace_stats_count; i++) { 150 print(stacktrace_stats[i], nc, total_mallocs, total_frees, overall_peak); 118 151 } 119 152 print('-', nct); … … 188 221 = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs); 189 222 } 223 224 if ( stacktrace_stats_enabled && stacktrace_depth > 0) { 225 stacktrace_stats[trace[stacktrace_depth]].mallocs++; 226 } 190 227 return __malloc( size ); 191 228 } … … 196 233 passes[passes_cnt - 1].frees++; 197 234 passes[passes_cnt - 1].n_allocs--; 235 } 236 if ( stacktrace_stats_enabled && stacktrace_depth > 0) { 237 stacktrace_stats[trace[stacktrace_depth]].frees++; 198 238 } 199 239 return __free( ptr ); … … 208 248 = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs); 209 249 } 250 if ( stacktrace_stats_enabled && stacktrace_depth > 0) { 251 stacktrace_stats[trace[stacktrace_depth]].mallocs++; 252 } 210 253 return __calloc( nelem, size ); 211 254 } … … 218 261 passes[passes_cnt - 1].frees++; 219 262 } // if 263 if ( stacktrace_stats_enabled && stacktrace_depth > 0) { 264 stacktrace_stats[trace[stacktrace_depth]].mallocs++; 265 stacktrace_stats[trace[stacktrace_depth]].frees++; 266 } 220 267 return s; 221 268 } -
src/Common/Stats/Heap.h
r309d814 r4c925cd 20 20 void newPass( const char * const name ); 21 21 void print(); 22 23 size_t new_stacktrace_id(const char * const name); 24 void stacktrace_push(size_t id); 25 void stacktrace_pop(); 22 26 } 23 27 } -
src/CompilationState.cc
r309d814 r4c925cd 14 14 // 15 15 16 #include "config.h" 17 16 18 int 17 19 astp = false, … … 28 30 genproto = false, 29 31 deterministic_output = false, 32 useNewAST = CFA_USE_NEW_AST, 30 33 nomainp = false, 31 34 parsep = false, -
src/CompilationState.h
r309d814 r4c925cd 29 29 genproto, 30 30 deterministic_output, 31 useNewAST, 31 32 nomainp, 32 33 parsep, -
src/InitTweak/InitTweak.cc