1 /** 2 * Convert a D symbol to a symbol the linker understands (with mangled name). 3 * 4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/tocsym.d, _tocsym.d) 8 * Documentation: https://dlang.org/phobos/dmd_tocsym.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/tocsym.d 10 */ 11 12 module dmd.tocsym; 13 14 import core.stdc.stdio; 15 import core.stdc.string; 16 17 import dmd.root.array; 18 import dmd.root.complex; 19 import dmd.root.rmem; 20 21 import dmd.aggregate; 22 import dmd.arraytypes; 23 import dmd.astenums; 24 import dmd.ctfeexpr; 25 import dmd.declaration; 26 import dmd.dclass; 27 import dmd.denum; 28 import dmd.dmodule; 29 import dmd.dstruct; 30 import dmd.dsymbol; 31 import dmd.dtemplate; 32 import dmd.e2ir; 33 import dmd.errors; 34 import dmd.expression; 35 import dmd.func; 36 import dmd.globals; 37 import dmd.glue; 38 import dmd.identifier; 39 import dmd.id; 40 import dmd.init; 41 import dmd.location; 42 import dmd.mtype; 43 import dmd.target; 44 import dmd.toctype; 45 import dmd.todt; 46 import dmd.toir; 47 import dmd.tokens; 48 import dmd.typinf; 49 import dmd.visitor; 50 import dmd.dmangle; 51 52 import dmd.backend.cdef; 53 import dmd.backend.cc; 54 import dmd.backend.dt; 55 import dmd.backend.type; 56 import dmd.backend.global; 57 import dmd.backend.oper; 58 import dmd.backend.cgcv; 59 import dmd.backend.symtab; 60 import dmd.backend.ty; 61 62 extern (C++): 63 64 65 /************************************* 66 * Helper 67 */ 68 69 Symbol *toSymbolX(Dsymbol ds, const(char)* prefix, SC sclass, type *t, const(char)* suffix) 70 { 71 //printf("Dsymbol::toSymbolX('%s')\n", prefix); 72 import dmd.common.string : SmallBuffer; 73 import dmd.common.outbuffer : OutBuffer; 74 75 OutBuffer buf; 76 mangleToBuffer(ds, &buf); 77 size_t nlen = buf.length; 78 const(char)* n = buf.peekChars(); 79 assert(n); 80 81 import core.stdc.string : strlen; 82 size_t prefixlen = strlen(prefix); 83 size_t suffixlen = strlen(suffix); 84 size_t idlen = 2 + nlen + size_t.sizeof * 3 + prefixlen + suffixlen + 1; 85 86 char[64] idbuf = void; 87 auto sb = SmallBuffer!(char)(idlen, idbuf[]); 88 char *id = sb.ptr; 89 90 int nwritten = snprintf(id, idlen, "_D%.*s%d%.*s%.*s", 91 cast(int)nlen, n, 92 cast(int)prefixlen, cast(int)prefixlen, prefix, 93 cast(int)suffixlen, suffix); 94 assert(cast(uint)nwritten < idlen); // nwritten does not include the terminating 0 char 95 96 Symbol *s = symbol_name(id[0 .. nwritten], sclass, t); 97 98 //printf("-Dsymbol::toSymbolX() %s\n", id); 99 return s; 100 } 101 102 /************************************* 103 */ 104 105 Symbol *toSymbol(Dsymbol s) 106 { 107 extern (C++) static final class ToSymbol : Visitor 108 { 109 alias visit = Visitor.visit; 110 111 Symbol *result; 112 113 this() scope 114 { 115 result = null; 116 } 117 118 override void visit(Dsymbol s) 119 { 120 printf("Dsymbol.toSymbol() '%s', kind = '%s'\n", s.toChars(), s.kind()); 121 assert(0); // BUG: implement 122 } 123 124 override void visit(SymbolDeclaration sd) 125 { 126 result = toInitializer(sd.dsym); 127 } 128 129 override void visit(VarDeclaration vd) 130 { 131 //printf("VarDeclaration.toSymbol(%s)\n", vd.toChars()); 132 if (vd.needThis()) 133 fprintf(stderr, "VarDeclaration.toSymbol(%s) needThis kind: %s\n", vd.toPrettyChars(), vd.kind()); 134 assert(!vd.needThis()); 135 136 import dmd.common.outbuffer : OutBuffer; 137 OutBuffer buf; 138 bool isNRVO = false; 139 const(char)[] id = vd.ident.toString(); 140 if (vd.isDataseg()) 141 { 142 mangleToBuffer(vd, &buf); 143 id = buf[]; 144 } 145 else 146 { 147 if (FuncDeclaration fd = vd.toParent2().isFuncDeclaration()) 148 { 149 if (fd.isNRVO() && fd.nrvo_var == vd) 150 { 151 buf.writestring("__nrvo_"); 152 buf.writestring(id); 153 id = buf[]; 154 isNRVO = true; 155 } 156 } 157 } 158 Symbol *s = symbol_calloc(id); 159 s.Salignment = vd.alignment.isDefault() ? -1 : vd.alignment.get(); 160 if (vd.storage_class & STC.temp) 161 s.Sflags |= SFLartifical; 162 if (isNRVO) 163 s.Sflags |= SFLnodebug; 164 if (vd.adFlags & Declaration.nounderscore) 165 s.Sflags |= SFLnounderscore; 166 167 TYPE *t; 168 if (vd.storage_class & (STC.out_ | STC.ref_)) 169 { 170 t = type_allocn(TYnref, Type_toCtype(vd.type)); 171 t.Tcount++; 172 } 173 else if (vd.storage_class & STC.lazy_) 174 { 175 if (target.os == Target.OS.Windows && target.is64bit && vd.isParameter()) 176 t = type_fake(TYnptr); 177 else 178 t = type_fake(TYdelegate); // Tdelegate as C type 179 t.Tcount++; 180 } 181 else if (vd.isParameter() && ISX64REF(vd)) 182 { 183 t = type_allocn(TYnref, Type_toCtype(vd.type)); 184 t.Tcount++; 185 } 186 else 187 { 188 t = Type_toCtype(vd.type); 189 t.Tcount++; 190 } 191 192 /* Even if a symbol is immutable, if it has a constructor then 193 * the constructor mutates it. Remember that constructors can 194 * be inlined into other code. 195 * Just can't rely on it being immutable. 196 */ 197 if (t.Tty & (mTYimmutable | mTYconst)) 198 { 199 if (vd.ctorinit) 200 { 201 /* It was initialized in a constructor, so not really immutable 202 * as far as the optimizer is concerned, as in this case: 203 * immutable int x; 204 * shared static this() { x += 3; } 205 */ 206 t = type_setty(&t, t.Tty & ~(mTYimmutable | mTYconst)); 207 } 208 else if (auto ts = vd.type.isTypeStruct()) 209 { 210 if (!ts.isMutable() && ts.sym.ctor) 211 { 212 t = type_setty(&t, t.Tty & ~(mTYimmutable | mTYconst)); 213 } 214 } 215 else if (auto tc = vd.type.isTypeClass()) 216 { 217 if (!tc.isMutable() && tc.sym.ctor) 218 { 219 t = type_setty(&t, t.Tty & ~(mTYimmutable | mTYconst)); 220 } 221 } 222 } 223 224 if (vd.isDataseg()) 225 { 226 if (vd.isThreadlocal() && !(vd.storage_class & STC.temp)) 227 { 228 /* Thread local storage 229 */ 230 auto ts = t; 231 ts.Tcount++; // make sure a different t is allocated 232 type_setty(&t, t.Tty | mTYthread); 233 ts.Tcount--; 234 235 if (config.objfmt == OBJ_MACH && _tysize[TYnptr] == 8) 236 s.Salignment = 2; 237 238 if (global.params.vtls) 239 { 240 message(vd.loc, "`%s` is thread local", vd.toChars()); 241 } 242 } 243 s.Sclass = SC.extern_; 244 s.Sfl = FLextern; 245 246 /* Make C static variables SCstatic 247 */ 248 if (vd.storage_class & STC.static_ && vd.isCsymbol()) 249 { 250 s.Sclass = SC.static_; 251 s.Sfl = FLdata; 252 } 253 254 /* if it's global or static, then it needs to have a qualified but unmangled name. 255 * This gives some explanation of the separation in treating name mangling. 256 * It applies to PDB format, but should apply to CV as PDB derives from CV. 257 * https://msdn.microsoft.com/en-us/library/ff553493%28VS.85%29.aspx 258 */ 259 s.prettyIdent = vd.toPrettyChars(true); 260 } 261 else 262 { 263 s.Sclass = SC.auto_; 264 s.Sfl = FLauto; 265 266 if (vd.nestedrefs.length) 267 { 268 /* Symbol is accessed by a nested function. Make sure 269 * it is not put in a register, and that the optimizer 270 * assumes it is modified across function calls and pointer 271 * dereferences. 272 */ 273 //printf("\tnested ref, not register\n"); 274 type_setcv(&t, t.Tty | mTYvolatile); 275 } 276 } 277 278 if (vd.storage_class & STC.volatile_) 279 { 280 type_setcv(&t, t.Tty | mTYvolatile); 281 } 282 283 mangle_t m = 0; 284 final switch (vd.resolvedLinkage()) 285 { 286 case LINK.windows: 287 m = target.is64bit ? mTYman_c : mTYman_std; 288 break; 289 290 case LINK.objc: 291 case LINK.c: 292 m = mTYman_c; 293 break; 294 295 case LINK.d: 296 m = mTYman_d; 297 break; 298 299 case LINK.cpp: 300 s.Sflags |= SFLpublic; 301 m = mTYman_cpp; 302 break; 303 304 case LINK.default_: 305 case LINK.system: 306 printf("linkage = %d, vd = %s %s @ [%s]\n", 307 vd._linkage, vd.kind(), vd.toChars(), vd.loc.toChars()); 308 assert(0); 309 } 310 311 type_setmangle(&t, m); 312 s.Stype = t; 313 314 s.lposscopestart = toSrcpos(vd.loc); 315 s.lnoscopeend = vd.endlinnum; 316 result = s; 317 } 318 319 override void visit(TypeInfoDeclaration tid) 320 { 321 //printf("TypeInfoDeclaration.toSymbol(%s), linkage = %d\n", tid.toChars(), tid.linkage); 322 assert(tid.tinfo.ty != Terror); 323 visit(tid.isVarDeclaration()); 324 } 325 326 override void visit(TypeInfoClassDeclaration ticd) 327 { 328 //printf("TypeInfoClassDeclaration.toSymbol(%s), linkage = %d\n", ticd.toChars(), ticd.linkage); 329 ticd.tinfo.isTypeClass().sym.accept(this); 330 } 331 332 override void visit(FuncAliasDeclaration fad) 333 { 334 fad.funcalias.accept(this); 335 } 336 337 override void visit(FuncDeclaration fd) 338 { 339 const(char)* id = mangleExact(fd); 340 341 //printf("FuncDeclaration.toSymbol(%s %s)\n", fd.kind(), fd.toChars()); 342 //printf("\tid = '%s'\n", id); 343 //printf("\ttype = %s\n", fd.type.toChars()); 344 auto s = symbol_calloc(id[0 .. strlen(id)]); 345 346 s.prettyIdent = fd.toPrettyChars(true); 347 348 /* Make C static functions SCstatic 349 */ 350 s.Sclass = (fd.storage_class & STC.static_ && fd.isCsymbol()) 351 ? SC.static_ 352 : SC.global; 353 354 symbol_func(s); 355 func_t *f = s.Sfunc; 356 if (fd.isVirtual() && fd.vtblIndex != -1) 357 f.Fflags |= Fvirtual; 358 else if (fd.isMember2() && fd.isStatic()) 359 f.Fflags |= Fstatic; 360 361 if (fd.isSafe()) 362 f.Fflags3 |= F3safe; 363 364 if (fd.inlining == PINLINE.default_ && global.params.useInline || 365 fd.inlining == PINLINE.always) 366 { 367 // this is copied from inline.d 368 if (!fd.fbody || 369 fd.ident == Id.ensure || 370 fd.skipCodegen || 371 (fd.ident == Id.require && 372 fd.toParent().isFuncDeclaration() && 373 fd.toParent().isFuncDeclaration().needThis()) || 374 (fd.isSynchronized() || 375 fd.isImportedSymbol() || 376 fd.hasNestedFrameRefs() || 377 (fd.isVirtual() && !fd.isFinalFunc()))) 378 { } 379 else 380 f.Fflags |= Finline; // inline this function if possible 381 } 382 383 if (fd.type.toBasetype().isTypeFunction().nextOf().isTypeNoreturn() || fd.noreturn) 384 s.Sflags |= SFLexit; // the function never returns 385 386 f.Fstartline = toSrcpos(fd.loc); 387 f.Fendline = fd.endloc.linnum ? toSrcpos(fd.endloc) : f.Fstartline; 388 389 auto t = Type_toCtype(fd.type); 390 if (fd.isNaked) 391 type_setty(&t, t.Tty | mTYnaked); 392 393 const msave = t.Tmangle; 394 if (fd.isMain()) 395 { 396 t.Tty = TYnfunc; 397 t.Tmangle = mTYman_c; 398 f.Fflags3 |= Fmain; 399 } 400 else 401 { 402 final switch (fd.resolvedLinkage()) 403 { 404 case LINK.windows: 405 t.Tmangle = target.is64bit ? mTYman_c : mTYman_std; 406 break; 407 408 case LINK.c: 409 if (fd.adFlags & Declaration.nounderscore) 410 s.Sflags |= SFLnounderscore; 411 goto case; 412 case LINK.objc: 413 t.Tmangle = mTYman_c; 414 break; 415 416 case LINK.d: 417 t.Tmangle = mTYman_d; 418 break; 419 case LINK.cpp: 420 s.Sflags |= SFLpublic; 421 /* Nested functions use the same calling convention as 422 * member functions, because both can be used as delegates. */ 423 if ((fd.isThis() || fd.isNested()) && !target.is64bit && target.os == Target.OS.Windows) 424 { 425 if ((cast(TypeFunction)fd.type).parameterList.varargs == VarArg.variadic) 426 { 427 t.Tty = TYnfunc; 428 } 429 else 430 { 431 t.Tty = TYmfunc; 432 } 433 } 434 t.Tmangle = mTYman_cpp; 435 break; 436 case LINK.default_: 437 case LINK.system: 438 printf("linkage = %d\n", fd._linkage); 439 assert(0); 440 } 441 } 442 443 if (msave) 444 assert(msave == t.Tmangle); 445 //printf("Tty = %x, mangle = x%x\n", t.Tty, t.Tmangle); 446 t.Tcount++; 447 s.Stype = t; 448 //s.Sfielddef = this; 449 450 result = s; 451 } 452 453 static type* getClassInfoCType() 454 { 455 __gshared Symbol* scc; 456 if (!scc) 457 scc = fake_classsym(Id.ClassInfo); 458 return scc.Stype; 459 } 460 461 /************************************* 462 * Create the "ClassInfo" symbol 463 */ 464 465 override void visit(ClassDeclaration cd) 466 { 467 auto s = toSymbolX(cd, "__Class", SC.extern_, getClassInfoCType(), "Z"); 468 s.Sfl = FLextern; 469 s.Sflags |= SFLnodebug; 470 result = s; 471 } 472 473 /************************************* 474 * Create the "InterfaceInfo" symbol 475 */ 476 477 override void visit(InterfaceDeclaration id) 478 { 479 auto s = toSymbolX(id, "__Interface", SC.extern_, getClassInfoCType(), "Z"); 480 s.Sfl = FLextern; 481 s.Sflags |= SFLnodebug; 482 result = s; 483 } 484 485 /************************************* 486 * Create the "ModuleInfo" symbol 487 */ 488 489 override void visit(Module m) 490 { 491 auto s = toSymbolX(m, "__ModuleInfo", SC.extern_, getClassInfoCType(), "Z"); 492 s.Sfl = FLextern; 493 s.Sflags |= SFLnodebug; 494 result = s; 495 } 496 } 497 498 if (s.csym) 499 return s.csym; 500 501 scope ToSymbol v = new ToSymbol(); 502 s.accept(v); 503 s.csym = v.result; 504 return v.result; 505 } 506 507 508 /************************************* 509 * Create Windows import symbol from backend Symbol. 510 * Params: 511 * sym = backend symbol 512 * loc = location for error message purposes 513 * Returns: 514 * import symbol 515 */ 516 517 private Symbol *createImport(Symbol *sym, Loc loc) 518 { 519 //printf("Dsymbol.createImport('%s')\n", sym.Sident.ptr); 520 const char* n = sym.Sident.ptr; 521 import core.stdc.stdlib : alloca; 522 const allocLen = 6 + strlen(n) + 1 + type_paramsize(sym.Stype).sizeof*3 + 1; 523 char *id = cast(char *) alloca(allocLen); 524 int idlen; 525 if (target.os & Target.OS.Posix) 526 { 527 error(loc, "could not generate import symbol for this platform"); 528 fatal(); 529 } 530 else if (sym.Stype.Tmangle == mTYman_std && tyfunc(sym.Stype.Tty)) 531 { 532 if (target.os == Target.OS.Windows && target.is64bit) 533 idlen = snprintf(id, allocLen, "__imp_%s",n); 534 else 535 idlen = snprintf(id, allocLen, "_imp__%s@%u",n,cast(uint)type_paramsize(sym.Stype)); 536 } 537 else 538 { 539 idlen = snprintf(id, allocLen, (target.os == Target.OS.Windows && target.is64bit) ? "__imp_%s" : (sym.Stype.Tmangle == mTYman_cpp) ? "_imp_%s" : "_imp__%s",n); 540 } 541 auto t = type_alloc(TYnptr | mTYconst); 542 t.Tnext = sym.Stype; 543 t.Tnext.Tcount++; 544 t.Tmangle = mTYman_c; 545 t.Tcount++; 546 auto s = symbol_calloc(id[0 .. idlen]); 547 s.Stype = t; 548 s.Sclass = SC.extern_; 549 s.Sfl = FLextern; 550 return s; 551 } 552 553 /********************************* 554 * Generate import symbol from symbol. 555 */ 556 557 Symbol *toImport(Declaration ds) 558 { 559 if (!ds.isym) 560 { 561 if (!ds.csym) 562 ds.csym = toSymbol(ds); 563 ds.isym = createImport(ds.csym, ds.loc); 564 } 565 return ds.isym; 566 } 567 568 /************************************* 569 * Thunks adjust the incoming 'this' pointer by 'offset'. 570 */ 571 572 Symbol *toThunkSymbol(FuncDeclaration fd, int offset) 573 { 574 Symbol *s = toSymbol(fd); 575 if (!offset) 576 return s; 577 578 if (retStyle(fd.type.isTypeFunction(), fd.needThis()) == RET.stack) 579 s.Sfunc.Fflags3 |= F3hiddenPtr; 580 581 s.Sfunc.Fflags &= ~Finline; // thunks are not real functions, don't inline them 582 583 __gshared int tmpnum; 584 const nameLen = 6 + tmpnum.sizeof * 3 + 1; 585 char[nameLen] name = void; 586 587 const len = snprintf(name.ptr,nameLen,"_THUNK%d",tmpnum++); 588 auto sthunk = symbol_name(name[0 .. len],SC.static_,fd.csym.Stype); 589 sthunk.Sflags |= SFLnodebug | SFLartifical; 590 sthunk.Sflags |= SFLimplem; 591 outthunk(sthunk, fd.csym, 0, TYnptr, -offset, -1, 0); 592 return sthunk; 593 } 594 595 596 /************************************** 597 * Fake a struct symbol. 598 */ 599 600 Classsym *fake_classsym(Identifier id) 601 { 602 auto t = type_struct_class(id.toChars(),8,0, 603 null,null, 604 false, false, true, false); 605 606 t.Ttag.Sstruct.Sflags = STRglobal; 607 t.Tflags |= TFsizeunknown | TFforward; 608 assert(t.Tmangle == 0); 609 t.Tmangle = mTYman_d; 610 return t.Ttag; 611 } 612 613 /************************************* 614 * This is accessible via the ClassData, but since it is frequently 615 * needed directly (like for rtti comparisons), make it directly accessible. 616 */ 617 618 Symbol *toVtblSymbol(ClassDeclaration cd, bool genCsymbol = true) 619 { 620 if (!cd.vtblsym || !cd.vtblsym.csym) 621 { 622 if (!cd.csym && genCsymbol) 623 toSymbol(cd); 624 625 auto t = type_allocn(TYnptr | mTYconst, tstypes[TYvoid]); 626 t.Tmangle = mTYman_d; 627 auto s = toSymbolX(cd, "__vtbl", SC.extern_, t, "Z"); 628 s.Sflags |= SFLnodebug; 629 s.Sfl = FLextern; 630 631 auto vtbl = cd.vtblSymbol(); 632 vtbl.csym = s; 633 } 634 return cd.vtblsym.csym; 635 } 636 637 /********************************** 638 * Create the static initializer for the struct/class. 639 */ 640 641 Symbol *toInitializer(AggregateDeclaration ad) 642 { 643 //printf("toInitializer() %s\n", ad.toChars()); 644 if (!ad.sinit) 645 { 646 static structalign_t alignOf(Type t) 647 { 648 const explicitAlignment = t.alignment(); 649 if (!explicitAlignment.isDefault()) // if overriding default alignment 650 return explicitAlignment; 651 652 // Use the default alignment for type t 653 structalign_t sa; 654 sa.set(t.alignsize()); 655 return sa; 656 } 657 658 auto sd = ad.isStructDeclaration(); 659 if (sd && 660 alignOf(sd.type).get() <= 16 && 661 sd.type.size() <= 128 && 662 sd.zeroInit && 663 config.objfmt != OBJ_MACH && // same reason as in toobj.d toObjFile() 664 !(config.objfmt == OBJ_MSCOFF && !target.is64bit)) // -m32mscoff relocations are wrong 665 { 666 auto bzsave = bzeroSymbol; 667 ad.sinit = getBzeroSymbol(); 668 669 // Ensure emitted only once per object file 670 if (bzsave && bzeroSymbol != bzsave) 671 assert(0); 672 } 673 else 674 { 675 auto stag = fake_classsym(Id.ClassInfo); 676 677 Symbol* s; 678 679 Module m = ad.getModule(); 680 if (m.filetype == FileType.c) 681 { 682 /* For ImportC structs, the module names are stripped from the mangled name. 683 * This leads to name collisions. Add the module name back in. 684 */ 685 import dmd.common.outbuffer : OutBuffer; 686 OutBuffer buf; 687 buf.writestring("__init"); 688 buf.writestring(m.toChars()); 689 s = toSymbolX(ad, buf.peekChars(), SC.extern_, stag.Stype, "Z"); 690 } 691 else 692 s = toSymbolX(ad, "__init", SC.extern_, stag.Stype, "Z"); 693 694 s.Sfl = FLextern; 695 s.Sflags |= SFLnodebug; 696 if (sd) 697 s.Salignment = sd.alignment.isDefault() ? -1 : sd.alignment.get(); 698 ad.sinit = s; 699 } 700 } 701 return cast(Symbol*)ad.sinit; 702 } 703 704 Symbol *toInitializer(EnumDeclaration ed) 705 { 706 if (!ed.sinit) 707 { 708 auto stag = fake_classsym(Id.ClassInfo); 709 assert(ed.ident); 710 auto s = toSymbolX(ed, "__init", SC.extern_, stag.Stype, "Z"); 711 s.Sfl = FLextern; 712 s.Sflags |= SFLnodebug; 713 ed.sinit = s; 714 } 715 return ed.sinit; 716 } 717 718 719 /******************************************** 720 * Determine the right symbol to look up 721 * an associative array element. 722 * Input: 723 * flags 0 don't add value signature 724 * 1 add value signature 725 */ 726 727 Symbol *aaGetSymbol(TypeAArray taa, const(char)* func, int flags) 728 { 729 assert((flags & ~1) == 0); 730 731 // Dumb linear symbol table - should use associative array! 732 __gshared Symbol*[] sarray; 733 734 //printf("aaGetSymbol(func = '%s', flags = %d, key = %p)\n", func, flags, key); 735 import core.stdc.stdlib : alloca; 736 const allocLen = 3 + strlen(func) + 1; 737 auto id = cast(char *)alloca(allocLen); 738 const idlen = snprintf(id, allocLen, "_aa%s", func); 739 740 // See if symbol is already in sarray 741 foreach (s; sarray) 742 { 743 if (strcmp(id, s.Sident.ptr) == 0) 744 { 745 return s; // use existing Symbol 746 } 747 } 748 749 // Create new Symbol 750 751 auto s = symbol_calloc(id[0 .. idlen]); 752 s.Sclass = SC.extern_; 753 s.Ssymnum = SYMIDX.max; 754 symbol_func(s); 755 756 auto t = type_function(TYnfunc, null, false, Type_toCtype(taa.next)); 757 t.Tmangle = mTYman_c; 758 s.Stype = t; 759 760 sarray ~= s; // remember it 761 return s; 762 } 763 764 /*****************************************************/ 765 /* CTFE stuff */ 766 /*****************************************************/ 767 768 Symbol* toSymbol(StructLiteralExp sle) 769 { 770 //printf("toSymbol() %p.sym: %p\n", sle, sle.sym); 771 if (sle.sym) 772 return sle.sym; 773 auto t = type_alloc(TYint); 774 t.Tcount++; 775 auto s = symbol_calloc("internal"); 776 s.Sclass = SC.static_; 777 s.Sfl = FLextern; 778 s.Sflags |= SFLnodebug; 779 s.Stype = t; 780 sle.sym = s; 781 auto dtb = DtBuilder(0); 782 Expression_toDt(sle, dtb); 783 s.Sdt = dtb.finish(); 784 outdata(s); 785 return sle.sym; 786 } 787 788 Symbol* toSymbol(ClassReferenceExp cre) 789 { 790 //printf("toSymbol() %p.value.sym: %p\n", cre, cre.value.sym); 791 if (cre.value.origin.sym) 792 return cre.value.origin.sym; 793 auto t = type_alloc(TYint); 794 t.Tcount++; 795 auto s = symbol_calloc("internal"); 796 s.Sclass = SC.static_; 797 s.Sfl = FLextern; 798 s.Sflags |= SFLnodebug; 799 s.Stype = t; 800 cre.value.sym = s; 801 cre.value.origin.sym = s; 802 auto dtb = DtBuilder(0); 803 ClassReferenceExp_toInstanceDt(cre, dtb); 804 s.Sdt = dtb.finish(); 805 outdata(s); 806 return cre.value.sym; 807 } 808 809 /************************************** 810 * For C++ class cd, generate an instance of __cpp_type_info_ptr 811 * and populate it with a pointer to the C++ type info. 812 * Params: 813 * cd = C++ class 814 * Returns: 815 * symbol of instance of __cpp_type_info_ptr 816 */ 817 Symbol* toSymbolCpp(ClassDeclaration cd) 818 { 819 assert(cd.isCPPclass()); 820 821 /* For the symbol std::exception, the type info is _ZTISt9exception 822 */ 823 if (!cd.cpp_type_info_ptr_sym) 824 { 825 __gshared Symbol *scpp; 826 if (!scpp) 827 scpp = fake_classsym(Id.cpp_type_info_ptr); 828 Symbol *s = toSymbolX(cd, "_cpp_type_info_ptr", SC.comdat, scpp.Stype, ""); 829 s.Sfl = FLdata; 830 s.Sflags |= SFLnodebug; 831 auto dtb = DtBuilder(0); 832 cpp_type_info_ptr_toDt(cd, dtb); 833 s.Sdt = dtb.finish(); 834 outdata(s); 835 cd.cpp_type_info_ptr_sym = s; 836 } 837 return cd.cpp_type_info_ptr_sym; 838 } 839 840 /********************************** 841 * Generate Symbol of C++ type info for C++ class cd. 842 * Params: 843 * cd = C++ class 844 * Returns: 845 * Symbol of cd's rtti type info 846 */ 847 Symbol *toSymbolCppTypeInfo(ClassDeclaration cd) 848 { 849 const id = target.cpp.typeInfoMangle(cd); 850 auto s = symbol_calloc(id[0 .. strlen(id)]); 851 s.Sclass = SC.extern_; 852 s.Sfl = FLextern; // C++ code will provide the definition 853 s.Sflags |= SFLnodebug; 854 auto t = type_fake(TYnptr); 855 t.Tcount++; 856 s.Stype = t; 857 return s; 858 } 859 860 /********************************** 861 * Converts a Loc to backend Srcpos 862 * Params: 863 * loc = Source code location 864 * Returns: 865 * Srcpos backend struct corresponding to the given location 866 */ 867 Srcpos toSrcpos(Loc loc) 868 { 869 return Srcpos.create(loc.filename, loc.linnum, loc.charnum); 870 }