1 /** 2 * Symbols for the back end 3 * 4 * Compiler implementation of the 5 * $(LINK2 https://www.dlang.org, D programming language). 6 * 7 * Copyright: Copyright (C) 1984-1998 by Symantec 8 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 9 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 10 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 11 * Source: https://github.com/dlang/dmd/blob/master/src/dmd/backend/symbol.d 12 */ 13 14 module dmd.backend.symbol; 15 16 version (SCPP) 17 { 18 version = COMPILE; 19 version = SCPP_HTOD; 20 } 21 version (HTOD) 22 { 23 version = COMPILE; 24 version = SCPP_HTOD; 25 } 26 version (MARS) 27 { 28 version = COMPILE; 29 enum HYDRATE = false; 30 enum DEHYDRATE = false; 31 } 32 33 version (COMPILE) 34 { 35 import core.stdc.stdio; 36 import core.stdc.stdlib; 37 import core.stdc.string; 38 39 import dmd.backend.cdef; 40 import dmd.backend.cc; 41 import dmd.backend.cgcv; 42 import dmd.backend.dlist; 43 import dmd.backend.dt; 44 import dmd.backend.dvec; 45 import dmd.backend.el; 46 import dmd.backend.global; 47 import dmd.backend.mem; 48 import dmd.backend.oper; 49 import dmd.backend.symtab; 50 import dmd.backend.ty; 51 import dmd.backend.type; 52 53 version (SCPP_HTOD) 54 { 55 import cpp; 56 import dtoken; 57 import scopeh; 58 import msgs2; 59 import parser; 60 import precomp; 61 62 extern (C++) void baseclass_free(baseclass_t *b); 63 } 64 65 66 extern (C++): 67 68 nothrow: 69 @safe: 70 71 alias MEM_PH_MALLOC = mem_malloc; 72 alias MEM_PH_CALLOC = mem_calloc; 73 alias MEM_PH_FREE = mem_free; 74 alias MEM_PH_FREEFP = mem_freefp; 75 alias MEM_PH_STRDUP = mem_strdup; 76 alias MEM_PH_REALLOC = mem_realloc; 77 alias MEM_PARF_MALLOC = mem_malloc; 78 alias MEM_PARF_CALLOC = mem_calloc; 79 alias MEM_PARF_REALLOC = mem_realloc; 80 alias MEM_PARF_FREE = mem_free; 81 alias MEM_PARF_STRDUP = mem_strdup; 82 83 version (SCPP_HTOD) 84 enum mBP = 0x20; 85 else 86 import dmd.backend.code_x86; 87 88 void struct_free(struct_t *st) { } 89 90 @trusted 91 func_t* func_calloc() 92 { 93 func_t* f = cast(func_t *) calloc(1, func_t.sizeof); 94 if (!f) 95 err_nomem(); 96 return f; 97 } 98 99 @trusted 100 void func_free(func_t* f) { free(f); } 101 102 /******************************* 103 * Type out symbol information. 104 */ 105 @trusted 106 void symbol_print(const Symbol *s) 107 { 108 debug 109 { 110 version (COMPILE) 111 { 112 if (!s) return; 113 printf("symbol %p '%s'\n ",s,s.Sident.ptr); 114 printf(" Sclass = %s ", class_str(s.Sclass)); 115 printf(" Ssymnum = %d",cast(int)s.Ssymnum); 116 printf(" Sfl = "); WRFL(cast(FL) s.Sfl); 117 printf(" Sseg = %d\n",s.Sseg); 118 // printf(" Ssize = x%02x\n",s.Ssize); 119 printf(" Soffset = x%04llx",cast(ulong)s.Soffset); 120 printf(" Sweight = %d",s.Sweight); 121 printf(" Sflags = x%04x",cast(uint)s.Sflags); 122 printf(" Sxtrnnum = %d\n",s.Sxtrnnum); 123 printf(" Stype = %p",s.Stype); 124 version (SCPP_HTOD) 125 { 126 printf(" Ssequence = %x", s.Ssequence); 127 printf(" Scover = %p", s.Scover); 128 } 129 printf(" Sl = %p",s.Sl); 130 printf(" Sr = %p\n",s.Sr); 131 if (s.Sscope) 132 printf(" Sscope = '%s'\n",s.Sscope.Sident.ptr); 133 if (s.Stype) 134 type_print(s.Stype); 135 if (s.Sclass == SC.member || s.Sclass == SC.field) 136 { 137 printf(" Smemoff =%5lld", cast(long)s.Smemoff); 138 printf(" Sbit =%3d",s.Sbit); 139 printf(" Swidth =%3d\n",s.Swidth); 140 } 141 version (SCPP_HTOD) 142 { 143 if (s.Sclass == SC.struct_) 144 { 145 printf(" Svbptr = %p, Svptr = %p\n",s.Sstruct.Svbptr,s.Sstruct.Svptr); 146 } 147 } 148 } 149 } 150 } 151 152 153 /********************************* 154 * Terminate use of symbol table. 155 */ 156 157 private __gshared Symbol *keep; 158 159 @trusted 160 void symbol_term() 161 { 162 symbol_free(keep); 163 } 164 165 /**************************************** 166 * Keep symbol around until symbol_term(). 167 */ 168 169 static if (TERMCODE) 170 { 171 172 void symbol_keep(Symbol *s) 173 { 174 symbol_debug(s); 175 s.Sr = keep; // use Sr so symbol_free() doesn't nest 176 keep = s; 177 } 178 179 } 180 181 /**************************************** 182 * Return alignment of symbol. 183 */ 184 @trusted 185 int Symbol_Salignsize(ref Symbol s) 186 { 187 if (s.Salignment > 0) 188 return s.Salignment; 189 int alignsize = type_alignsize(s.Stype); 190 191 /* Reduce alignment faults when SIMD vectors 192 * are reinterpreted cast to other types with less alignment. 193 */ 194 if (config.fpxmmregs && alignsize < 16 && 195 s.Sclass == SC.auto_ && 196 type_size(s.Stype) == 16) 197 { 198 alignsize = 16; 199 } 200 201 return alignsize; 202 } 203 204 /**************************************** 205 * Aver if Symbol is not only merely dead, but really most sincerely dead. 206 * Params: 207 * anyInlineAsm = true if there's any inline assembler code 208 * Returns: 209 * true if symbol is dead. 210 */ 211 212 @trusted 213 bool Symbol_Sisdead(const ref Symbol s, bool anyInlineAsm) 214 { 215 version (MARS) 216 enum vol = false; 217 else 218 enum vol = true; 219 return s.Sflags & SFLdead || 220 /* SFLdead means the optimizer found no references to it. 221 * The rest deals with variables that the compiler never needed 222 * to read from memory because they were cached in registers, 223 * and so no memory needs to be allocated for them. 224 * Code that does write those variables to memory gets NOPed out 225 * during address assignment. 226 */ 227 (!anyInlineAsm && !(s.Sflags & SFLread) && s.Sflags & SFLunambig && 228 229 // mTYvolatile means this variable has been reference by a nested function 230 (vol || !(s.Stype.Tty & mTYvolatile)) && 231 232 (config.flags4 & CFG4optimized || !config.fulltypes)); 233 } 234 235 /**************************************** 236 * Determine if symbol needs a 'this' pointer. 237 */ 238 239 @trusted 240 int Symbol_needThis(const ref Symbol s) 241 { 242 //printf("needThis() '%s'\n", Sident.ptr); 243 244 debug assert(isclassmember(&s)); 245 246 if (s.Sclass == SC.member || s.Sclass == SC.field) 247 return 1; 248 if (tyfunc(s.Stype.Tty) && !(s.Sfunc.Fflags & Fstatic)) 249 return 1; 250 return 0; 251 } 252 253 /************************************ 254 * Determine if `s` may be affected if an assignment is done through 255 * a pointer. 256 * Params: 257 * s = symbol to check 258 * Returns: 259 * true if it may be modified by assignment through a pointer 260 */ 261 262 bool Symbol_isAffected(const ref Symbol s) 263 { 264 //printf("s: %s %d\n", s.Sident.ptr, !(s.Sflags & SFLunambig) && !(s.ty() & (mTYconst | mTYimmutable))); 265 //symbol_print(s); 266 267 /* If nobody took its address and it's not statically allocated, 268 * then it is not accessible via pointer and so is not affected. 269 */ 270 if (s.Sflags & SFLunambig) 271 return false; 272 273 /* If it's immutable, it can't be affected. 274 * 275 * Disable this check because: 276 * 1. Symbol_isAffected is not used by copyprop() and should be. 277 * 2. Non-@safe functions can temporarilly cast away immutable. 278 * 3. Need to add an @safe flag to funcsym_p to enable this. 279 * 4. Const can be mutated by a separate view. 280 * Address this in a separate PR. 281 */ 282 static if (0) 283 if (s.ty() & (mTYconst | mTYimmutable)) 284 { 285 /* Disabled for the moment because even @safe functions 286 * may have inlined unsafe code from other functions 287 */ 288 if (funcsym_p.Sfunc.Fflags3 & F3safe && 289 s.ty() & mTYimmutable) 290 { 291 return false; 292 } 293 } 294 return true; 295 } 296 297 298 /*********************************** 299 * Get user name of symbol. 300 */ 301 302 @trusted 303 const(char)* symbol_ident(const Symbol *s) 304 { 305 version (SCPP_HTOD) 306 { 307 __gshared char* noname = cast(char*)"__unnamed".ptr; 308 switch (s.Sclass) 309 { case SC.struct_: 310 if (s.Sstruct.Salias) 311 return s.Sstruct.Salias.Sident.ptr; 312 else if (s.Sstruct.Sflags & STRnotagname) 313 return noname; 314 break; 315 case SC.enum_: 316 if (CPP) 317 { if (s.Senum.SEalias) 318 return s.Senum.SEalias.Sident.ptr; 319 else if (s.Senum.SEflags & SENnotagname) 320 return noname; 321 } 322 break; 323 324 case SC.namespace: 325 if (s.Sident[0] == '?' && s.Sident.ptr[1] == '%') 326 return cast(char*)"unique".ptr; // an unnamed namespace 327 break; 328 329 default: 330 break; 331 } 332 } 333 return s.Sident.ptr; 334 } 335 336 /**************************************** 337 * Create a new symbol. 338 */ 339 340 @trusted 341 extern (C) 342 Symbol * symbol_calloc(const(char)[] id) 343 { 344 //printf("sizeof(symbol)=%d, sizeof(s.Sident)=%d, len=%d\n", symbol.sizeof, s.Sident.sizeof, cast(int)id.length); 345 Symbol* s = cast(Symbol *) mem_fmalloc(Symbol.sizeof - Symbol.Sident.length + id.length + 1 + 5); 346 memset(s,0,Symbol.sizeof - s.Sident.length); 347 version (SCPP_HTOD) 348 { 349 s.Ssequence = pstate.STsequence; 350 pstate.STsequence += 1; 351 //if (s.Ssequence == 0x21) *cast(char*)0=0; 352 } 353 memcpy(s.Sident.ptr,id.ptr,id.length); 354 s.Sident.ptr[id.length] = 0; 355 s.Ssymnum = SYMIDX.max; 356 if (debugy) 357 printf("symbol_calloc('%s') = %p\n",s.Sident.ptr,s); 358 debug s.id = Symbol.IDsymbol; 359 return s; 360 } 361 362 /**************************************** 363 * Create a Symbol 364 * Params: 365 * name = name to give the Symbol 366 * type = type for the Symbol 367 * Returns: 368 * created Symbol 369 */ 370 371 @trusted 372 extern (C) 373 Symbol * symbol_name(const(char)[] name, SC sclass, type *t) 374 { 375 type_debug(t); 376 Symbol *s = symbol_calloc(name); 377 s.Sclass = sclass; 378 s.Stype = t; 379 s.Stype.Tcount++; 380 381 if (tyfunc(t.Tty)) 382 symbol_func(s); 383 return s; 384 } 385 386 /**************************************** 387 * Create a symbol that is an alias to another function symbol. 388 */ 389 390 @trusted 391 Funcsym *symbol_funcalias(Funcsym *sf) 392 { 393 symbol_debug(sf); 394 assert(tyfunc(sf.Stype.Tty)); 395 if (sf.Sclass == SC.funcalias) 396 sf = sf.Sfunc.Falias; 397 auto s = cast(Funcsym *)symbol_name(sf.Sident.ptr[0 .. strlen(sf.Sident.ptr)],SC.funcalias,sf.Stype); 398 s.Sfunc.Falias = sf; 399 400 version (SCPP_HTOD) 401 s.Scover = sf.Scover; 402 403 return s; 404 } 405 406 /**************************************** 407 * Create a symbol, give it a name, storage class and type. 408 */ 409 410 @trusted 411 Symbol * symbol_generate(SC sclass,type *t) 412 { 413 __gshared int tmpnum; 414 char[4 + tmpnum.sizeof * 3 + 1] name; 415 416 //printf("symbol_generate(_TMP%d)\n", tmpnum); 417 const length = snprintf(name.ptr,name.length,"_TMP%d",tmpnum++); 418 Symbol *s = symbol_name(name.ptr[0 .. length],sclass,t); 419 //symbol_print(s); 420 421 version (MARS) 422 s.Sflags |= SFLnodebug | SFLartifical; 423 424 return s; 425 } 426 427 /**************************************** 428 * Generate an auto symbol, and add it to the symbol table. 429 */ 430 431 Symbol * symbol_genauto(type *t) 432 { Symbol *s; 433 434 s = symbol_generate(SC.auto_,t); 435 version (SCPP_HTOD) 436 { 437 //printf("symbol_genauto(t) '%s'\n", s.Sident.ptr); 438 if (pstate.STdefertemps) 439 { symbol_keep(s); 440 s.Ssymnum = SYMIDX.max; 441 } 442 else 443 { s.Sflags |= SFLfree; 444 if (init_staticctor) 445 { // variable goes into _STI_xxxx 446 s.Ssymnum = SYMIDX.max; // deferred allocation 447 //printf("test2\n"); 448 //if (s.Sident[4] == '2') *(char*)0=0; 449 } 450 else 451 { 452 symbol_add(s); 453 } 454 } 455 } 456 else 457 { 458 s.Sflags |= SFLfree; 459 symbol_add(s); 460 } 461 return s; 462 } 463 464 /****************************************** 465 * Generate symbol into which we can copy the contents of expression e. 466 */ 467 468 Symbol *symbol_genauto(elem *e) 469 { 470 return symbol_genauto(type_fake(e.Ety)); 471 } 472 473 /****************************************** 474 * Generate symbol into which we can copy the contents of expression e. 475 */ 476 477 Symbol *symbol_genauto(tym_t ty) 478 { 479 return symbol_genauto(type_fake(ty)); 480 } 481 482 /**************************************** 483 * Add in the variants for a function symbol. 484 */ 485 486 @trusted 487 void symbol_func(Symbol *s) 488 { 489 //printf("symbol_func(%s, x%x)\n", s.Sident.ptr, fregsaved); 490 symbol_debug(s); 491 s.Sfl = FLfunc; 492 // Interrupt functions modify all registers 493 // BUG: do interrupt functions really save BP? 494 // Note that fregsaved may not be set yet 495 s.Sregsaved = (s.Stype && tybasic(s.Stype.Tty) == TYifunc) ? cast(regm_t) mBP : fregsaved; 496 s.Sseg = UNKNOWN; // don't know what segment it is in 497 if (!s.Sfunc) 498 s.Sfunc = func_calloc(); 499 } 500 501 /*************************************** 502 * Add a field to a struct s. 503 * Params: 504 * s = the struct symbol 505 * name = field name 506 * t = the type of the field 507 * offset = offset of the field 508 */ 509 510 @trusted 511 void symbol_struct_addField(Symbol *s, const(char)* name, type *t, uint offset) 512 { 513 Symbol *s2 = symbol_name(name[0 .. strlen(name)], SC.member, t); 514 s2.Smemoff = offset; 515 list_append(&s.Sstruct.Sfldlst, s2); 516 } 517 518 /*************************************** 519 * Add a bit field to a struct s. 520 * Params: 521 * s = the struct symbol 522 * name = field name 523 * t = the type of the field 524 * offset = offset of the field 525 * fieldWidth = width of bit field 526 * bitOffset = bit number of start of field 527 */ 528 529 @trusted 530 void symbol_struct_addBitField(Symbol *s, const(char)* name, type *t, uint offset, uint fieldWidth, uint bitOffset) 531 { 532 //printf("symbol_struct_addBitField() s: %s\n", s.Sident.ptr); 533 Symbol *s2 = symbol_name(name[0 .. strlen(name)], SC.field, t); 534 s2.Smemoff = offset; 535 s2.Swidth = cast(ubyte)fieldWidth; 536 s2.Sbit = cast(ubyte)bitOffset; 537 list_append(&s.Sstruct.Sfldlst, s2); 538 symbol_struct_hasBitFields(s); 539 } 540 541 /*************************************** 542 * Mark struct s as having bit fields 543 * Params: 544 * s = the struct symbol 545 */ 546 @trusted 547 void symbol_struct_hasBitFields(Symbol *s) 548 { 549 s.Sstruct.Sflags |= STRbitfields; 550 } 551 552 /*************************************** 553 * Add a base class to a struct s. 554 * Input: 555 * s the struct/class symbol 556 * t the type of the base class 557 * offset offset of the base class in the struct/class 558 */ 559 560 @trusted 561 void symbol_struct_addBaseClass(Symbol *s, type *t, uint offset) 562 { 563 assert(t && t.Tty == TYstruct); 564 auto bc = cast(baseclass_t*)mem_fmalloc(baseclass_t.sizeof); 565 bc.BCbase = t.Ttag; 566 bc.BCoffset = offset; 567 bc.BCnext = s.Sstruct.Sbase; 568 s.Sstruct.Sbase = bc; 569 } 570 571 /******************************** 572 * Define symbol in specified symbol table. 573 * Returns: 574 * pointer to symbol 575 */ 576 577 version (SCPP_HTOD) 578 { 579 Symbol * defsy(const(char)* p,Symbol **parent) 580 { 581 Symbol *s = symbol_calloc(p[0 .. strlen(p)]); 582 symbol_addtotree(parent,s); 583 return s; 584 } 585 } 586 587 /******************************** 588 * Check integrity of symbol data structure. 589 */ 590 591 debug 592 { 593 594 void symbol_check(const Symbol *s) 595 { 596 //printf("symbol_check('%s',%p)\n",s.Sident.ptr,s); 597 symbol_debug(s); 598 if (s.Stype) type_debug(s.Stype); 599 assert(cast(uint)s.Sclass < cast(uint)SCMAX); 600 version (SCPP_HTOD) 601 { 602 if (s.Sscope) 603 symbol_check(s.Sscope); 604 if (s.Scover) 605 symbol_check(s.Scover); 606 } 607 } 608 609 void symbol_tree_check(const(Symbol)* s) 610 { 611 while (s) 612 { symbol_check(s); 613 symbol_tree_check(s.Sl); 614 s = s.Sr; 615 } 616 } 617 618 } 619 620 /******************************** 621 * Insert symbol in specified symbol table. 622 */ 623 624 version (SCPP_HTOD) 625 { 626 627 void symbol_addtotree(Symbol **parent,Symbol *s) 628 { Symbol *rover; 629 byte cmp; 630 size_t len; 631 const(char)* p; 632 char c; 633 634 //printf("symbol_addtotree('%s',%p)\n",s.Sident.ptr,*parent); 635 debug 636 { 637 symbol_tree_check(*parent); 638 assert(!s.Sl && !s.Sr); 639 } 640 symbol_debug(s); 641 p = s.Sident.ptr; 642 c = *p; 643 len = strlen(p); 644 p++; 645 rover = *parent; 646 while (rover != null) // while we haven't run out of tree 647 { symbol_debug(rover); 648 if ((cmp = cast(byte)(c - rover.Sident[0])) == 0) 649 { cmp = cast(byte)memcmp(p,rover.Sident.ptr + 1,len); // compare identifier strings 650 if (cmp == 0) // found it if strings match 651 { 652 if (CPP) 653 { Symbol *s2; 654 655 switch (rover.Sclass) 656 { case SC.struct_: 657 s2 = rover; 658 goto case_struct; 659 660 case_struct: 661 if (s2.Sstruct.Sctor && 662 !(s2.Sstruct.Sctor.Sfunc.Fflags & Fgen)) 663 cpperr(EM_ctor_disallowed,p); // no ctor allowed for class rover 664 s2.Sstruct.Sflags |= STRnoctor; 665 goto case_cover; 666 667 case_cover: 668 // Replace rover with the new symbol s, and 669 // have s 'cover' the tag symbol s2. 670 // BUG: memory leak on rover if s2!=rover 671 assert(!s2.Scover); 672 s.Sl = rover.Sl; 673 s.Sr = rover.Sr; 674 s.Scover = s2; 675 *parent = s; 676 rover.Sl = rover.Sr = null; 677 return; 678 679 case SC.enum_: 680 s2 = rover; 681 goto case_cover; 682 683 case SC.template_: 684 s2 = rover; 685 s2.Stemplate.TMflags |= STRnoctor; 686 goto case_cover; 687 688 case SC.alias_: 689 s2 = rover.Smemalias; 690 if (s2.Sclass == SC.struct_) 691 goto case_struct; 692 if (s2.Sclass == SC.enum_) 693 goto case_cover; 694 break; 695 696 default: 697 break; 698 } 699 } 700 synerr(EM_multiple_def,p - 1); // symbol is already defined 701 //symbol_undef(s); // undefine the symbol 702 return; 703 } 704 } 705 parent = (cmp < 0) ? /* if we go down left side */ 706 &(rover.Sl) : /* then get left child */ 707 &(rover.Sr); /* else get right child */ 708 rover = *parent; /* get child */ 709 } 710 /* not in table, so insert into table */ 711 *parent = s; /* link new symbol into tree */ 712 } 713 } 714 715 /************************************* 716 * Search for symbol in multiple symbol tables, 717 * starting with most recently nested one. 718 * Input: 719 * p . identifier string 720 * Returns: 721 * pointer to symbol 722 * null if couldn't find it 723 */ 724 725 static if (0) 726 { 727 Symbol * lookupsym(const(char)* p) 728 { 729 return scope_search(p,SCTglobal | SCTlocal); 730 } 731 } 732 733 /************************************* 734 * Search for symbol in symbol table. 735 * Input: 736 * p . identifier string 737 * rover . where to start looking 738 * Returns: 739 * pointer to symbol (null if not found) 740 */ 741 742 version (SCPP_HTOD) 743 { 744 745 Symbol * findsy(const(char)* p,Symbol *rover) 746 { 747 /+ 748 #if TX86 && __DMC__ 749 volatile int len; 750 __asm 751 { 752 #if !_WIN32 753 push DS 754 pop ES 755 #endif 756 mov EDI,p 757 xor AL,AL 758 759 mov BL,[EDI] 760 mov ECX,-1 761 762 repne scasb 763 764 not ECX 765 mov EDX,p 766 767 dec ECX 768 inc EDX 769 770 mov len,ECX 771 mov AL,BL 772 773 mov EBX,rover 774 mov ESI,EDX 775 776 test EBX,EBX 777 je L6 778 779 cmp AL,symbol.Sident[EBX] 780 js L2 781 782 lea EDI,symbol.Sident+1[EBX] 783 je L5 784 785 mov EBX,symbol.Sr[EBX] 786 jmp L3 787 788 L1: mov ECX,len 789 L2: mov EBX,symbol.Sl[EBX] 790 791 L3: test EBX,EBX 792 je L6 793 794 L4: cmp AL,symbol.Sident[EBX] 795 js L2 796 797 lea EDI,symbol.Sident+1[EBX] 798 je L5 799 800 mov EBX,symbol.Sr[EBX] 801 jmp L3 802 803 L5: rep cmpsb 804 805 mov ESI,EDX 806 js L1 807 808 je L6 809 810 mov EBX,symbol.Sr[EBX] 811 mov ECX,len 812 813 test EBX,EBX 814 jne L4 815 816 L6: mov EAX,EBX 817 } 818 #else 819 +/ 820 size_t len; 821 byte cmp; /* set to value of strcmp */ 822 char c = *p; 823 824 len = strlen(p); 825 p++; // will pick up 0 on memcmp 826 while (rover != null) // while we haven't run out of tree 827 { symbol_debug(rover); 828 if ((cmp = cast(byte)(c - rover.Sident[0])) == 0) 829 { cmp = cast(byte)memcmp(p,rover.Sident.ptr + 1,len); /* compare identifier strings */ 830 if (cmp == 0) 831 return rover; /* found it if strings match */ 832 } 833 rover = (cmp < 0) ? rover.Sl : rover.Sr; 834 } 835 return rover; // failed to find it 836 //#endif 837 } 838 839 } 840 841 /*********************************** 842 * Create a new symbol table. 843 */ 844 845 version (SCPP_HTOD) 846 { 847 848 void createglobalsymtab() 849 { 850 assert(!scope_end); 851 if (CPP) 852 scope_push(null,cast(scope_fp)&findsy, SCTcglobal); 853 else 854 scope_push(null,cast(scope_fp)&findsy, SCTglobaltag); 855 scope_push(null,cast(scope_fp)&findsy, SCTglobal); 856 } 857 858 859 void createlocalsymtab() 860 { 861 assert(scope_end); 862 if (!CPP) 863 scope_push(null,cast(scope_fp)&findsy, SCTtag); 864 scope_push(null,cast(scope_fp)&findsy, SCTlocal); 865 } 866 867 868 /*********************************** 869 * Delete current symbol table and back up one. 870 */ 871 872 void deletesymtab() 873 { Symbol *root; 874 875 root = cast(Symbol *)scope_pop(); 876 if (root) 877 { 878 if (funcsym_p) 879 list_prepend(&funcsym_p.Sfunc.Fsymtree,root); 880 else 881 symbol_free(root); // free symbol table 882 } 883 884 if (!CPP) 885 { 886 root = cast(Symbol *)scope_pop(); 887 if (root) 888 { 889 if (funcsym_p) 890 list_prepend(&funcsym_p.Sfunc.Fsymtree,root); 891 else 892 symbol_free(root); // free symbol table 893 } 894 } 895 } 896 897 } 898 899 /********************************* 900 * Delete symbol from symbol table, taking care to delete 901 * all children of a symbol. 902 * Make sure there are no more forward references (labels, tags). 903 * Input: 904 * pointer to a symbol 905 */ 906 907 @trusted 908 void meminit_free(meminit_t *m) /* helper for symbol_free() */ 909 { 910 list_free(&m.MIelemlist,cast(list_free_fp)&el_free); 911 MEM_PARF_FREE(m); 912 } 913 914 @trusted 915 void symbol_free(Symbol *s) 916 { 917 while (s) /* if symbol exists */ 918 { Symbol *sr; 919 920 debug 921 { 922 if (debugy) 923 printf("symbol_free('%s',%p)\n",s.Sident.ptr,s); 924 symbol_debug(s); 925 assert(/*s.Sclass != SC.unde &&*/ cast(int) s.Sclass < cast(int) SCMAX); 926 } 927 { type *t = s.Stype; 928 929 if (t) 930 type_debug(t); 931 if (t && tyfunc(t.Tty) && s.Sfunc) 932 { 933 func_t *f = s.Sfunc; 934 935 debug assert(f); 936 blocklist_free(&f.Fstartblock); 937 freesymtab(f.Flocsym[].ptr,0,f.Flocsym.length); 938 939 f.Flocsym.dtor(); 940 if (CPP) 941 { 942 if (f.Fflags & Fnotparent) 943 { debug if (debugy) printf("not parent, returning\n"); 944 return; 945 } 946 947 /* We could be freeing the symbol before its class is */ 948 /* freed, so remove it from the class's field list */ 949 if (f.Fclass) 950 { list_t tl; 951 952 symbol_debug(f.Fclass); 953 tl = list_inlist(f.Fclass.Sstruct.Sfldlst,s); 954 if (tl) 955 list_setsymbol(tl, null); 956 } 957 958 if (f.Foversym && f.Foversym.Sfunc) 959 { f.Foversym.Sfunc.Fflags &= ~Fnotparent; 960 f.Foversym.Sfunc.Fclass = null; 961 symbol_free(f.Foversym); 962 } 963 964 if (f.Fexplicitspec) 965 symbol_free(f.Fexplicitspec); 966 967 /* If operator function, remove from list of such functions */ 968 if (f.Fflags & Foperator) 969 { assert(f.Foper && f.Foper < OPMAX); 970 //if (list_inlist(cpp_operfuncs[f.Foper],s)) 971 // list_subtract(&cpp_operfuncs[f.Foper],s); 972 } 973 974 list_free(&f.Fclassfriends,FPNULL); 975 list_free(&f.Ffwdrefinstances,FPNULL); 976 param_free(&f.Farglist); 977 param_free(&f.Fptal); 978 list_free(&f.Fexcspec,cast(list_free_fp)&type_free); 979 980 version (SCPP_HTOD) 981 token_free(f.Fbody); 982 983 el_free(f.Fbaseinit); 984 if (f.Fthunk && !(f.Fflags & Finstance)) 985 MEM_PH_FREE(f.Fthunk); 986 list_free(&f.Fthunks,cast(list_free_fp)&symbol_free); 987 } 988 list_free(&f.Fsymtree,cast(list_free_fp)&symbol_free); 989 version (MARS) 990 f.typesTable.dtor(); 991 func_free(f); 992 } 993 switch (s.Sclass) 994 { 995 version (SCPP_HTOD) 996 { 997 case SC.label: 998 if (!s.Slabel) 999 synerr(EM_unknown_label,s.Sident.ptr); 1000 break; 1001 } 1002 case SC.struct_: 1003 version (SCPP_HTOD) 1004 { 1005 if (CPP) 1006 { 1007 struct_t *st = s.Sstruct; 1008 assert(st); 1009 list_free(&st.Sclassfriends,FPNULL); 1010 list_free(&st.Sfriendclass,FPNULL); 1011 list_free(&st.Sfriendfuncs,FPNULL); 1012 list_free(&st.Scastoverload,FPNULL); 1013 list_free(&st.Sopoverload,FPNULL); 1014 list_free(&st.Svirtual,&MEM_PH_FREEFP); 1015 list_free(&st.Sfldlst,FPNULL); 1016 symbol_free(st.Sroot); 1017 baseclass_t* b,bn; 1018 1019 for (b = st.Sbase; b; b = bn) 1020 { bn = b.BCnext; 1021 list_free(&b.BCpublics,FPNULL); 1022 baseclass_free(b); 1023 } 1024 for (b = st.Svirtbase; b; b = bn) 1025 { bn = b.BCnext; 1026 baseclass_free(b); 1027 } 1028 for (b = st.Smptrbase; b; b = bn) 1029 { bn = b.BCnext; 1030 list_free(&b.BCmptrlist,&MEM_PH_FREEFP); 1031 baseclass_free(b); 1032 } 1033 for (b = st.Svbptrbase; b; b = bn) 1034 { bn = b.BCnext; 1035 baseclass_free(b); 1036 } 1037 param_free(&st.Sarglist); 1038 param_free(&st.Spr_arglist); 1039 struct_free(st); 1040 } 1041 } 1042 if (!CPP) 1043 { 1044 debug if (debugy) 1045 printf("freeing members %p\n",s.Sstruct.Sfldlst); 1046 1047 list_free(&s.Sstruct.Sfldlst,FPNULL); 1048 symbol_free(s.Sstruct.Sroot); 1049 struct_free(s.Sstruct); 1050 } 1051 static if (0) /* Don't complain anymore about these, ANSI C says */ 1052 { 1053 /* it's ok */ 1054 if (t && t.Tflags & TFsizeunknown) 1055 synerr(EM_unknown_tag,s.Sident.ptr); 1056 } 1057 break; 1058 case SC.enum_: 1059 /* The actual member symbols are either in a local */ 1060 /* table or on the member list of a class, so we */ 1061 /* don't free them here. */ 1062 assert(s.Senum); 1063 list_free(&s.Senum.SEenumlist,FPNULL); 1064 MEM_PH_FREE(s.Senum); 1065 s.Senum = null; 1066 break; 1067 1068 version (SCPP_HTOD) 1069 { 1070 case SC.template_: 1071 { template_t *tm = s.Stemplate; 1072 1073 list_free(&tm.TMinstances,FPNULL); 1074 list_free(&tm.TMmemberfuncs,cast(list_free_fp)&tmf_free); 1075 list_free(&tm.TMexplicit,cast(list_free_fp)&tme_free); 1076 list_free(&tm.TMnestedexplicit,cast(list_free_fp)&tmne_free); 1077 list_free(&tm.TMnestedfriends,cast(list_free_fp)&tmnf_free); 1078 param_free(&tm.TMptpl); 1079 param_free(&tm.TMptal); 1080 token_free(tm.TMbody); 1081 symbol_free(tm.TMpartial); 1082 list_free(&tm.TMfriends,FPNULL); 1083 MEM_PH_FREE(tm); 1084 break; 1085 } 1086 case SC.namespace: 1087 symbol_free(s.Snameroot); 1088 list_free(&s.Susing,FPNULL); 1089 break; 1090 1091 case SC.memalias: 1092 case SC.funcalias: 1093 case SC.adl: 1094 list_free(&s.Spath,FPNULL); 1095 break; 1096 } 1097 case SC.parameter: 1098 case SC.regpar: 1099 case SC.fastpar: 1100 case SC.shadowreg: 1101 case SC.register: 1102 case SC.auto_: 1103 vec_free(s.Srange); 1104 static if (0) 1105 { 1106 goto case SC.const_; 1107 case SC.const_: 1108 if (s.Sflags & (SFLvalue | SFLdtorexp)) 1109 el_free(s.Svalue); 1110 } 1111 break; 1112 default: 1113 break; 1114 } 1115 if (s.Sflags & (SFLvalue | SFLdtorexp)) 1116 el_free(s.Svalue); 1117 if (s.Sdt) 1118 dt_free(s.Sdt); 1119 type_free(t); 1120 symbol_free(s.Sl); 1121 version (SCPP_HTOD) 1122 { 1123 if (s.Scover) 1124 symbol_free(s.Scover); 1125 } 1126 sr = s.Sr; 1127 debug 1128 { 1129 s.id = 0; 1130 } 1131 mem_ffree(s); 1132 } 1133 s = sr; 1134 } 1135 } 1136 1137 /******************************** 1138 * Undefine a symbol. 1139 * Assume error msg was already printed. 1140 */ 1141 1142 static if (0) 1143 { 1144 private void symbol_undef(Symbol *s) 1145 { 1146 s.Sclass = SC.unde; 1147 s.Ssymnum = SYMIDX.max; 1148 type_free(s.Stype); /* free type data */ 1149 s.Stype = null; 1150 } 1151 } 1152 1153 /***************************** 1154 * Add symbol to current symbol array. 1155 */ 1156 1157 @trusted 1158 SYMIDX symbol_add(Symbol *s) 1159 { 1160 return symbol_add(*cstate.CSpsymtab, s); 1161 } 1162 1163 @trusted 1164 SYMIDX symbol_add(ref symtab_t symtab, Symbol* s) 1165 { 1166 //printf("symbol_add('%s')\n", s.Sident.ptr); 1167 debug 1168 { 1169 if (!s || !s.Sident[0]) 1170 { printf("bad symbol\n"); 1171 assert(0); 1172 } 1173 } 1174 symbol_debug(s); 1175 if (pstate.STinsizeof) 1176 { symbol_keep(s); 1177 return SYMIDX.max; 1178 } 1179 const sitop = symtab.length; 1180 symtab.setLength(sitop + 1); 1181 symtab[sitop] = s; 1182 1183 debug if (debugy) 1184 printf("symbol_add(%p '%s') = %d\n",s,s.Sident.ptr, cast(int) symtab.length); 1185 1186 debug if (s.Ssymnum != SYMIDX.max) 1187 printf("symbol %s already added\n", s.Sident.ptr); 1188 assert(s.Ssymnum == SYMIDX.max); 1189 s.Ssymnum = sitop; 1190 1191 return sitop; 1192 } 1193 1194 /******************************************** 1195 * Insert s into symtab at position n. 1196 * Returns: 1197 * position in table 1198 */ 1199 @trusted 1200 SYMIDX symbol_insert(ref symtab_t symtab, Symbol* s, SYMIDX n) 1201 { 1202 const sinew = symbol_add(s); // added at end, have to move it 1203 for (SYMIDX i = sinew; i > n; --i) 1204 { 1205 symtab[i] = symtab[i - 1]; 1206 symtab[i].Ssymnum += 1; 1207 } 1208 globsym[n] = s; 1209 s.Ssymnum = n; 1210 return n; 1211 } 1212 1213 /**************************** 1214 * Free up the symbols stab[n1 .. n2] 1215 */ 1216 1217 @trusted 1218 void freesymtab(Symbol **stab,SYMIDX n1,SYMIDX n2) 1219 { 1220 if (!stab) 1221 return; 1222 1223 debug if (debugy) 1224 printf("freesymtab(from %d to %d)\n", cast(int) n1, cast(int) n2); 1225 1226 assert(stab != globsym[].ptr || (n1 <= n2 && n2 <= globsym.length)); 1227 foreach (ref s; stab[n1 .. n2]) 1228 { 1229 if (s && s.Sflags & SFLfree) 1230 { 1231 1232 debug 1233 { 1234 if (debugy) 1235 printf("Freeing %p '%s'\n",s,s.Sident.ptr); 1236 symbol_debug(s); 1237 } 1238 s.Sl = s.Sr = null; 1239 s.Ssymnum = SYMIDX.max; 1240 symbol_free(s); 1241 s = null; 1242 } 1243 } 1244 } 1245 1246 /**************************** 1247 * Create a copy of a symbol. 1248 */ 1249 1250 @trusted 1251 Symbol * symbol_copy(Symbol *s) 1252 { Symbol *scopy; 1253 type *t; 1254 1255 symbol_debug(s); 1256 /*printf("symbol_copy(%s)\n",s.Sident.ptr);*/ 1257 scopy = symbol_calloc(s.Sident.ptr[0 .. strlen(s.Sident.ptr)]); 1258 memcpy(scopy,s,Symbol.sizeof - s.Sident.sizeof); 1259 scopy.Sl = scopy.Sr = scopy.Snext = null; 1260 scopy.Ssymnum = SYMIDX.max; 1261 if (scopy.Sdt) 1262 { 1263 auto dtb = DtBuilder(0); 1264 dtb.nzeros(cast(uint)type_size(scopy.Stype)); 1265 scopy.Sdt = dtb.finish(); 1266 } 1267 if (scopy.Sflags & (SFLvalue | SFLdtorexp)) 1268 scopy.Svalue = el_copytree(s.Svalue); 1269 t = scopy.Stype; 1270 if (t) 1271 { t.Tcount++; /* one more parent of the type */ 1272 type_debug(t); 1273 } 1274 return scopy; 1275 } 1276 1277 /******************************* 1278 * Search list for a symbol with an identifier that matches. 1279 * Returns: 1280 * pointer to matching symbol 1281 * null if not found 1282 */ 1283 1284 version (SCPP_HTOD) 1285 { 1286 1287 Symbol * symbol_searchlist(symlist_t sl,const(char)* vident) 1288 { 1289 debug 1290 int count = 0; 1291 1292 //printf("searchlist(%s)\n",vident); 1293 foreach (sln; ListRange(sl)) 1294 { 1295 Symbol* s = list_symbol(sln); 1296 symbol_debug(s); 1297 /*printf("\tcomparing with %s\n",s.Sident.ptr);*/ 1298 if (strcmp(vident,s.Sident.ptr) == 0) 1299 return s; 1300 1301 debug assert(++count < 300); /* prevent infinite loops */ 1302 } 1303 return null; 1304 } 1305 1306 /*************************************** 1307 * Search for symbol in sequence of symbol tables. 1308 * Input: 1309 * glbl !=0 if global symbol table only 1310 */ 1311 1312 Symbol *symbol_search(const(char)* id) 1313 { 1314 Scope *sc; 1315 if (CPP) 1316 { uint sct; 1317 1318 sct = pstate.STclasssym ? SCTclass : 0; 1319 sct |= SCTmfunc | SCTlocal | SCTwith | SCTglobal | SCTnspace | SCTtemparg | SCTtempsym; 1320 return scope_searchx(id,sct,&sc); 1321 } 1322 else 1323 return scope_searchx(id,SCTglobal | SCTlocal,&sc); 1324 } 1325 1326 } 1327 1328 1329 /******************************************* 1330 * Hydrate a symbol tree. 1331 */ 1332 1333 static if (HYDRATE) 1334 { 1335 @trusted 1336 void symbol_tree_hydrate(Symbol **ps) 1337 { Symbol *s; 1338 1339 while (isdehydrated(*ps)) /* if symbol is dehydrated */ 1340 { 1341 s = symbol_hydrate(ps); 1342 symbol_debug(s); 1343 if (s.Scover) 1344 symbol_hydrate(&s.Scover); 1345 symbol_tree_hydrate(&s.Sl); 1346 ps = &s.Sr; 1347 } 1348 1349 } 1350 } 1351 1352 /******************************************* 1353 * Dehydrate a symbol tree. 1354 */ 1355 1356 static if (DEHYDRATE) 1357 { 1358 @trusted 1359 void symbol_tree_dehydrate(Symbol **ps) 1360 { Symbol *s; 1361 1362 while ((s = *ps) != null && !isdehydrated(s)) /* if symbol exists */ 1363 { 1364 symbol_debug(s); 1365 symbol_dehydrate(ps); 1366 version (DEBUG_XSYMGEN) 1367 { 1368 if (xsym_gen && ph_in_head(s)) 1369 return; 1370 } 1371 symbol_dehydrate(&s.Scover); 1372 symbol_tree_dehydrate(&s.Sl); 1373 ps = &s.Sr; 1374 } 1375 } 1376 } 1377 1378 /******************************************* 1379 * Hydrate a symbol. 1380 */ 1381 1382 static if (HYDRATE) 1383 { 1384 @trusted 1385 Symbol *symbol_hydrate(Symbol **ps) 1386 { Symbol *s; 1387 1388 s = *ps; 1389 if (isdehydrated(s)) /* if symbol is dehydrated */ 1390 { type *t; 1391 struct_t *st; 1392 1393 s = cast(Symbol *) ph_hydrate(cast(void**)ps); 1394 1395 debug debugy && printf("symbol_hydrate('%s')\n",s.Sident.ptr); 1396 1397 symbol_debug(s); 1398 if (!isdehydrated(s.Stype)) // if this symbol is already dehydrated 1399 return s; // no need to do it again 1400 if (pstate.SThflag != FLAG_INPLACE && s.Sfl != FLreg) 1401 s.Sxtrnnum = 0; // not written to .OBJ file yet 1402 type_hydrate(&s.Stype); 1403 //printf("symbol_hydrate(%p, '%s', t = %p)\n",s,s.Sident.ptr,s.Stype); 1404 t = s.Stype; 1405 if (t) 1406 type_debug(t); 1407 1408 if (t && tyfunc(t.Tty) && ph_hydrate(cast(void**)&s.Sfunc)) 1409 { 1410 func_t *f = s.Sfunc; 1411 SYMIDX si; 1412 1413 debug assert(f); 1414 1415 list_hydrate(&f.Fsymtree,cast(list_free_fp)&symbol_tree_hydrate); 1416 blocklist_hydrate(&f.Fstartblock); 1417 1418 ph_hydrate(cast(void**)&f.Flocsym.tab); 1419 for (si = 0; si < f.Flocsym.length; si++) 1420 symbol_hydrate(&f.Flocsym[].ptr[si]); 1421 1422 srcpos_hydrate(&f.Fstartline); 1423 srcpos_hydrate(&f.Fendline); 1424 1425 symbol_hydrate(&f.F__func__); 1426 1427 if (CPP) 1428 { 1429 symbol_hydrate(&f.Fparsescope); 1430 Classsym_hydrate(&f.Fclass); 1431 symbol_hydrate(&f.Foversym); 1432 symbol_hydrate(&f.Fexplicitspec); 1433 symbol_hydrate(&f.Fsurrogatesym); 1434 1435 list_hydrate(&f.Fclassfriends,cast(list_free_fp)&symbol_hydrate); 1436 el_hydrate(&f.Fbaseinit); 1437 token_hydrate(&f.Fbody); 1438 symbol_hydrate(&f.Falias); 1439 list_hydrate(&f.Fthunks,cast(list_free_fp)&symbol_hydrate); 1440 if (f.Fflags & Finstance) 1441 symbol_hydrate(&f.Ftempl); 1442 else 1443 thunk_hydrate(&f.Fthunk); 1444 param_hydrate(&f.Farglist); 1445 param_hydrate(&f.Fptal); 1446 list_hydrate(&f.Ffwdrefinstances,cast(list_free_fp)&symbol_hydrate); 1447 list_hydrate(&f.Fexcspec,cast(list_free_fp)&type_hydrate); 1448 } 1449 } 1450 if (CPP) 1451 symbol_hydrate(&s.Sscope); 1452 switch (s.Sclass) 1453 { 1454 case SC.struct_: 1455 if (CPP) 1456 { 1457 st = cast(struct_t *) ph_hydrate(cast(void**)&s.Sstruct); 1458 assert(st); 1459 symbol_tree_hydrate(&st.Sroot); 1460 ph_hydrate(cast(void**)&st.Spvirtder); 1461 list_hydrate(&st.Sfldlst,cast(list_free_fp)&symbol_hydrate); 1462 list_hydrate(&st.Svirtual,cast(list_free_fp)&mptr_hydrate); 1463 list_hydrate(&st.Sopoverload,cast(list_free_fp)&symbol_hydrate); 1464 list_hydrate(&st.Scastoverload,cast(list_free_fp)&symbol_hydrate); 1465 list_hydrate(&st.Sclassfriends,cast(list_free_fp)&symbol_hydrate); 1466 list_hydrate(&st.Sfriendclass,cast(list_free_fp)&symbol_hydrate); 1467 list_hydrate(&st.Sfriendfuncs,cast(list_free_fp)&symbol_hydrate); 1468 assert(!st.Sinlinefuncs); 1469 1470 baseclass_hydrate(&st.Sbase); 1471 baseclass_hydrate(&st.Svirtbase); 1472 baseclass_hydrate(&st.Smptrbase); 1473 baseclass_hydrate(&st.Sprimary); 1474 baseclass_hydrate(&st.Svbptrbase); 1475 1476 ph_hydrate(cast(void**)&st.Svecctor); 1477 ph_hydrate(cast(void**)&st.Sctor); 1478 ph_hydrate(cast(void**)&st.Sdtor); 1479 ph_hydrate(cast(void**)&st.Sprimdtor); 1480 ph_hydrate(cast(void**)&st.Spriminv); 1481 ph_hydrate(cast(void**)&st.Sscaldeldtor); 1482 ph_hydrate(cast(void**)&st.Sinvariant); 1483 ph_hydrate(cast(void**)&st.Svptr); 1484 ph_hydrate(cast(void**)&st.Svtbl); 1485 ph_hydrate(cast(void**)&st.Sopeq); 1486 ph_hydrate(cast(void**)&st.Sopeq2); 1487 ph_hydrate(cast(void**)&st.Scpct); 1488 ph_hydrate(cast(void**)&st.Sveccpct); 1489 ph_hydrate(cast(void**)&st.Salias); 1490 ph_hydrate(cast(void**)&st.Stempsym); 1491 param_hydrate(&st.Sarglist); 1492 param_hydrate(&st.Spr_arglist); 1493 ph_hydrate(cast(void**)&st.Svbptr); 1494 ph_hydrate(cast(void**)&st.Svbptr_parent); 1495 ph_hydrate(cast(void**)&st.Svbtbl); 1496 } 1497 else 1498 { 1499 ph_hydrate(cast(void**)&s.Sstruct); 1500 symbol_tree_hydrate(&s.Sstruct.Sroot); 1501 list_hydrate(&s.Sstruct.Sfldlst,cast(list_free_fp)&symbol_hydrate); 1502 } 1503 break; 1504 1505 case SC.enum_: 1506 assert(s.Senum); 1507 ph_hydrate(cast(void**)&s.Senum); 1508 if (CPP) 1509 { ph_hydrate(cast(void**)&s.Senum.SEalias); 1510 list_hydrate(&s.Senum.SEenumlist,cast(list_free_fp)&symbol_hydrate); 1511 } 1512 break; 1513 1514 case SC.template_: 1515 { template_t *tm; 1516 1517 tm = cast(template_t *) ph_hydrate(cast(void**)&s.Stemplate); 1518 list_hydrate(&tm.TMinstances,cast(list_free_fp)&symbol_hydrate); 1519 list_hydrate(&tm.TMfriends,cast(list_free_fp)&symbol_hydrate); 1520 param_hydrate(&tm.TMptpl); 1521 param_hydrate(&tm.TMptal); 1522 token_hydrate(&tm.TMbody); 1523 list_hydrate(&tm.TMmemberfuncs,cast(list_free_fp)&tmf_hydrate); 1524 list_hydrate(&tm.TMexplicit,cast(list_free_fp)&tme_hydrate); 1525 list_hydrate(&tm.TMnestedexplicit,cast(list_free_fp)&tmne_hydrate); 1526 list_hydrate(&tm.TMnestedfriends,cast(list_free_fp)&tmnf_hydrate); 1527 ph_hydrate(cast(void**)&tm.TMnext); 1528 symbol_hydrate(&tm.TMpartial); 1529 symbol_hydrate(&tm.TMprimary); 1530 break; 1531 } 1532 1533 case SC.namespace: 1534 symbol_tree_hydrate(&s.Snameroot); 1535 list_hydrate(&s.Susing,cast(list_free_fp)&symbol_hydrate); 1536 break; 1537 1538 case SC.memalias: 1539 case SC.funcalias: 1540 case SC.adl: 1541 list_hydrate(&s.Spath,cast(list_free_fp)&symbol_hydrate); 1542 goto case SC.alias_; 1543 1544 case SC.alias_: 1545 ph_hydrate(cast(void**)&s.Smemalias); 1546 break; 1547 1548 default: 1549 if (s.Sflags & (SFLvalue | SFLdtorexp)) 1550 el_hydrate(&s.Svalue); 1551 break; 1552 } 1553 { dt_t **pdt; 1554 dt_t *dt; 1555 1556 for (pdt = &s.Sdt; isdehydrated(*pdt); pdt = &dt.DTnext) 1557 { 1558 dt = cast(dt_t *) ph_hydrate(cast(void**)pdt); 1559 switch (dt.dt) 1560 { case DT_abytes: 1561 case DT_nbytes: 1562 ph_hydrate(cast(void**)&dt.DTpbytes); 1563 break; 1564 case DT_xoff: 1565 symbol_hydrate(&dt.DTsym); 1566 break; 1567 1568 default: 1569 break; 1570 } 1571 } 1572 } 1573 if (s.Scover) 1574 symbol_hydrate(&s.Scover); 1575 } 1576 return s; 1577 } 1578 } 1579 1580 /******************************************* 1581 * Dehydrate a symbol. 1582 */ 1583 1584 static if (DEHYDRATE) 1585 { 1586 @trusted 1587 void symbol_dehydrate(Symbol **ps) 1588 { 1589 Symbol *s; 1590 1591 if ((s = *ps) != null && !isdehydrated(s)) /* if symbol exists */ 1592 { type *t; 1593 struct_t *st; 1594 1595 debug 1596 if (debugy) 1597 printf("symbol_dehydrate('%s')\n",s.Sident.ptr); 1598 1599 ph_dehydrate(ps); 1600 version (DEBUG_XSYMGEN) 1601 { 1602 if (xsym_gen && ph_in_head(s)) 1603 return; 1604 } 1605 symbol_debug(s); 1606 t = s.Stype; 1607 if (isdehydrated(t)) 1608 return; 1609 type_dehydrate(&s.Stype); 1610 1611 if (tyfunc(t.Tty) && !isdehydrated(s.Sfunc)) 1612 { 1613 func_t *f = s.Sfunc; 1614 SYMIDX si; 1615 1616 debug assert(f); 1617 ph_dehydrate(&s.Sfunc); 1618 1619 list_dehydrate(&f.Fsymtree,cast(list_free_fp)&symbol_tree_dehydrate); 1620 blocklist_dehydrate(&f.Fstartblock); 1621 assert(!isdehydrated(&f.Flocsym.tab)); 1622 1623 version (DEBUG_XSYMGEN) 1624 { 1625 if (!xsym_gen || !ph_in_head(f.Flocsym[].ptr)) 1626 for (si = 0; si < f.Flocsym.length; si++) 1627 symbol_dehydrate(&f.Flocsym.tab[si]); 1628 } 1629 else 1630 { 1631 for (si = 0; si < f.Flocsym.length; si++) 1632 symbol_dehydrate(&f.Flocsym.tab[si]); 1633 } 1634 ph_dehydrate(&f.Flocsym.tab); 1635 1636 srcpos_dehydrate(&f.Fstartline); 1637 srcpos_dehydrate(&f.Fendline); 1638 symbol_dehydrate(&f.F__func__); 1639 if (CPP) 1640 { 1641 symbol_dehydrate(&f.Fparsescope); 1642 ph_dehydrate(&f.Fclass); 1643 symbol_dehydrate(&f.Foversym); 1644 symbol_dehydrate(&f.Fexplicitspec); 1645 symbol_dehydrate(&f.Fsurrogatesym); 1646 1647 list_dehydrate(&f.Fclassfriends,FPNULL); 1648 el_dehydrate(&f.Fbaseinit); 1649 version (DEBUG_XSYMGEN) 1650 { 1651 if (xsym_gen && s.Sclass == SC.functempl) 1652 ph_dehydrate(&f.Fbody); 1653 else 1654 token_dehydrate(&f.Fbody); 1655 } 1656 else 1657 token_dehydrate(&f.Fbody); 1658 1659 symbol_dehydrate(&f.Falias); 1660 list_dehydrate(&f.Fthunks,cast(list_free_fp)&symbol_dehydrate); 1661 if (f.Fflags & Finstance) 1662 symbol_dehydrate(&f.Ftempl); 1663 else 1664 thunk_dehydrate(&f.Fthunk); 1665 //#if !TX86 && DEBUG_XSYMGEN 1666 // if (xsym_gen && s.Sclass == SCfunctempl) 1667 // ph_dehydrate(&f.Farglist); 1668 // else 1669 //#endif 1670 param_dehydrate(&f.Farglist); 1671 param_dehydrate(&f.Fptal); 1672 list_dehydrate(&f.Ffwdrefinstances,cast(list_free_fp)&symbol_dehydrate); 1673 list_dehydrate(&f.Fexcspec,cast(list_free_fp)&type_dehydrate); 1674 } 1675 } 1676 if (CPP) 1677 ph_dehydrate(&s.Sscope); 1678 switch (s.Sclass) 1679 { 1680 case SC.struct_: 1681 if (CPP) 1682 { 1683 st = s.Sstruct; 1684 if (isdehydrated(st)) 1685 break; 1686 ph_dehydrate(&s.Sstruct); 1687 assert(st); 1688 symbol_tree_dehydrate(&st.Sroot); 1689 ph_dehydrate(&st.Spvirtder); 1690 list_dehydrate(&st.Sfldlst,cast(list_free_fp)&symbol_dehydrate); 1691 list_dehydrate(&st.Svirtual,cast(list_free_fp)&mptr_dehydrate); 1692 list_dehydrate(&st.Sopoverload,cast(list_free_fp)&symbol_dehydrate); 1693 list_dehydrate(&st.Scastoverload,cast(list_free_fp)&symbol_dehydrate); 1694 list_dehydrate(&st.Sclassfriends,cast(list_free_fp)&symbol_dehydrate); 1695 list_dehydrate(&st.Sfriendclass,cast(list_free_fp)&ph_dehydrate); 1696 list_dehydrate(&st.Sfriendfuncs,cast(list_free_fp)&ph_dehydrate); 1697 assert(!st.Sinlinefuncs); 1698 1699 baseclass_dehydrate(&st.Sbase); 1700 baseclass_dehydrate(&st.Svirtbase); 1701 baseclass_dehydrate(&st.Smptrbase); 1702 baseclass_dehydrate(&st.Sprimary); 1703 baseclass_dehydrate(&st.Svbptrbase); 1704 1705 ph_dehydrate(&st.Svecctor); 1706 ph_dehydrate(&st.Sctor); 1707 ph_dehydrate(&st.Sdtor); 1708 ph_dehydrate(&st.Sprimdtor); 1709 ph_dehydrate(&st.Spriminv); 1710 ph_dehydrate(&st.Sscaldeldtor); 1711 ph_dehydrate(&st.Sinvariant); 1712 ph_dehydrate(&st.Svptr); 1713 ph_dehydrate(&st.Svtbl); 1714 ph_dehydrate(&st.Sopeq); 1715 ph_dehydrate(&st.Sopeq2); 1716 ph_dehydrate(&st.Scpct); 1717 ph_dehydrate(&st.Sveccpct); 1718 ph_dehydrate(&st.Salias); 1719 ph_dehydrate(&st.Stempsym); 1720 param_dehydrate(&st.Sarglist); 1721 param_dehydrate(&st.Spr_arglist); 1722 ph_dehydrate(&st.Svbptr); 1723 ph_dehydrate(&st.Svbptr_parent); 1724 ph_dehydrate(&st.Svbtbl); 1725 } 1726 else 1727 { 1728 symbol_tree_dehydrate(&s.Sstruct.Sroot); 1729 list_dehydrate(&s.Sstruct.Sfldlst,cast(list_free_fp)&symbol_dehydrate); 1730 ph_dehydrate(&s.Sstruct); 1731 } 1732 break; 1733 1734 case SC.enum_: 1735 assert(s.Senum); 1736 if (!isdehydrated(s.Senum)) 1737 { 1738 if (CPP) 1739 { ph_dehydrate(&s.Senum.SEalias); 1740 list_dehydrate(&s.Senumlist,cast(list_free_fp)&ph_dehydrate); 1741 } 1742 ph_dehydrate(&s.Senum); 1743 } 1744 break; 1745 1746 case SC.template_: 1747 { template_t *tm; 1748 1749 tm = s.Stemplate; 1750 if (!isdehydrated(tm)) 1751 { 1752 ph_dehydrate(&s.Stemplate); 1753 list_dehydrate(&tm.TMinstances,cast(list_free_fp)&symbol_dehydrate); 1754 list_dehydrate(&tm.TMfriends,cast(list_free_fp)&symbol_dehydrate); 1755 list_dehydrate(&tm.TMnestedfriends,cast(list_free_fp)&tmnf_dehydrate); 1756 param_dehydrate(&tm.TMptpl); 1757 param_dehydrate(&tm.TMptal); 1758 token_dehydrate(&tm.TMbody); 1759 list_dehydrate(&tm.TMmemberfuncs,cast(list_free_fp)&tmf_dehydrate); 1760 list_dehydrate(&tm.TMexplicit,cast(list_free_fp)&tme_dehydrate); 1761 list_dehydrate(&tm.TMnestedexplicit,cast(list_free_fp)&tmne_dehydrate); 1762 ph_dehydrate(&tm.TMnext); 1763 symbol_dehydrate(&tm.TMpartial); 1764 symbol_dehydrate(&tm.TMprimary); 1765 } 1766 break; 1767 } 1768 1769 case SC.namespace_: 1770 symbol_tree_dehydrate(&s.Snameroot); 1771 list_dehydrate(&s.Susing,cast(list_free_fp)&symbol_dehydrate); 1772 break; 1773 1774 case SC.memalias: 1775 case SC.funcalias: 1776 case SC.adl: 1777 list_dehydrate(&s.Spath,cast(list_free_fp)&symbol_dehydrate); 1778 case SC.alias_: 1779 ph_dehydrate(&s.Smemalias); 1780 break; 1781 1782 default: 1783 if (s.Sflags & (SFLvalue | SFLdtorexp)) 1784 el_dehydrate(&s.Svalue); 1785 break; 1786 } 1787 { dt_t **pdt; 1788 dt_t *dt; 1789 1790 for (pdt = &s.Sdt; 1791 (dt = *pdt) != null && !isdehydrated(dt); 1792 pdt = &dt.DTnext) 1793 { 1794 ph_dehydrate(pdt); 1795 switch (dt.dt) 1796 { case DT_abytes: 1797 case DT_nbytes: 1798 ph_dehydrate(&dt.DTpbytes); 1799 break; 1800 case DT_xoff: 1801 symbol_dehydrate(&dt.DTsym); 1802 break; 1803 } 1804 } 1805 } 1806 if (s.Scover) 1807 symbol_dehydrate(&s.Scover); 1808 } 1809 } 1810 } 1811 1812 /*************************** 1813 * Dehydrate threaded list of symbols. 1814 */ 1815 1816 static if (DEHYDRATE) 1817 { 1818 @trusted 1819 void symbol_symdefs_dehydrate(Symbol **ps) 1820 { 1821 Symbol *s; 1822 1823 for (; *ps; ps = &s.Snext) 1824 { 1825 s = *ps; 1826 symbol_debug(s); 1827 //printf("symbol_symdefs_dehydrate(%p, '%s')\n",s,s.Sident.ptr); 1828 symbol_dehydrate(ps); 1829 } 1830 } 1831 } 1832 1833 1834 /*************************** 1835 * Hydrate threaded list of symbols. 1836 * Input: 1837 * *psx start of threaded list 1838 * *parent root of symbol table to add symbol into 1839 * flag !=0 means add onto existing stuff 1840 * 0 means hydrate in place 1841 */ 1842 1843 version (SCPP_HTOD) 1844 { 1845 1846 @trusted 1847 void symbol_symdefs_hydrate(Symbol **psx,Symbol **parent,int flag) 1848 { Symbol *s; 1849 1850 //printf("symbol_symdefs_hydrate(flag = %d)\n",flag); 1851 debug 1852 { 1853 int count = 0; 1854 1855 if (flag) symbol_tree_check(*parent); 1856 } 1857 for (; *psx; psx = &s.Snext) 1858 { 1859 //printf("%p ",*psx); 1860 debug 1861 count++; 1862 1863 s = dohydrate ? symbol_hydrate(psx) : *psx; 1864 1865 //if (s.Sclass == SCstruct) 1866 //printf("symbol_symdefs_hydrate(%p, '%s')\n",s,s.Sident.ptr); 1867 symbol_debug(s); 1868 static if (0) 1869 { 1870 if (tyfunc(s.Stype.Tty)) 1871 { OutBuffer buf; 1872 char *p1; 1873 1874 p1 = param_tostring(&buf,s.Stype); 1875 printf("'%s%s'\n",cpp_prettyident(s),p1); 1876 } 1877 } 1878 type_debug(s.Stype); 1879 if (flag) 1880 { char *p; 1881 Symbol **ps; 1882 Symbol *rover; 1883 char c; 1884 size_t len; 1885 1886 p = s.Sident.ptr; 1887 c = *p; 1888 1889 // Put symbol s into symbol table 1890 1891 static if (MMFIO) 1892 { 1893 if (s.Sl || s.Sr) // avoid writing to page if possible 1894 s.Sl = s.Sr = null; 1895 } 1896 else 1897 s.Sl = s.Sr = null; 1898 1899 len = strlen(p); 1900 p++; 1901 ps = parent; 1902 while ((rover = *ps) != null) 1903 { byte cmp; 1904 1905 if ((cmp = cast(byte)(c - rover.Sident[0])) == 0) 1906 { cmp = cast(byte)memcmp(p,rover.Sident.ptr + 1,len); // compare identifier strings 1907 if (cmp == 0) 1908 { 1909 if (CPP && tyfunc(s.Stype.Tty) && tyfunc(rover.Stype.Tty)) 1910 { Symbol **psym; 1911 Symbol *sn; 1912 Symbol *so; 1913 1914 so = s; 1915 do 1916 { 1917 // Tack onto end of overloaded function list 1918 for (psym = &rover; *psym; psym = &(*psym).Sfunc.Foversym) 1919 { if (cpp_funccmp(so, *psym)) 1920 { //printf("function '%s' already in list\n",so.Sident.ptr); 1921 goto L2; 1922 } 1923 } 1924 //printf("appending '%s' to rover\n",so.Sident.ptr); 1925 *psym = so; 1926 L2: 1927 sn = so.Sfunc.Foversym; 1928 so.Sfunc.Foversym = null; 1929 so = sn; 1930 } while (so); 1931 //printf("overloading...\n"); 1932 } 1933 else if (s.Sclass == SC.struct_) 1934 { 1935 if (CPP && rover.Scover) 1936 { ps = &rover.Scover; 1937 rover = *ps; 1938 } 1939 else 1940 if (rover.Sclass == SC.struct_) 1941 { 1942 if (!(s.Stype.Tflags & TFforward)) 1943 { // Replace rover with s in symbol table 1944 //printf("Replacing '%s'\n",s.Sident.ptr); 1945 *ps = s; 1946 s.Sl = rover.Sl; 1947 s.Sr = rover.Sr; 1948 rover.Sl = rover.Sr = null; 1949 rover.Stype.Ttag = cast(Classsym *)s; 1950 symbol_keep(rover); 1951 } 1952 else 1953 s.Stype.Ttag = cast(Classsym *)rover; 1954 } 1955 } 1956 goto L1; 1957 } 1958 } 1959 ps = (cmp < 0) ? /* if we go down left side */ 1960 &rover.Sl : 1961 &rover.Sr; 1962 } 1963 *ps = s; 1964 if (s.Sclass == SC.comdef) 1965 { s.Sclass = SC.global; 1966 outcommon(s,type_size(s.Stype)); 1967 } 1968 } 1969 L1: 1970 } // for 1971 debug 1972 { 1973 if (flag) symbol_tree_check(*parent); 1974 printf("%d symbols hydrated\n",count); 1975 } 1976 } 1977 1978 } 1979 1980 static if (0) 1981 { 1982 1983 /************************************* 1984 * Put symbol table s into parent symbol table. 1985 */ 1986 1987 void symboltable_hydrate(Symbol *s,Symbol **parent) 1988 { 1989 while (s) 1990 { Symbol* sl,sr; 1991 char *p; 1992 1993 symbol_debug(s); 1994 1995 sl = s.Sl; 1996 sr = s.Sr; 1997 p = s.Sident.ptr; 1998 1999 //printf("symboltable_hydrate('%s')\n",p); 2000 2001 /* Put symbol s into symbol table */ 2002 { Symbol **ps; 2003 Symbol *rover; 2004 int c = *p; 2005 2006 ps = parent; 2007 while ((rover = *ps) != null) 2008 { int cmp; 2009 2010 if ((cmp = c - rover.Sident[0]) == 0) 2011 { cmp = strcmp(p,rover.Sident.ptr); /* compare identifier strings */ 2012 if (cmp == 0) 2013 { 2014 if (CPP && tyfunc(s.Stype.Tty) && tyfunc(rover.Stype.Tty)) 2015 { Symbol **ps; 2016 Symbol *sn; 2017 2018 do 2019 { 2020 // Tack onto end of overloaded function list 2021 for (ps = &rover; *ps; ps = &(*ps).Sfunc.Foversym) 2022 { if (cpp_funccmp(s, *ps)) 2023 goto L2; 2024 } 2025 s.Sl = s.Sr = null; 2026 *ps = s; 2027 L2: 2028 sn = s.Sfunc.Foversym; 2029 s.Sfunc.Foversym = null; 2030 s = sn; 2031 } while (s); 2032 } 2033 else 2034 { 2035 if (!typematch(s.Stype,rover.Stype,0)) 2036 { 2037 // cpp_predefine() will define this again 2038 if (type_struct(rover.Stype) && 2039 rover.Sstruct.Sflags & STRpredef) 2040 { s.Sl = s.Sr = null; 2041 symbol_keep(s); 2042 } 2043 else 2044 synerr(EM_multiple_def,p); // already defined 2045 } 2046 } 2047 goto L1; 2048 } 2049 } 2050 ps = (cmp < 0) ? /* if we go down left side */ 2051 &rover.Sl : 2052 &rover.Sr; 2053 } 2054 { 2055 s.Sl = s.Sr = null; 2056 *ps = s; 2057 } 2058 } 2059 L1: 2060 symboltable_hydrate(sl,parent); 2061 s = sr; 2062 } 2063 } 2064 2065 } 2066 2067 2068 /************************************ 2069 * Hydrate/dehydrate an mptr_t. 2070 */ 2071 2072 static if (HYDRATE) 2073 { 2074 @trusted 2075 private void mptr_hydrate(mptr_t **pm) 2076 { mptr_t *m; 2077 2078 m = cast(mptr_t *) ph_hydrate(cast(void**)pm); 2079 symbol_hydrate(&m.MPf); 2080 symbol_hydrate(&m.MPparent); 2081 } 2082 } 2083 2084 static if (DEHYDRATE) 2085 { 2086 @trusted 2087 private void mptr_dehydrate(mptr_t **pm) 2088 { mptr_t *m; 2089 2090 m = *pm; 2091 if (m && !isdehydrated(m)) 2092 { 2093 ph_dehydrate(pm); 2094 version (DEBUG_XSYMGEN) 2095 { 2096 if (xsym_gen && ph_in_head(m.MPf)) 2097 ph_dehydrate(&m.MPf); 2098 else 2099 symbol_dehydrate(&m.MPf); 2100 } 2101 else 2102 symbol_dehydrate(&m.MPf); 2103 2104 symbol_dehydrate(&m.MPparent); 2105 } 2106 } 2107 } 2108 2109 /************************************ 2110 * Hydrate/dehydrate a baseclass_t. 2111 */ 2112 2113 static if (HYDRATE) 2114 { 2115 @trusted 2116 private void baseclass_hydrate(baseclass_t **pb) 2117 { baseclass_t *b; 2118 2119 assert(pb); 2120 while (isdehydrated(*pb)) 2121 { 2122 b = cast(baseclass_t *) ph_hydrate(cast(void**)pb); 2123 2124 ph_hydrate(cast(void**)&b.BCbase); 2125 ph_hydrate(cast(void**)&b.BCpbase); 2126 list_hydrate(&b.BCpublics,cast(list_free_fp)&symbol_hydrate); 2127 list_hydrate(&b.BCmptrlist,cast(list_free_fp)&mptr_hydrate); 2128 symbol_hydrate(&b.BCvtbl); 2129 Classsym_hydrate(&b.BCparent); 2130 2131 pb = &b.BCnext; 2132 } 2133 } 2134 } 2135 2136 /********************************** 2137 * Dehydrate a baseclass_t. 2138 */ 2139 2140 static if (DEHYDRATE) 2141 { 2142 @trusted 2143 private void baseclass_dehydrate(baseclass_t **pb) 2144 { baseclass_t *b; 2145 2146 while ((b = *pb) != null && !isdehydrated(b)) 2147 { 2148 ph_dehydrate(pb); 2149 2150 version (DEBUG_XSYMGEN) 2151 { 2152 if (xsym_gen && ph_in_head(b)) 2153 return; 2154 } 2155 2156 ph_dehydrate(&b.BCbase); 2157 ph_dehydrate(&b.BCpbase); 2158 list_dehydrate(&b.BCpublics,cast(list_free_fp)&symbol_dehydrate); 2159 list_dehydrate(&b.BCmptrlist,cast(list_free_fp)&mptr_dehydrate); 2160 symbol_dehydrate(&b.BCvtbl); 2161 Classsym_dehydrate(&b.BCparent); 2162 2163 pb = &b.BCnext; 2164 } 2165 } 2166 } 2167 2168 /*************************** 2169 * Look down baseclass list to find sbase. 2170 * Returns: 2171 * null not found 2172 * pointer to baseclass 2173 */ 2174 2175 baseclass_t *baseclass_find(baseclass_t *bm,Classsym *sbase) 2176 { 2177 symbol_debug(sbase); 2178 for (; bm; bm = bm.BCnext) 2179 if (bm.BCbase == sbase) 2180 break; 2181 return bm; 2182 } 2183 2184 @trusted 2185 baseclass_t *baseclass_find_nest(baseclass_t *bm,Classsym *sbase) 2186 { 2187 symbol_debug(sbase); 2188 for (; bm; bm = bm.BCnext) 2189 { 2190 if (bm.BCbase == sbase || 2191 baseclass_find_nest(bm.BCbase.Sstruct.Sbase, sbase)) 2192 break; 2193 } 2194 return bm; 2195 } 2196 2197 /****************************** 2198 * Calculate number of baseclasses in list. 2199 */ 2200 2201 int baseclass_nitems(baseclass_t *b) 2202 { int i; 2203 2204 for (i = 0; b; b = b.BCnext) 2205 i++; 2206 return i; 2207 } 2208 2209 2210 /***************************** 2211 * Go through symbol table preparing it to be written to a precompiled 2212 * header. That means removing references to things in the .OBJ file. 2213 */ 2214 2215 version (SCPP_HTOD) 2216 { 2217 2218 @trusted 2219 void symboltable_clean(Symbol *s) 2220 { 2221 while (s) 2222 { 2223 struct_t *st; 2224 2225 //printf("clean('%s')\n",s.Sident.ptr); 2226 if (config.fulltypes != CVTDB && s.Sxtrnnum && s.Sfl != FLreg) 2227 s.Sxtrnnum = 0; // eliminate debug info type index 2228 switch (s.Sclass) 2229 { 2230 case SC.struct_: 2231 s.Stypidx = 0; 2232 st = s.Sstruct; 2233 assert(st); 2234 symboltable_clean(st.Sroot); 2235 //list_apply(&st.Sfldlst,cast(list_free_fp)&symboltable_clean); 2236 break; 2237 2238 case SC.typedef_: 2239 case SC.enum_: 2240 s.Stypidx = 0; 2241 break; 2242 2243 case SC.template_: 2244 { template_t *tm = s.Stemplate; 2245 2246 list_apply(&tm.TMinstances,cast(list_free_fp)&symboltable_clean); 2247 break; 2248 } 2249 2250 case SC.namespace: 2251 symboltable_clean(s.Snameroot); 2252 break; 2253 2254 default: 2255 if (s.Sxtrnnum && s.Sfl != FLreg) 2256 s.Sxtrnnum = 0; // eliminate external symbol index 2257 if (tyfunc(s.Stype.Tty)) 2258 { 2259 func_t *f = s.Sfunc; 2260 SYMIDX si; 2261 2262 debug assert(f); 2263 2264 list_apply(&f.Fsymtree,cast(list_free_fp)&symboltable_clean); 2265 for (si = 0; si < f.Flocsym.length; si++) 2266 symboltable_clean(f.Flocsym[si]); 2267 if (f.Foversym) 2268 symboltable_clean(f.Foversym); 2269 if (f.Fexplicitspec) 2270 symboltable_clean(f.Fexplicitspec); 2271 } 2272 break; 2273 } 2274 if (s.Sl) 2275 symboltable_clean(s.Sl); 2276 if (s.Scover) 2277 symboltable_clean(s.Scover); 2278 s = s.Sr; 2279 } 2280 } 2281 2282 } 2283 2284 version (SCPP_HTOD) 2285 { 2286 2287 /* 2288 * Balance our symbol tree in place. This is nice for precompiled headers, since they 2289 * will typically be written out once, but read in many times. We balance the tree in 2290 * place by traversing the tree inorder and writing the pointers out to an ordered 2291 * list. Once we have a list of symbol pointers, we can create a tree by recursively 2292 * dividing the list, using the midpoint of each division as the new root for that 2293 * subtree. 2294 */ 2295 2296 struct Balance 2297 { 2298 uint nsyms; 2299 Symbol **array; 2300 uint index; 2301 } 2302 2303 private __gshared Balance balance; 2304 2305 private void count_symbols(Symbol *s) 2306 { 2307 while (s) 2308 { 2309 balance.nsyms++; 2310 switch (s.Sclass) 2311 { 2312 case SC.namespace: 2313 symboltable_balance(&s.Snameroot); 2314 break; 2315 2316 case SC.struct_: 2317 symboltable_balance(&s.Sstruct.Sroot); 2318 break; 2319 2320 default: 2321 break; 2322 } 2323 count_symbols(s.Sl); 2324 s = s.Sr; 2325 } 2326 } 2327 2328 private void place_in_array(Symbol *s) 2329 { 2330 while (s) 2331 { 2332 place_in_array(s.Sl); 2333 balance.array[balance.index++] = s; 2334 s = s.Sr; 2335 } 2336 } 2337 2338 /* 2339 * Create a tree in place by subdividing between lo and hi inclusive, using i 2340 * as the root for the tree. When the lo-hi interval is one, we've either 2341 * reached a leaf or an empty node. We subdivide below i by halving the interval 2342 * between i and lo, and using i-1 as our new hi point. A similar subdivision 2343 * is created above i. 2344 */ 2345 private Symbol * create_tree(int i, int lo, int hi) 2346 { 2347 Symbol *s = balance.array[i]; 2348 2349 if (i < lo || i > hi) /* empty node ? */ 2350 return null; 2351 2352 assert(cast(uint) i < balance.nsyms); 2353 if (i == lo && i == hi) { /* leaf node ? */ 2354 s.Sl = null; 2355 s.Sr = null; 2356 return s; 2357 } 2358 2359 s.Sl = create_tree((i + lo) / 2, lo, i - 1); 2360 s.Sr = create_tree((i + hi + 1) / 2, i + 1, hi); 2361 2362 return s; 2363 } 2364 2365 enum METRICS = false; 2366 2367 void symboltable_balance(Symbol **ps) 2368 { 2369 Balance balancesave; 2370 static if (METRICS) 2371 { 2372 clock_t ticks; 2373 2374 printf("symbol table before balance:\n"); 2375 symbol_table_metrics(); 2376 ticks = clock(); 2377 } 2378 balancesave = balance; // so we can nest 2379 balance.nsyms = 0; 2380 count_symbols(*ps); 2381 //printf("Number of global symbols = %d\n",balance.nsyms); 2382 2383 // Use malloc instead of mem because of pagesize limits 2384 balance.array = cast(Symbol **) malloc(balance.nsyms * (Symbol *).sizeof); 2385 if (!balance.array) 2386 goto Lret; // no error, just don't balance 2387 2388 balance.index = 0; 2389 place_in_array(*ps); 2390 2391 *ps = create_tree(balance.nsyms / 2, 0, balance.nsyms - 1); 2392 2393 free(balance.array); 2394 static if (METRICS) 2395 { 2396 printf("time to balance: %ld\n", clock() - ticks); 2397 printf("symbol table after balance:\n"); 2398 symbol_table_metrics(); 2399 } 2400 Lret: 2401 balance = balancesave; 2402 } 2403 2404 } 2405 2406 /***************************************** 2407 * Symbol table search routine for members of structs, given that 2408 * we don't know which struct it is in. 2409 * Give error message if it appears more than once. 2410 * Returns: 2411 * null member not found 2412 * symbol* symbol matching member 2413 */ 2414 2415 version (SCPP_HTOD) 2416 { 2417 2418 struct Paramblock // to minimize stack usage in helper function 2419 { const(char)* id; // identifier we are looking for 2420 Symbol *sm; // where to put result 2421 Symbol *s; 2422 } 2423 2424 private void membersearchx(Paramblock *p,Symbol *s) 2425 { 2426 while (s) 2427 { 2428 symbol_debug(s); 2429 2430 switch (s.Sclass) 2431 { 2432 case SC.struct_: 2433 foreach (sl; ListRange(s.Sstruct.Sfldlst)) 2434 { 2435 Symbol* sm = list_symbol(sl); 2436 symbol_debug(sm); 2437 if ((sm.Sclass == SC.member || sm.Sclass == SC.field) && 2438 strcmp(p.id,sm.Sident.ptr) == 0) 2439 { 2440 if (p.sm && p.sm.Smemoff != sm.Smemoff) 2441 synerr(EM_ambig_member,p.id,s.Sident.ptr,p.s.Sident.ptr); // ambiguous reference to id 2442 p.s = s; 2443 p.sm = sm; 2444 break; 2445 } 2446 } 2447 break; 2448 2449 default: 2450 break; 2451 } 2452 2453 if (s.Sl) 2454 membersearchx(p,s.Sl); 2455 s = s.Sr; 2456 } 2457 } 2458 2459 Symbol *symbol_membersearch(const(char)* id) 2460 { 2461 list_t sl; 2462 Paramblock pb; 2463 Scope *sc; 2464 2465 pb.id = id; 2466 pb.sm = null; 2467 for (sc = scope_end; sc; sc = sc.next) 2468 { 2469 if (sc.sctype & (CPP ? (SCTglobal | SCTlocal) : (SCTglobaltag | SCTtag))) 2470 membersearchx(cast(Paramblock *)&pb,cast(Symbol *)sc.root); 2471 } 2472 return pb.sm; 2473 } 2474 2475 /******************************************* 2476 * Generate debug info for global struct tag symbols. 2477 */ 2478 2479 private void symbol_gendebuginfox(Symbol *s) 2480 { 2481 for (; s; s = s.Sr) 2482 { 2483 if (s.Sl) 2484 symbol_gendebuginfox(s.Sl); 2485 if (s.Scover) 2486 symbol_gendebuginfox(s.Scover); 2487 switch (s.Sclass) 2488 { 2489 case SC.enum_: 2490 if (CPP && s.Senum.SEflags & SENnotagname) 2491 break; 2492 goto Lout; 2493 case SC.struct_: 2494 if (s.Sstruct.Sflags & STRanonymous) 2495 break; 2496 goto Lout; 2497 case SC.typedef_: 2498 Lout: 2499 if (!s.Stypidx) 2500 cv_outsym(s); 2501 break; 2502 2503 default: 2504 break; 2505 } 2506 } 2507 } 2508 2509 void symbol_gendebuginfo() 2510 { Scope *sc; 2511 2512 for (sc = scope_end; sc; sc = sc.next) 2513 { 2514 if (sc.sctype & (SCTglobaltag | SCTglobal)) 2515 symbol_gendebuginfox(cast(Symbol *)sc.root); 2516 } 2517 } 2518 2519 } 2520 2521 /************************************* 2522 * Reset Symbol so that it's now an "extern" to the next obj file being created. 2523 */ 2524 void symbol_reset(Symbol *s) 2525 { 2526 s.Soffset = 0; 2527 s.Sxtrnnum = 0; 2528 s.Stypidx = 0; 2529 s.Sflags &= ~(STRoutdef | SFLweak); 2530 s.Sdw_ref_idx = 0; 2531 if (s.Sclass == SC.global || s.Sclass == SC.comdat || 2532 s.Sfl == FLudata || s.Sclass == SC.static_) 2533 { s.Sclass = SC.extern_; 2534 s.Sfl = FLextern; 2535 } 2536 } 2537 2538 /**************************************** 2539 * Determine pointer type needed to access a Symbol, 2540 * essentially what type an OPrelconst should get 2541 * for that Symbol. 2542 * Params: 2543 * s = pointer to Symbol 2544 * Returns: 2545 * pointer type to access it 2546 */ 2547 tym_t symbol_pointerType(const Symbol* s) 2548 { 2549 return s.Stype.Tty & mTYimmutable ? TYimmutPtr : TYnptr; 2550 } 2551 2552 }