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