1 /** 2 * Symbols for the back end 3 * 4 * Compiler implementation of the 5 * $(LINK2 https://www.dlang.org, D programming language). 6 * 7 * Copyright: Copyright (C) 1984-1998 by Symantec 8 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 9 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 10 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 11 * Source: https://github.com/dlang/dmd/blob/master/src/dmd/backend/symbol.d 12 */ 13 14 module dmd.backend.symbol; 15 16 enum HYDRATE = false; 17 enum DEHYDRATE = false; 18 19 import core.stdc.stdio; 20 import core.stdc.stdlib; 21 import core.stdc.string; 22 23 import dmd.backend.cdef; 24 import dmd.backend.cc; 25 import dmd.backend.cgcv; 26 import dmd.backend.dlist; 27 import dmd.backend.dt; 28 import dmd.backend.dvec; 29 import dmd.backend.el; 30 import dmd.backend.global; 31 import dmd.backend.mem; 32 import dmd.backend.oper; 33 import dmd.backend.symtab; 34 import dmd.backend.ty; 35 import dmd.backend.type; 36 37 38 nothrow: 39 @safe: 40 41 import dmd.backend.code_x86; 42 43 void struct_free(struct_t *st) { } 44 45 @trusted @nogc 46 func_t* func_calloc() 47 { 48 func_t* f = cast(func_t *) calloc(1, func_t.sizeof); 49 if (!f) 50 err_nomem(); 51 return f; 52 } 53 54 @trusted 55 void func_free(func_t* f) { free(f); } 56 57 /******************************* 58 * Type out symbol information. 59 */ 60 @trusted 61 void symbol_print(const Symbol *s) 62 { 63 debug 64 { 65 if (!s) return; 66 printf("symbol %p '%s'\n ",s,s.Sident.ptr); 67 printf(" Sclass = %s ", class_str(s.Sclass)); 68 printf(" Ssymnum = %d",cast(int)s.Ssymnum); 69 printf(" Sfl = "); WRFL(cast(FL) s.Sfl); 70 printf(" Sseg = %d\n",s.Sseg); 71 // printf(" Ssize = x%02x\n",s.Ssize); 72 printf(" Soffset = x%04llx",cast(ulong)s.Soffset); 73 printf(" Sweight = %d",s.Sweight); 74 printf(" Sflags = x%04x",cast(uint)s.Sflags); 75 printf(" Sxtrnnum = %d\n",s.Sxtrnnum); 76 printf(" Stype = %p",s.Stype); 77 printf(" Sl = %p",s.Sl); 78 printf(" Sr = %p\n",s.Sr); 79 if (s.Sscope) 80 printf(" Sscope = '%s'\n",s.Sscope.Sident.ptr); 81 if (s.Stype) 82 type_print(s.Stype); 83 if (s.Sclass == SC.member || s.Sclass == SC.field) 84 { 85 printf(" Smemoff =%5lld", cast(long)s.Smemoff); 86 printf(" Sbit =%3d",s.Sbit); 87 printf(" Swidth =%3d\n",s.Swidth); 88 } 89 } 90 } 91 92 93 /********************************* 94 * Terminate use of symbol table. 95 */ 96 97 private __gshared Symbol *keep; 98 99 @trusted 100 void symbol_term() 101 { 102 symbol_free(keep); 103 } 104 105 /**************************************** 106 * Keep symbol around until symbol_term(). 107 */ 108 109 static if (TERMCODE) 110 { 111 112 void symbol_keep(Symbol *s) 113 { 114 symbol_debug(s); 115 s.Sr = keep; // use Sr so symbol_free() doesn't nest 116 keep = s; 117 } 118 119 } 120 121 /**************************************** 122 * Return alignment of symbol. 123 */ 124 @trusted 125 int Symbol_Salignsize(ref Symbol s) 126 { 127 if (s.Salignment > 0) 128 return s.Salignment; 129 int alignsize = type_alignsize(s.Stype); 130 131 /* Reduce alignment faults when SIMD vectors 132 * are reinterpreted cast to other types with less alignment. 133 */ 134 if (config.fpxmmregs && alignsize < 16 && 135 s.Sclass == SC.auto_ && 136 type_size(s.Stype) == 16) 137 { 138 alignsize = 16; 139 } 140 141 return alignsize; 142 } 143 144 /**************************************** 145 * Aver if Symbol is not only merely dead, but really most sincerely dead. 146 * Params: 147 * anyInlineAsm = true if there's any inline assembler code 148 * Returns: 149 * true if symbol is dead. 150 */ 151 152 @trusted 153 bool Symbol_Sisdead(const ref Symbol s, bool anyInlineAsm) 154 { 155 enum vol = false; 156 return s.Sflags & SFLdead || 157 /* SFLdead means the optimizer found no references to it. 158 * The rest deals with variables that the compiler never needed 159 * to read from memory because they were cached in registers, 160 * and so no memory needs to be allocated for them. 161 * Code that does write those variables to memory gets NOPed out 162 * during address assignment. 163 */ 164 (!anyInlineAsm && !(s.Sflags & SFLread) && s.Sflags & SFLunambig && 165 166 // mTYvolatile means this variable has been reference by a nested function 167 (vol || !(s.Stype.Tty & mTYvolatile)) && 168 169 (config.flags4 & CFG4optimized || !config.fulltypes)); 170 } 171 172 /**************************************** 173 * Determine if symbol needs a 'this' pointer. 174 */ 175 176 @trusted 177 int Symbol_needThis(const ref Symbol s) 178 { 179 //printf("needThis() '%s'\n", Sident.ptr); 180 181 debug assert(isclassmember(&s)); 182 183 if (s.Sclass == SC.member || s.Sclass == SC.field) 184 return 1; 185 if (tyfunc(s.Stype.Tty) && !(s.Sfunc.Fflags & Fstatic)) 186 return 1; 187 return 0; 188 } 189 190 /************************************ 191 * Determine if `s` may be affected if an assignment is done through 192 * a pointer. 193 * Params: 194 * s = symbol to check 195 * Returns: 196 * true if it may be modified by assignment through a pointer 197 */ 198 199 bool Symbol_isAffected(const ref Symbol s) 200 { 201 //printf("s: %s %d\n", s.Sident.ptr, !(s.Sflags & SFLunambig) && !(s.ty() & (mTYconst | mTYimmutable))); 202 //symbol_print(s); 203 204 /* If nobody took its address and it's not statically allocated, 205 * then it is not accessible via pointer and so is not affected. 206 */ 207 if (s.Sflags & SFLunambig) 208 return false; 209 210 /* If it's immutable, it can't be affected. 211 * 212 * Disable this check because: 213 * 1. Symbol_isAffected is not used by copyprop() and should be. 214 * 2. Non-@safe functions can temporarilly cast away immutable. 215 * 3. Need to add an @safe flag to funcsym_p to enable this. 216 * 4. Const can be mutated by a separate view. 217 * Address this in a separate PR. 218 */ 219 static if (0) 220 if (s.ty() & (mTYconst | mTYimmutable)) 221 { 222 /* Disabled for the moment because even @safe functions 223 * may have inlined unsafe code from other functions 224 */ 225 if (funcsym_p.Sfunc.Fflags3 & F3safe && 226 s.ty() & mTYimmutable) 227 { 228 return false; 229 } 230 } 231 return true; 232 } 233 234 235 /*********************************** 236 * Get user name of symbol. 237 */ 238 239 @trusted 240 const(char)* symbol_ident(const Symbol *s) 241 { 242 return s.Sident.ptr; 243 } 244 245 /**************************************** 246 * Create a new symbol. 247 */ 248 249 @trusted @nogc 250 extern (C) 251 Symbol * symbol_calloc(const(char)[] id) 252 { 253 //printf("sizeof(symbol)=%d, sizeof(s.Sident)=%d, len=%d\n", symbol.sizeof, s.Sident.sizeof, cast(int)id.length); 254 Symbol* s = cast(Symbol *) mem_fmalloc(Symbol.sizeof - Symbol.Sident.length + id.length + 1 + 5); 255 memset(s,0,Symbol.sizeof - s.Sident.length); 256 memcpy(s.Sident.ptr,id.ptr,id.length); 257 s.Sident.ptr[id.length] = 0; 258 s.Ssymnum = SYMIDX.max; 259 if (debugy) 260 printf("symbol_calloc('%s') = %p\n",s.Sident.ptr,s); 261 debug s.id = Symbol.IDsymbol; 262 return s; 263 } 264 265 /**************************************** 266 * Create a Symbol 267 * Params: 268 * name = name to give the Symbol 269 * type = type for the Symbol 270 * Returns: 271 * created Symbol 272 */ 273 274 @trusted @nogc 275 extern (C) 276 Symbol * symbol_name(const(char)[] name, SC sclass, type *t) 277 { 278 type_debug(t); 279 Symbol *s = symbol_calloc(name); 280 s.Sclass = sclass; 281 s.Stype = t; 282 s.Stype.Tcount++; 283 284 if (tyfunc(t.Tty)) 285 symbol_func(s); 286 return s; 287 } 288 289 /**************************************** 290 * Create a symbol that is an alias to another function symbol. 291 */ 292 293 @trusted 294 Funcsym *symbol_funcalias(Funcsym *sf) 295 { 296 symbol_debug(sf); 297 assert(tyfunc(sf.Stype.Tty)); 298 if (sf.Sclass == SC.funcalias) 299 sf = sf.Sfunc.Falias; 300 auto s = cast(Funcsym *)symbol_name(sf.Sident.ptr[0 .. strlen(sf.Sident.ptr)],SC.funcalias,sf.Stype); 301 s.Sfunc.Falias = sf; 302 303 return s; 304 } 305 306 /**************************************** 307 * Create a symbol, give it a name, storage class and type. 308 */ 309 310 @trusted @nogc 311 Symbol * symbol_generate(SC sclass,type *t) 312 { 313 __gshared int tmpnum; 314 char[4 + tmpnum.sizeof * 3 + 1] name; 315 316 //printf("symbol_generate(_TMP%d)\n", tmpnum); 317 const length = snprintf(name.ptr,name.length,"_TMP%d",tmpnum++); 318 Symbol *s = symbol_name(name.ptr[0 .. length],sclass,t); 319 //symbol_print(s); 320 321 s.Sflags |= SFLnodebug | SFLartifical; 322 323 return s; 324 } 325 326 /**************************************** 327 * Generate an auto symbol, and add it to the symbol table. 328 */ 329 330 Symbol * symbol_genauto(type *t) 331 { Symbol *s; 332 333 s = symbol_generate(SC.auto_,t); 334 s.Sflags |= SFLfree; 335 symbol_add(s); 336 return s; 337 } 338 339 /****************************************** 340 * Generate symbol into which we can copy the contents of expression e. 341 */ 342 343 Symbol *symbol_genauto(elem *e) 344 { 345 return symbol_genauto(type_fake(e.Ety)); 346 } 347 348 /****************************************** 349 * Generate symbol into which we can copy the contents of expression e. 350 */ 351 352 Symbol *symbol_genauto(tym_t ty) 353 { 354 return symbol_genauto(type_fake(ty)); 355 } 356 357 /**************************************** 358 * Add in the variants for a function symbol. 359 */ 360 361 @trusted @nogc 362 void symbol_func(Symbol *s) 363 { 364 //printf("symbol_func(%s, x%x)\n", s.Sident.ptr, fregsaved); 365 symbol_debug(s); 366 s.Sfl = FLfunc; 367 // Interrupt functions modify all registers 368 // BUG: do interrupt functions really save BP? 369 // Note that fregsaved may not be set yet 370 s.Sregsaved = (s.Stype && tybasic(s.Stype.Tty) == TYifunc) ? cast(regm_t) mBP : fregsaved; 371 s.Sseg = UNKNOWN; // don't know what segment it is in 372 if (!s.Sfunc) 373 s.Sfunc = func_calloc(); 374 } 375 376 /*************************************** 377 * Add a field to a struct s. 378 * Params: 379 * s = the struct symbol 380 * name = field name 381 * t = the type of the field 382 * offset = offset of the field 383 */ 384 385 @trusted 386 void symbol_struct_addField(Symbol *s, const(char)* name, type *t, uint offset) 387 { 388 Symbol *s2 = symbol_name(name[0 .. strlen(name)], SC.member, t); 389 s2.Smemoff = offset; 390 list_append(&s.Sstruct.Sfldlst, s2); 391 } 392 393 /*************************************** 394 * Add a bit field to a struct s. 395 * Params: 396 * s = the struct symbol 397 * name = field name 398 * t = the type of the field 399 * offset = offset of the field 400 * fieldWidth = width of bit field 401 * bitOffset = bit number of start of field 402 */ 403 404 @trusted 405 void symbol_struct_addBitField(Symbol *s, const(char)* name, type *t, uint offset, uint fieldWidth, uint bitOffset) 406 { 407 //printf("symbol_struct_addBitField() s: %s\n", s.Sident.ptr); 408 Symbol *s2 = symbol_name(name[0 .. strlen(name)], SC.field, t); 409 s2.Smemoff = offset; 410 s2.Swidth = cast(ubyte)fieldWidth; 411 s2.Sbit = cast(ubyte)bitOffset; 412 list_append(&s.Sstruct.Sfldlst, s2); 413 symbol_struct_hasBitFields(s); 414 } 415 416 /*************************************** 417 * Mark struct s as having bit fields 418 * Params: 419 * s = the struct symbol 420 */ 421 @trusted 422 void symbol_struct_hasBitFields(Symbol *s) 423 { 424 s.Sstruct.Sflags |= STRbitfields; 425 } 426 427 /*************************************** 428 * Add a base class to a struct s. 429 * Input: 430 * s the struct/class symbol 431 * t the type of the base class 432 * offset offset of the base class in the struct/class 433 */ 434 435 @trusted 436 void symbol_struct_addBaseClass(Symbol *s, type *t, uint offset) 437 { 438 assert(t && t.Tty == TYstruct); 439 auto bc = cast(baseclass_t*)mem_fmalloc(baseclass_t.sizeof); 440 bc.BCbase = t.Ttag; 441 bc.BCoffset = offset; 442 bc.BCnext = s.Sstruct.Sbase; 443 s.Sstruct.Sbase = bc; 444 } 445 446 /******************************** 447 * Check integrity of symbol data structure. 448 */ 449 450 debug 451 { 452 453 void symbol_check(const Symbol *s) 454 { 455 //printf("symbol_check('%s',%p)\n",s.Sident.ptr,s); 456 symbol_debug(s); 457 if (s.Stype) type_debug(s.Stype); 458 assert(cast(uint)s.Sclass < cast(uint)SCMAX); 459 } 460 461 void symbol_tree_check(const(Symbol)* s) 462 { 463 while (s) 464 { symbol_check(s); 465 symbol_tree_check(s.Sl); 466 s = s.Sr; 467 } 468 } 469 470 } 471 472 /************************************* 473 * Search for symbol in multiple symbol tables, 474 * starting with most recently nested one. 475 * Input: 476 * p . identifier string 477 * Returns: 478 * pointer to symbol 479 * null if couldn't find it 480 */ 481 482 static if (0) 483 { 484 Symbol * lookupsym(const(char)* p) 485 { 486 return scope_search(p,SCTglobal | SCTlocal); 487 } 488 } 489 490 /********************************* 491 * Delete symbol from symbol table, taking care to delete 492 * all children of a symbol. 493 * Make sure there are no more forward references (labels, tags). 494 * Input: 495 * pointer to a symbol 496 */ 497 498 @trusted 499 void meminit_free(meminit_t *m) /* helper for symbol_free() */ 500 { 501 list_free(&m.MIelemlist,cast(list_free_fp)&el_free); 502 mem_free(m); 503 } 504 505 @trusted 506 void symbol_free(Symbol *s) 507 { 508 while (s) /* if symbol exists */ 509 { Symbol *sr; 510 511 debug 512 { 513 if (debugy) 514 printf("symbol_free('%s',%p)\n",s.Sident.ptr,s); 515 symbol_debug(s); 516 assert(/*s.Sclass != SC.unde &&*/ cast(int) s.Sclass < cast(int) SCMAX); 517 } 518 { type *t = s.Stype; 519 520 if (t) 521 type_debug(t); 522 if (t && tyfunc(t.Tty) && s.Sfunc) 523 { 524 func_t *f = s.Sfunc; 525 526 debug assert(f); 527 blocklist_free(&f.Fstartblock); 528 freesymtab(f.Flocsym[].ptr,0,f.Flocsym.length); 529 530 f.Flocsym.dtor(); 531 if (CPP) 532 { 533 if (f.Fflags & Fnotparent) 534 { debug if (debugy) printf("not parent, returning\n"); 535 return; 536 } 537 538 /* We could be freeing the symbol before its class is */ 539 /* freed, so remove it from the class's field list */ 540 if (f.Fclass) 541 { list_t tl; 542 543 symbol_debug(f.Fclass); 544 tl = list_inlist(f.Fclass.Sstruct.Sfldlst,s); 545 if (tl) 546 list_setsymbol(tl, null); 547 } 548 549 if (f.Foversym && f.Foversym.Sfunc) 550 { f.Foversym.Sfunc.Fflags &= ~Fnotparent; 551 f.Foversym.Sfunc.Fclass = null; 552 symbol_free(f.Foversym); 553 } 554 555 if (f.Fexplicitspec) 556 symbol_free(f.Fexplicitspec); 557 558 /* If operator function, remove from list of such functions */ 559 if (f.Fflags & Foperator) 560 { assert(f.Foper && f.Foper < OPMAX); 561 //if (list_inlist(cpp_operfuncs[f.Foper],s)) 562 // list_subtract(&cpp_operfuncs[f.Foper],s); 563 } 564 565 list_free(&f.Fclassfriends,FPNULL); 566 list_free(&f.Ffwdrefinstances,FPNULL); 567 param_free(&f.Farglist); 568 param_free(&f.Fptal); 569 list_free(&f.Fexcspec,cast(list_free_fp)&type_free); 570 571 572 el_free(f.Fbaseinit); 573 if (f.Fthunk && !(f.Fflags & Finstance)) 574 mem_free(f.Fthunk); 575 list_free(&f.Fthunks,cast(list_free_fp)&symbol_free); 576 } 577 list_free(&f.Fsymtree,cast(list_free_fp)&symbol_free); 578 f.typesTable.dtor(); 579 func_free(f); 580 } 581 switch (s.Sclass) 582 { 583 case SC.struct_: 584 if (!CPP) 585 { 586 debug if (debugy) 587 printf("freeing members %p\n",s.Sstruct.Sfldlst); 588 589 list_free(&s.Sstruct.Sfldlst,FPNULL); 590 symbol_free(s.Sstruct.Sroot); 591 struct_free(s.Sstruct); 592 } 593 static if (0) /* Don't complain anymore about these, ANSI C says */ 594 { 595 /* it's ok */ 596 if (t && t.Tflags & TFsizeunknown) 597 synerr(EM_unknown_tag,s.Sident.ptr); 598 } 599 break; 600 case SC.enum_: 601 /* The actual member symbols are either in a local */ 602 /* table or on the member list of a class, so we */ 603 /* don't free them here. */ 604 assert(s.Senum); 605 list_free(&s.Senum.SEenumlist,FPNULL); 606 mem_free(s.Senum); 607 s.Senum = null; 608 break; 609 610 case SC.parameter: 611 case SC.regpar: 612 case SC.fastpar: 613 case SC.shadowreg: 614 case SC.register: 615 case SC.auto_: 616 vec_free(s.Srange); 617 static if (0) 618 { 619 goto case SC.const_; 620 case SC.const_: 621 if (s.Sflags & (SFLvalue | SFLdtorexp)) 622 el_free(s.Svalue); 623 } 624 break; 625 default: 626 break; 627 } 628 if (s.Sflags & (SFLvalue | SFLdtorexp)) 629 el_free(s.Svalue); 630 if (s.Sdt) 631 dt_free(s.Sdt); 632 type_free(t); 633 symbol_free(s.Sl); 634 sr = s.Sr; 635 debug 636 { 637 s.id = 0; 638 } 639 mem_ffree(s); 640 } 641 s = sr; 642 } 643 } 644 645 /******************************** 646 * Undefine a symbol. 647 * Assume error msg was already printed. 648 */ 649 650 static if (0) 651 { 652 private void symbol_undef(Symbol *s) 653 { 654 s.Sclass = SC.unde; 655 s.Ssymnum = SYMIDX.max; 656 type_free(s.Stype); /* free type data */ 657 s.Stype = null; 658 } 659 } 660 661 /***************************** 662 * Add symbol to current symbol array. 663 */ 664 665 @trusted 666 SYMIDX symbol_add(Symbol *s) 667 { 668 return symbol_add(*cstate.CSpsymtab, s); 669 } 670 671 @trusted 672 SYMIDX symbol_add(ref symtab_t symtab, Symbol* s) 673 { 674 //printf("symbol_add('%s')\n", s.Sident.ptr); 675 debug 676 { 677 if (!s || !s.Sident[0]) 678 { printf("bad symbol\n"); 679 assert(0); 680 } 681 } 682 symbol_debug(s); 683 if (pstate.STinsizeof) 684 { symbol_keep(s); 685 return SYMIDX.max; 686 } 687 const sitop = symtab.length; 688 symtab.setLength(sitop + 1); 689 symtab[sitop] = s; 690 691 debug if (debugy) 692 printf("symbol_add(%p '%s') = %d\n",s,s.Sident.ptr, cast(int) symtab.length); 693 694 debug if (s.Ssymnum != SYMIDX.max) 695 printf("symbol %s already added\n", s.Sident.ptr); 696 assert(s.Ssymnum == SYMIDX.max); 697 s.Ssymnum = sitop; 698 699 return sitop; 700 } 701 702 /******************************************** 703 * Insert s into symtab at position n. 704 * Returns: 705 * position in table 706 */ 707 @trusted 708 SYMIDX symbol_insert(ref symtab_t symtab, Symbol* s, SYMIDX n) 709 { 710 const sinew = symbol_add(s); // added at end, have to move it 711 for (SYMIDX i = sinew; i > n; --i) 712 { 713 symtab[i] = symtab[i - 1]; 714 symtab[i].Ssymnum += 1; 715 } 716 globsym[n] = s; 717 s.Ssymnum = n; 718 return n; 719 } 720 721 /**************************** 722 * Free up the symbols stab[n1 .. n2] 723 */ 724 725 @trusted 726 void freesymtab(Symbol **stab,SYMIDX n1,SYMIDX n2) 727 { 728 if (!stab) 729 return; 730 731 debug if (debugy) 732 printf("freesymtab(from %d to %d)\n", cast(int) n1, cast(int) n2); 733 734 assert(stab != globsym[].ptr || (n1 <= n2 && n2 <= globsym.length)); 735 foreach (ref s; stab[n1 .. n2]) 736 { 737 if (s && s.Sflags & SFLfree) 738 { 739 740 debug 741 { 742 if (debugy) 743 printf("Freeing %p '%s'\n",s,s.Sident.ptr); 744 symbol_debug(s); 745 } 746 s.Sl = s.Sr = null; 747 s.Ssymnum = SYMIDX.max; 748 symbol_free(s); 749 s = null; 750 } 751 } 752 } 753 754 /**************************** 755 * Create a copy of a symbol. 756 */ 757 758 @trusted 759 Symbol * symbol_copy(Symbol *s) 760 { Symbol *scopy; 761 type *t; 762 763 symbol_debug(s); 764 /*printf("symbol_copy(%s)\n",s.Sident.ptr);*/ 765 scopy = symbol_calloc(s.Sident.ptr[0 .. strlen(s.Sident.ptr)]); 766 memcpy(scopy,s,Symbol.sizeof - s.Sident.sizeof); 767 scopy.Sl = scopy.Sr = scopy.Snext = null; 768 scopy.Ssymnum = SYMIDX.max; 769 if (scopy.Sdt) 770 { 771 auto dtb = DtBuilder(0); 772 dtb.nzeros(cast(uint)type_size(scopy.Stype)); 773 scopy.Sdt = dtb.finish(); 774 } 775 if (scopy.Sflags & (SFLvalue | SFLdtorexp)) 776 scopy.Svalue = el_copytree(s.Svalue); 777 t = scopy.Stype; 778 if (t) 779 { t.Tcount++; /* one more parent of the type */ 780 type_debug(t); 781 } 782 return scopy; 783 } 784 785 /******************************************* 786 * Hydrate a symbol tree. 787 */ 788 789 static if (HYDRATE) 790 { 791 @trusted 792 void symbol_tree_hydrate(Symbol **ps) 793 { Symbol *s; 794 795 while (isdehydrated(*ps)) /* if symbol is dehydrated */ 796 { 797 s = symbol_hydrate(ps); 798 symbol_debug(s); 799 if (s.Scover) 800 symbol_hydrate(&s.Scover); 801 symbol_tree_hydrate(&s.Sl); 802 ps = &s.Sr; 803 } 804 805 } 806 } 807 808 /******************************************* 809 * Dehydrate a symbol tree. 810 */ 811 812 static if (DEHYDRATE) 813 { 814 @trusted 815 void symbol_tree_dehydrate(Symbol **ps) 816 { Symbol *s; 817 818 while ((s = *ps) != null && !isdehydrated(s)) /* if symbol exists */ 819 { 820 symbol_debug(s); 821 symbol_dehydrate(ps); 822 version (DEBUG_XSYMGEN) 823 { 824 if (xsym_gen && ph_in_head(s)) 825 return; 826 } 827 symbol_dehydrate(&s.Scover); 828 symbol_tree_dehydrate(&s.Sl); 829 ps = &s.Sr; 830 } 831 } 832 } 833 834 /******************************************* 835 * Hydrate a symbol. 836 */ 837 838 static if (HYDRATE) 839 { 840 @trusted 841 Symbol *symbol_hydrate(Symbol **ps) 842 { Symbol *s; 843 844 s = *ps; 845 if (isdehydrated(s)) /* if symbol is dehydrated */ 846 { type *t; 847 struct_t *st; 848 849 s = cast(Symbol *) ph_hydrate(cast(void**)ps); 850 851 debug debugy && printf("symbol_hydrate('%s')\n",s.Sident.ptr); 852 853 symbol_debug(s); 854 if (!isdehydrated(s.Stype)) // if this symbol is already dehydrated 855 return s; // no need to do it again 856 if (pstate.SThflag != FLAG_INPLACE && s.Sfl != FLreg) 857 s.Sxtrnnum = 0; // not written to .OBJ file yet 858 type_hydrate(&s.Stype); 859 //printf("symbol_hydrate(%p, '%s', t = %p)\n",s,s.Sident.ptr,s.Stype); 860 t = s.Stype; 861 if (t) 862 type_debug(t); 863 864 if (t && tyfunc(t.Tty) && ph_hydrate(cast(void**)&s.Sfunc)) 865 { 866 func_t *f = s.Sfunc; 867 SYMIDX si; 868 869 debug assert(f); 870 871 list_hydrate(&f.Fsymtree,cast(list_free_fp)&symbol_tree_hydrate); 872 blocklist_hydrate(&f.Fstartblock); 873 874 ph_hydrate(cast(void**)&f.Flocsym.tab); 875 for (si = 0; si < f.Flocsym.length; si++) 876 symbol_hydrate(&f.Flocsym[].ptr[si]); 877 878 srcpos_hydrate(&f.Fstartline); 879 srcpos_hydrate(&f.Fendline); 880 881 symbol_hydrate(&f.F__func__); 882 883 if (CPP) 884 { 885 symbol_hydrate(&f.Fparsescope); 886 Classsym_hydrate(&f.Fclass); 887 symbol_hydrate(&f.Foversym); 888 symbol_hydrate(&f.Fexplicitspec); 889 symbol_hydrate(&f.Fsurrogatesym); 890 891 list_hydrate(&f.Fclassfriends,cast(list_free_fp)&symbol_hydrate); 892 el_hydrate(&f.Fbaseinit); 893 token_hydrate(&f.Fbody); 894 symbol_hydrate(&f.Falias); 895 list_hydrate(&f.Fthunks,cast(list_free_fp)&symbol_hydrate); 896 if (f.Fflags & Finstance) 897 symbol_hydrate(&f.Ftempl); 898 else 899 thunk_hydrate(&f.Fthunk); 900 param_hydrate(&f.Farglist); 901 param_hydrate(&f.Fptal); 902 list_hydrate(&f.Ffwdrefinstances,cast(list_free_fp)&symbol_hydrate); 903 list_hydrate(&f.Fexcspec,cast(list_free_fp)&type_hydrate); 904 } 905 } 906 if (CPP) 907 symbol_hydrate(&s.Sscope); 908 switch (s.Sclass) 909 { 910 case SC.struct_: 911 if (CPP) 912 { 913 st = cast(struct_t *) ph_hydrate(cast(void**)&s.Sstruct); 914 assert(st); 915 symbol_tree_hydrate(&st.Sroot); 916 ph_hydrate(cast(void**)&st.Spvirtder); 917 list_hydrate(&st.Sfldlst,cast(list_free_fp)&symbol_hydrate); 918 list_hydrate(&st.Svirtual,cast(list_free_fp)&mptr_hydrate); 919 list_hydrate(&st.Sopoverload,cast(list_free_fp)&symbol_hydrate); 920 list_hydrate(&st.Scastoverload,cast(list_free_fp)&symbol_hydrate); 921 list_hydrate(&st.Sclassfriends,cast(list_free_fp)&symbol_hydrate); 922 list_hydrate(&st.Sfriendclass,cast(list_free_fp)&symbol_hydrate); 923 list_hydrate(&st.Sfriendfuncs,cast(list_free_fp)&symbol_hydrate); 924 assert(!st.Sinlinefuncs); 925 926 baseclass_hydrate(&st.Sbase); 927 baseclass_hydrate(&st.Svirtbase); 928 baseclass_hydrate(&st.Smptrbase); 929 baseclass_hydrate(&st.Sprimary); 930 baseclass_hydrate(&st.Svbptrbase); 931 932 ph_hydrate(cast(void**)&st.Svecctor); 933 ph_hydrate(cast(void**)&st.Sctor); 934 ph_hydrate(cast(void**)&st.Sdtor); 935 ph_hydrate(cast(void**)&st.Sprimdtor); 936 ph_hydrate(cast(void**)&st.Spriminv); 937 ph_hydrate(cast(void**)&st.Sscaldeldtor); 938 ph_hydrate(cast(void**)&st.Sinvariant); 939 ph_hydrate(cast(void**)&st.Svptr); 940 ph_hydrate(cast(void**)&st.Svtbl); 941 ph_hydrate(cast(void**)&st.Sopeq); 942 ph_hydrate(cast(void**)&st.Sopeq2); 943 ph_hydrate(cast(void**)&st.Scpct); 944 ph_hydrate(cast(void**)&st.Sveccpct); 945 ph_hydrate(cast(void**)&st.Salias); 946 ph_hydrate(cast(void**)&st.Stempsym); 947 param_hydrate(&st.Sarglist); 948 param_hydrate(&st.Spr_arglist); 949 ph_hydrate(cast(void**)&st.Svbptr); 950 ph_hydrate(cast(void**)&st.Svbptr_parent); 951 ph_hydrate(cast(void**)&st.Svbtbl); 952 } 953 else 954 { 955 ph_hydrate(cast(void**)&s.Sstruct); 956 symbol_tree_hydrate(&s.Sstruct.Sroot); 957 list_hydrate(&s.Sstruct.Sfldlst,cast(list_free_fp)&symbol_hydrate); 958 } 959 break; 960 961 case SC.enum_: 962 assert(s.Senum); 963 ph_hydrate(cast(void**)&s.Senum); 964 if (CPP) 965 { ph_hydrate(cast(void**)&s.Senum.SEalias); 966 list_hydrate(&s.Senum.SEenumlist,cast(list_free_fp)&symbol_hydrate); 967 } 968 break; 969 970 case SC.template_: 971 { template_t *tm; 972 973 tm = cast(template_t *) ph_hydrate(cast(void**)&s.Stemplate); 974 list_hydrate(&tm.TMinstances,cast(list_free_fp)&symbol_hydrate); 975 list_hydrate(&tm.TMfriends,cast(list_free_fp)&symbol_hydrate); 976 param_hydrate(&tm.TMptpl); 977 param_hydrate(&tm.TMptal); 978 token_hydrate(&tm.TMbody); 979 list_hydrate(&tm.TMmemberfuncs,cast(list_free_fp)&tmf_hydrate); 980 list_hydrate(&tm.TMexplicit,cast(list_free_fp)&tme_hydrate); 981 list_hydrate(&tm.TMnestedexplicit,cast(list_free_fp)&tmne_hydrate); 982 list_hydrate(&tm.TMnestedfriends,cast(list_free_fp)&tmnf_hydrate); 983 ph_hydrate(cast(void**)&tm.TMnext); 984 symbol_hydrate(&tm.TMpartial); 985 symbol_hydrate(&tm.TMprimary); 986 break; 987 } 988 989 case SC.namespace: 990 symbol_tree_hydrate(&s.Snameroot); 991 list_hydrate(&s.Susing,cast(list_free_fp)&symbol_hydrate); 992 break; 993 994 case SC.memalias: 995 case SC.funcalias: 996 case SC.adl: 997 list_hydrate(&s.Spath,cast(list_free_fp)&symbol_hydrate); 998 goto case SC.alias_; 999 1000 case SC.alias_: 1001 ph_hydrate(cast(void**)&s.Smemalias); 1002 break; 1003 1004 default: 1005 if (s.Sflags & (SFLvalue | SFLdtorexp)) 1006 el_hydrate(&s.Svalue); 1007 break; 1008 } 1009 { dt_t **pdt; 1010 dt_t *dt; 1011 1012 for (pdt = &s.Sdt; isdehydrated(*pdt); pdt = &dt.DTnext) 1013 { 1014 dt = cast(dt_t *) ph_hydrate(cast(void**)pdt); 1015 switch (dt.dt) 1016 { case DT_abytes: 1017 case DT_nbytes: 1018 ph_hydrate(cast(void**)&dt.DTpbytes); 1019 break; 1020 case DT_xoff: 1021 symbol_hydrate(&dt.DTsym); 1022 break; 1023 1024 default: 1025 break; 1026 } 1027 } 1028 } 1029 if (s.Scover) 1030 symbol_hydrate(&s.Scover); 1031 } 1032 return s; 1033 } 1034 } 1035 1036 /******************************************* 1037 * Dehydrate a symbol. 1038 */ 1039 1040 static if (DEHYDRATE) 1041 { 1042 @trusted 1043 void symbol_dehydrate(Symbol **ps) 1044 { 1045 Symbol *s; 1046 1047 if ((s = *ps) != null && !isdehydrated(s)) /* if symbol exists */ 1048 { type *t; 1049 struct_t *st; 1050 1051 debug 1052 if (debugy) 1053 printf("symbol_dehydrate('%s')\n",s.Sident.ptr); 1054 1055 ph_dehydrate(ps); 1056 version (DEBUG_XSYMGEN) 1057 { 1058 if (xsym_gen && ph_in_head(s)) 1059 return; 1060 } 1061 symbol_debug(s); 1062 t = s.Stype; 1063 if (isdehydrated(t)) 1064 return; 1065 type_dehydrate(&s.Stype); 1066 1067 if (tyfunc(t.Tty) && !isdehydrated(s.Sfunc)) 1068 { 1069 func_t *f = s.Sfunc; 1070 SYMIDX si; 1071 1072 debug assert(f); 1073 ph_dehydrate(&s.Sfunc); 1074 1075 list_dehydrate(&f.Fsymtree,cast(list_free_fp)&symbol_tree_dehydrate); 1076 blocklist_dehydrate(&f.Fstartblock); 1077 assert(!isdehydrated(&f.Flocsym.tab)); 1078 1079 version (DEBUG_XSYMGEN) 1080 { 1081 if (!xsym_gen || !ph_in_head(f.Flocsym[].ptr)) 1082 for (si = 0; si < f.Flocsym.length; si++) 1083 symbol_dehydrate(&f.Flocsym.tab[si]); 1084 } 1085 else 1086 { 1087 for (si = 0; si < f.Flocsym.length; si++) 1088 symbol_dehydrate(&f.Flocsym.tab[si]); 1089 } 1090 ph_dehydrate(&f.Flocsym.tab); 1091 1092 srcpos_dehydrate(&f.Fstartline); 1093 srcpos_dehydrate(&f.Fendline); 1094 symbol_dehydrate(&f.F__func__); 1095 if (CPP) 1096 { 1097 symbol_dehydrate(&f.Fparsescope); 1098 ph_dehydrate(&f.Fclass); 1099 symbol_dehydrate(&f.Foversym); 1100 symbol_dehydrate(&f.Fexplicitspec); 1101 symbol_dehydrate(&f.Fsurrogatesym); 1102 1103 list_dehydrate(&f.Fclassfriends,FPNULL); 1104 el_dehydrate(&f.Fbaseinit); 1105 version (DEBUG_XSYMGEN) 1106 { 1107 if (xsym_gen && s.Sclass == SC.functempl) 1108 ph_dehydrate(&f.Fbody); 1109 else 1110 token_dehydrate(&f.Fbody); 1111 } 1112 else 1113 token_dehydrate(&f.Fbody); 1114 1115 symbol_dehydrate(&f.Falias); 1116 list_dehydrate(&f.Fthunks,cast(list_free_fp)&symbol_dehydrate); 1117 if (f.Fflags & Finstance) 1118 symbol_dehydrate(&f.Ftempl); 1119 else 1120 thunk_dehydrate(&f.Fthunk); 1121 //#if !TX86 && DEBUG_XSYMGEN 1122 // if (xsym_gen && s.Sclass == SCfunctempl) 1123 // ph_dehydrate(&f.Farglist); 1124 // else 1125 //#endif 1126 param_dehydrate(&f.Farglist); 1127 param_dehydrate(&f.Fptal); 1128 list_dehydrate(&f.Ffwdrefinstances,cast(list_free_fp)&symbol_dehydrate); 1129 list_dehydrate(&f.Fexcspec,cast(list_free_fp)&type_dehydrate); 1130 } 1131 } 1132 if (CPP) 1133 ph_dehydrate(&s.Sscope); 1134 switch (s.Sclass) 1135 { 1136 case SC.struct_: 1137 if (CPP) 1138 { 1139 st = s.Sstruct; 1140 if (isdehydrated(st)) 1141 break; 1142 ph_dehydrate(&s.Sstruct); 1143 assert(st); 1144 symbol_tree_dehydrate(&st.Sroot); 1145 ph_dehydrate(&st.Spvirtder); 1146 list_dehydrate(&st.Sfldlst,cast(list_free_fp)&symbol_dehydrate); 1147 list_dehydrate(&st.Svirtual,cast(list_free_fp)&mptr_dehydrate); 1148 list_dehydrate(&st.Sopoverload,cast(list_free_fp)&symbol_dehydrate); 1149 list_dehydrate(&st.Scastoverload,cast(list_free_fp)&symbol_dehydrate); 1150 list_dehydrate(&st.Sclassfriends,cast(list_free_fp)&symbol_dehydrate); 1151 list_dehydrate(&st.Sfriendclass,cast(list_free_fp)&ph_dehydrate); 1152 list_dehydrate(&st.Sfriendfuncs,cast(list_free_fp)&ph_dehydrate); 1153 assert(!st.Sinlinefuncs); 1154 1155 baseclass_dehydrate(&st.Sbase); 1156 baseclass_dehydrate(&st.Svirtbase); 1157 baseclass_dehydrate(&st.Smptrbase); 1158 baseclass_dehydrate(&st.Sprimary); 1159 baseclass_dehydrate(&st.Svbptrbase); 1160 1161 ph_dehydrate(&st.Svecctor); 1162 ph_dehydrate(&st.Sctor); 1163 ph_dehydrate(&st.Sdtor); 1164 ph_dehydrate(&st.Sprimdtor); 1165 ph_dehydrate(&st.Spriminv); 1166 ph_dehydrate(&st.Sscaldeldtor); 1167 ph_dehydrate(&st.Sinvariant); 1168 ph_dehydrate(&st.Svptr); 1169 ph_dehydrate(&st.Svtbl); 1170 ph_dehydrate(&st.Sopeq); 1171 ph_dehydrate(&st.Sopeq2); 1172 ph_dehydrate(&st.Scpct); 1173 ph_dehydrate(&st.Sveccpct); 1174 ph_dehydrate(&st.Salias); 1175 ph_dehydrate(&st.Stempsym); 1176 param_dehydrate(&st.Sarglist); 1177 param_dehydrate(&st.Spr_arglist); 1178 ph_dehydrate(&st.Svbptr); 1179 ph_dehydrate(&st.Svbptr_parent); 1180 ph_dehydrate(&st.Svbtbl); 1181 } 1182 else 1183 { 1184 symbol_tree_dehydrate(&s.Sstruct.Sroot); 1185 list_dehydrate(&s.Sstruct.Sfldlst,cast(list_free_fp)&symbol_dehydrate); 1186 ph_dehydrate(&s.Sstruct); 1187 } 1188 break; 1189 1190 case SC.enum_: 1191 assert(s.Senum); 1192 if (!isdehydrated(s.Senum)) 1193 { 1194 if (CPP) 1195 { ph_dehydrate(&s.Senum.SEalias); 1196 list_dehydrate(&s.Senumlist,cast(list_free_fp)&ph_dehydrate); 1197 } 1198 ph_dehydrate(&s.Senum); 1199 } 1200 break; 1201 1202 case SC.template_: 1203 { template_t *tm; 1204 1205 tm = s.Stemplate; 1206 if (!isdehydrated(tm)) 1207 { 1208 ph_dehydrate(&s.Stemplate); 1209 list_dehydrate(&tm.TMinstances,cast(list_free_fp)&symbol_dehydrate); 1210 list_dehydrate(&tm.TMfriends,cast(list_free_fp)&symbol_dehydrate); 1211 list_dehydrate(&tm.TMnestedfriends,cast(list_free_fp)&tmnf_dehydrate); 1212 param_dehydrate(&tm.TMptpl); 1213 param_dehydrate(&tm.TMptal); 1214 token_dehydrate(&tm.TMbody); 1215 list_dehydrate(&tm.TMmemberfuncs,cast(list_free_fp)&tmf_dehydrate); 1216 list_dehydrate(&tm.TMexplicit,cast(list_free_fp)&tme_dehydrate); 1217 list_dehydrate(&tm.TMnestedexplicit,cast(list_free_fp)&tmne_dehydrate); 1218 ph_dehydrate(&tm.TMnext); 1219 symbol_dehydrate(&tm.TMpartial); 1220 symbol_dehydrate(&tm.TMprimary); 1221 } 1222 break; 1223 } 1224 1225 case SC.namespace_: 1226 symbol_tree_dehydrate(&s.Snameroot); 1227 list_dehydrate(&s.Susing,cast(list_free_fp)&symbol_dehydrate); 1228 break; 1229 1230 case SC.memalias: 1231 case SC.funcalias: 1232 case SC.adl: 1233 list_dehydrate(&s.Spath,cast(list_free_fp)&symbol_dehydrate); 1234 case SC.alias_: 1235 ph_dehydrate(&s.Smemalias); 1236 break; 1237 1238 default: 1239 if (s.Sflags & (SFLvalue | SFLdtorexp)) 1240 el_dehydrate(&s.Svalue); 1241 break; 1242 } 1243 { dt_t **pdt; 1244 dt_t *dt; 1245 1246 for (pdt = &s.Sdt; 1247 (dt = *pdt) != null && !isdehydrated(dt); 1248 pdt = &dt.DTnext) 1249 { 1250 ph_dehydrate(pdt); 1251 switch (dt.dt) 1252 { case DT_abytes: 1253 case DT_nbytes: 1254 ph_dehydrate(&dt.DTpbytes); 1255 break; 1256 case DT_xoff: 1257 symbol_dehydrate(&dt.DTsym); 1258 break; 1259 } 1260 } 1261 } 1262 if (s.Scover) 1263 symbol_dehydrate(&s.Scover); 1264 } 1265 } 1266 } 1267 1268 /*************************** 1269 * Dehydrate threaded list of symbols. 1270 */ 1271 1272 static if (DEHYDRATE) 1273 { 1274 @trusted 1275 void symbol_symdefs_dehydrate(Symbol **ps) 1276 { 1277 Symbol *s; 1278 1279 for (; *ps; ps = &s.Snext) 1280 { 1281 s = *ps; 1282 symbol_debug(s); 1283 //printf("symbol_symdefs_dehydrate(%p, '%s')\n",s,s.Sident.ptr); 1284 symbol_dehydrate(ps); 1285 } 1286 } 1287 } 1288 1289 1290 static if (0) 1291 { 1292 1293 /************************************* 1294 * Put symbol table s into parent symbol table. 1295 */ 1296 1297 void symboltable_hydrate(Symbol *s,Symbol **parent) 1298 { 1299 while (s) 1300 { Symbol* sl,sr; 1301 char *p; 1302 1303 symbol_debug(s); 1304 1305 sl = s.Sl; 1306 sr = s.Sr; 1307 p = s.Sident.ptr; 1308 1309 //printf("symboltable_hydrate('%s')\n",p); 1310 1311 /* Put symbol s into symbol table */ 1312 { Symbol **ps; 1313 Symbol *rover; 1314 int c = *p; 1315 1316 ps = parent; 1317 while ((rover = *ps) != null) 1318 { int cmp; 1319 1320 if ((cmp = c - rover.Sident[0]) == 0) 1321 { cmp = strcmp(p,rover.Sident.ptr); /* compare identifier strings */ 1322 if (cmp == 0) 1323 { 1324 if (CPP && tyfunc(s.Stype.Tty) && tyfunc(rover.Stype.Tty)) 1325 { Symbol **ps; 1326 Symbol *sn; 1327 1328 do 1329 { 1330 // Tack onto end of overloaded function list 1331 for (ps = &rover; *ps; ps = &(*ps).Sfunc.Foversym) 1332 { if (cpp_funccmp(s, *ps)) 1333 goto L2; 1334 } 1335 s.Sl = s.Sr = null; 1336 *ps = s; 1337 L2: 1338 sn = s.Sfunc.Foversym; 1339 s.Sfunc.Foversym = null; 1340 s = sn; 1341 } while (s); 1342 } 1343 else 1344 { 1345 if (!typematch(s.Stype,rover.Stype,0)) 1346 { 1347 // cpp_predefine() will define this again 1348 if (type_struct(rover.Stype) && 1349 rover.Sstruct.Sflags & STRpredef) 1350 { s.Sl = s.Sr = null; 1351 symbol_keep(s); 1352 } 1353 else 1354 synerr(EM_multiple_def,p); // already defined 1355 } 1356 } 1357 goto L1; 1358 } 1359 } 1360 ps = (cmp < 0) ? /* if we go down left side */ 1361 &rover.Sl : 1362 &rover.Sr; 1363 } 1364 { 1365 s.Sl = s.Sr = null; 1366 *ps = s; 1367 } 1368 } 1369 L1: 1370 symboltable_hydrate(sl,parent); 1371 s = sr; 1372 } 1373 } 1374 1375 } 1376 1377 1378 /************************************ 1379 * Hydrate/dehydrate an mptr_t. 1380 */ 1381 1382 static if (HYDRATE) 1383 { 1384 @trusted 1385 private void mptr_hydrate(mptr_t **pm) 1386 { mptr_t *m; 1387 1388 m = cast(mptr_t *) ph_hydrate(cast(void**)pm); 1389 symbol_hydrate(&m.MPf); 1390 symbol_hydrate(&m.MPparent); 1391 } 1392 } 1393 1394 static if (DEHYDRATE) 1395 { 1396 @trusted 1397 private void mptr_dehydrate(mptr_t **pm) 1398 { mptr_t *m; 1399 1400 m = *pm; 1401 if (m && !isdehydrated(m)) 1402 { 1403 ph_dehydrate(pm); 1404 version (DEBUG_XSYMGEN) 1405 { 1406 if (xsym_gen && ph_in_head(m.MPf)) 1407 ph_dehydrate(&m.MPf); 1408 else 1409 symbol_dehydrate(&m.MPf); 1410 } 1411 else 1412 symbol_dehydrate(&m.MPf); 1413 1414 symbol_dehydrate(&m.MPparent); 1415 } 1416 } 1417 } 1418 1419 /************************************ 1420 * Hydrate/dehydrate a baseclass_t. 1421 */ 1422 1423 static if (HYDRATE) 1424 { 1425 @trusted 1426 private void baseclass_hydrate(baseclass_t **pb) 1427 { baseclass_t *b; 1428 1429 assert(pb); 1430 while (isdehydrated(*pb)) 1431 { 1432 b = cast(baseclass_t *) ph_hydrate(cast(void**)pb); 1433 1434 ph_hydrate(cast(void**)&b.BCbase); 1435 ph_hydrate(cast(void**)&b.BCpbase); 1436 list_hydrate(&b.BCpublics,cast(list_free_fp)&symbol_hydrate); 1437 list_hydrate(&b.BCmptrlist,cast(list_free_fp)&mptr_hydrate); 1438 symbol_hydrate(&b.BCvtbl); 1439 Classsym_hydrate(&b.BCparent); 1440 1441 pb = &b.BCnext; 1442 } 1443 } 1444 } 1445 1446 /********************************** 1447 * Dehydrate a baseclass_t. 1448 */ 1449 1450 static if (DEHYDRATE) 1451 { 1452 @trusted 1453 private void baseclass_dehydrate(baseclass_t **pb) 1454 { baseclass_t *b; 1455 1456 while ((b = *pb) != null && !isdehydrated(b)) 1457 { 1458 ph_dehydrate(pb); 1459 1460 version (DEBUG_XSYMGEN) 1461 { 1462 if (xsym_gen && ph_in_head(b)) 1463 return; 1464 } 1465 1466 ph_dehydrate(&b.BCbase); 1467 ph_dehydrate(&b.BCpbase); 1468 list_dehydrate(&b.BCpublics,cast(list_free_fp)&symbol_dehydrate); 1469 list_dehydrate(&b.BCmptrlist,cast(list_free_fp)&mptr_dehydrate); 1470 symbol_dehydrate(&b.BCvtbl); 1471 Classsym_dehydrate(&b.BCparent); 1472 1473 pb = &b.BCnext; 1474 } 1475 } 1476 } 1477 1478 /*************************** 1479 * Look down baseclass list to find sbase. 1480 * Returns: 1481 * null not found 1482 * pointer to baseclass 1483 */ 1484 1485 baseclass_t *baseclass_find(baseclass_t *bm,Classsym *sbase) 1486 { 1487 symbol_debug(sbase); 1488 for (; bm; bm = bm.BCnext) 1489 if (bm.BCbase == sbase) 1490 break; 1491 return bm; 1492 } 1493 1494 @trusted 1495 baseclass_t *baseclass_find_nest(baseclass_t *bm,Classsym *sbase) 1496 { 1497 symbol_debug(sbase); 1498 for (; bm; bm = bm.BCnext) 1499 { 1500 if (bm.BCbase == sbase || 1501 baseclass_find_nest(bm.BCbase.Sstruct.Sbase, sbase)) 1502 break; 1503 } 1504 return bm; 1505 } 1506 1507 /****************************** 1508 * Calculate number of baseclasses in list. 1509 */ 1510 1511 int baseclass_nitems(baseclass_t *b) 1512 { int i; 1513 1514 for (i = 0; b; b = b.BCnext) 1515 i++; 1516 return i; 1517 } 1518 1519 /************************************* 1520 * Reset Symbol so that it's now an "extern" to the next obj file being created. 1521 */ 1522 void symbol_reset(Symbol *s) 1523 { 1524 s.Soffset = 0; 1525 s.Sxtrnnum = 0; 1526 s.Stypidx = 0; 1527 s.Sflags &= ~(STRoutdef | SFLweak); 1528 s.Sdw_ref_idx = 0; 1529 if (s.Sclass == SC.global || s.Sclass == SC.comdat || 1530 s.Sfl == FLudata || s.Sclass == SC.static_) 1531 { s.Sclass = SC.extern_; 1532 s.Sfl = FLextern; 1533 } 1534 } 1535 1536 /**************************************** 1537 * Determine pointer type needed to access a Symbol, 1538 * essentially what type an OPrelconst should get 1539 * for that Symbol. 1540 * Params: 1541 * s = pointer to Symbol 1542 * Returns: 1543 * pointer type to access it 1544 */ 1545 tym_t symbol_pointerType(const Symbol* s) 1546 { 1547 return s.Stype.Tty & mTYimmutable ? TYimmutPtr : TYnptr; 1548 }