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