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