1 /** 2 * Generate the object file for function declarations and critical sections. 3 * 4 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/glue.d, _glue.d) 8 * Documentation: $(LINK https://dlang.org/phobos/dmd_glue.html) 9 * Coverage: $(LINK https://codecov.io/gh/dlang/dmd/src/master/src/dmd/glue.d) 10 */ 11 12 module dmd.glue; 13 14 import core.stdc.stdio; 15 import core.stdc..string; 16 import core.stdc.stdlib; 17 18 import dmd.root.array; 19 import dmd.root.file; 20 import dmd.root.filename; 21 import dmd.root.outbuffer; 22 import dmd.root.rmem; 23 import dmd.root..string; 24 25 import dmd.backend.cdef; 26 import dmd.backend.cc; 27 import dmd.backend.code; 28 import dmd.backend.dt; 29 import dmd.backend.el; 30 import dmd.backend.global; 31 import dmd.backend.obj; 32 import dmd.backend.oper; 33 import dmd.backend.outbuf; 34 import dmd.backend.rtlsym; 35 import dmd.backend.ty; 36 import dmd.backend.type; 37 38 import dmd.aggregate; 39 import dmd.arraytypes; 40 import dmd.blockexit; 41 import dmd.dclass; 42 import dmd.declaration; 43 import dmd.dmangle; 44 import dmd.dmodule; 45 import dmd.dstruct; 46 import dmd.dsymbol; 47 import dmd.dtemplate; 48 import dmd.e2ir; 49 import dmd.errors; 50 import dmd.expression; 51 import dmd.func; 52 import dmd.globals; 53 import dmd.identifier; 54 import dmd.id; 55 import dmd.lib; 56 import dmd.mtype; 57 import dmd.objc_glue; 58 import dmd.s2ir; 59 import dmd.statement; 60 import dmd.target; 61 import dmd.tocsym; 62 import dmd.toctype; 63 import dmd.toir; 64 import dmd.toobj; 65 import dmd.typesem; 66 import dmd.utils; 67 68 extern (C++): 69 70 alias symbols = Array!(Symbol*); 71 alias toSymbol = dmd.tocsym.toSymbol; 72 73 //extern 74 __gshared 75 { 76 elem *eictor; 77 Symbol *ictorlocalgot; 78 Symbol* bzeroSymbol; /// common location for immutable zeros 79 symbols sctors; 80 StaticDtorDeclarations ectorgates; 81 symbols sdtors; 82 symbols stests; 83 84 symbols ssharedctors; 85 SharedStaticDtorDeclarations esharedctorgates; 86 symbols sshareddtors; 87 88 const(char)* lastmname; 89 } 90 91 92 /************************************** 93 * Append s to list of object files to generate later. 94 */ 95 96 __gshared Dsymbols obj_symbols_towrite; 97 98 void obj_append(Dsymbol s) 99 { 100 //printf("deferred: %s\n", s.toChars()); 101 obj_symbols_towrite.push(s); 102 } 103 104 void obj_write_deferred(Library library) 105 { 106 for (size_t i = 0; i < obj_symbols_towrite.dim; i++) 107 { 108 Dsymbol s = obj_symbols_towrite[i]; 109 Module m = s.getModule(); 110 111 const(char)* mname; 112 if (m) 113 { 114 mname = m.srcfile.toChars(); 115 lastmname = mname; 116 } 117 else 118 { 119 //mname = s.ident.toChars(); 120 mname = lastmname; 121 assert(mname); 122 } 123 124 obj_start(mname); 125 126 __gshared int count; 127 count++; // sequence for generating names 128 129 /* Create a module that's a doppelganger of m, with just 130 * enough to be able to create the moduleinfo. 131 */ 132 OutBuffer idbuf; 133 idbuf.printf("%s.%d", m ? m.ident.toChars() : mname, count); 134 135 if (!m) 136 { 137 // it doesn't make sense to make up a module if we don't know where to put the symbol 138 // so output it into it's own object file without ModuleInfo 139 objmod.initfile(idbuf.peekChars(), null, mname); 140 toObjFile(s, false); 141 objmod.termfile(); 142 } 143 else 144 { 145 Identifier id = Identifier.create(idbuf.extractChars()); 146 147 Module md = new Module(mname.toDString, id, 0, 0); 148 md.members = new Dsymbols(); 149 md.members.push(s); // its only 'member' is s 150 md.doppelganger = 1; // identify this module as doppelganger 151 md.md = m.md; 152 md.aimports.push(m); // it only 'imports' m 153 154 genObjFile(md, false); 155 } 156 157 /* Set object file name to be source name with sequence number, 158 * as mangled symbol names get way too long. 159 */ 160 const(char)* fname = FileName.removeExt(mname); 161 OutBuffer namebuf; 162 uint hash = 0; 163 for (const(char)* p = s.toChars(); *p; p++) 164 hash += *p; 165 namebuf.printf("%s_%x_%x.%.*s", fname, count, hash, 166 cast(int)global.obj_ext.length, global.obj_ext.ptr); 167 FileName.free(cast(char *)fname); 168 fname = namebuf.extractChars(); 169 170 //printf("writing '%s'\n", fname); 171 obj_end(library, fname); 172 } 173 obj_symbols_towrite.dim = 0; 174 } 175 176 177 /*********************************************** 178 * Generate function that calls array of functions and gates. 179 * Params: 180 * m = module symbol (for name mangling purposes) 181 * sctors = array of functions 182 * ectorgates = array of gates 183 * id = identifier string for generator function 184 * Returns: 185 * function Symbol generated 186 */ 187 188 private Symbol *callFuncsAndGates(Module m, symbols *sctors, StaticDtorDeclarations *ectorgates, 189 const(char)* id) 190 { 191 Symbol *sctor = null; 192 193 if ((sctors && sctors.dim) || 194 (ectorgates && ectorgates.dim)) 195 { 196 __gshared type *t; 197 if (!t) 198 { 199 /* t will be the type of the functions generated: 200 * extern (C) void func(); 201 */ 202 t = type_function(TYnfunc, null, false, tstypes[TYvoid]); 203 t.Tmangle = mTYman_c; 204 } 205 206 localgot = null; 207 sctor = toSymbolX(m, id, SCglobal, t, "FZv"); 208 cstate.CSpsymtab = &sctor.Sfunc.Flocsym; 209 elem *ector = null; 210 211 if (ectorgates) 212 { 213 foreach (f; *ectorgates) 214 { 215 Symbol *s = toSymbol(f.vgate); 216 elem *e = el_var(s); 217 e = el_bin(OPaddass, TYint, e, el_long(TYint, 1)); 218 ector = el_combine(ector, e); 219 } 220 } 221 222 if (sctors) 223 { 224 foreach (s; *sctors) 225 { 226 elem *e = el_una(OPucall, TYvoid, el_var(s)); 227 ector = el_combine(ector, e); 228 } 229 } 230 231 block *b = block_calloc(); 232 b.BC = BCret; 233 b.Belem = ector; 234 sctor.Sfunc.Fstartline.Sfilename = m.arg.xarraydup.ptr; 235 sctor.Sfunc.Fstartblock = b; 236 writefunc(sctor); 237 } 238 return sctor; 239 } 240 241 /************************************** 242 * Prepare for generating obj file. 243 */ 244 245 __gshared Outbuffer objbuf; 246 247 void obj_start(const(char)* srcfile) 248 { 249 //printf("obj_start()\n"); 250 251 bzeroSymbol = null; 252 rtlsym_reset(); 253 clearStringTab(); 254 255 version (Windows) 256 { 257 // Produce Ms COFF files for 64 bit code, OMF for 32 bit code 258 assert(objbuf.length() == 0); 259 objmod = global.params.mscoff ? MsCoffObj_init(&objbuf, srcfile, null) 260 : OmfObj_init(&objbuf, srcfile, null); 261 } 262 else 263 { 264 objmod = Obj.init(&objbuf, srcfile, null); 265 } 266 267 el_reset(); 268 cg87_reset(); 269 out_reset(); 270 } 271 272 273 void obj_end(Library library, const(char)* objfilename) 274 { 275 objmod.term(objfilename); 276 //delete objmod; 277 objmod = null; 278 279 if (library) 280 { 281 // Transfer ownership of image buffer to library 282 library.addObject(objfilename.toDString(), objbuf.extractSlice[]); 283 } 284 else 285 { 286 //printf("write obj %s\n", objfilename); 287 writeFile(Loc.initial, objfilename.toDString, objbuf[]); 288 } 289 objbuf.dtor(); 290 } 291 292 bool obj_includelib(const(char)* name) nothrow 293 { 294 return objmod.includelib(name); 295 } 296 297 extern(D) bool obj_includelib(const(char)[] name) nothrow 298 { 299 return name.toCStringThen!(n => obj_includelib(n.ptr)); 300 } 301 302 void obj_startaddress(Symbol *s) 303 { 304 return objmod.startaddress(s); 305 } 306 307 bool obj_linkerdirective(const(char)* directive) 308 { 309 return objmod.linkerdirective(directive); 310 } 311 312 313 /************************************** 314 * Generate .obj file for Module. 315 */ 316 317 void genObjFile(Module m, bool multiobj) 318 { 319 //EEcontext *ee = env.getEEcontext(); 320 321 //printf("Module.genobjfile(multiobj = %d) %s\n", multiobj, m.toChars()); 322 323 lastmname = m.srcfile.toChars(); 324 325 objmod.initfile(lastmname, null, m.toPrettyChars()); 326 327 eictor = null; 328 ictorlocalgot = null; 329 sctors.setDim(0); 330 ectorgates.setDim(0); 331 sdtors.setDim(0); 332 ssharedctors.setDim(0); 333 esharedctorgates.setDim(0); 334 sshareddtors.setDim(0); 335 stests.setDim(0); 336 337 if (m.doppelganger) 338 { 339 /* Generate a reference to the moduleinfo, so the module constructors 340 * and destructors get linked in. 341 */ 342 Module mod = m.aimports[0]; 343 assert(mod); 344 if (mod.sictor || mod.sctor || mod.sdtor || mod.ssharedctor || mod.sshareddtor) 345 { 346 Symbol *s = toSymbol(mod); 347 //objextern(s); 348 //if (!s.Sxtrnnum) objextdef(s.Sident); 349 if (!s.Sxtrnnum) 350 { 351 //printf("%s\n", s.Sident); 352 //#if 0 /* This should work, but causes optlink to fail in common/newlib.asm */ 353 // objextdef(s.Sident); 354 //#else 355 Symbol *sref = symbol_generate(SCstatic, type_fake(TYnptr)); 356 sref.Sfl = FLdata; 357 auto dtb = DtBuilder(0); 358 dtb.xoff(s, 0, TYnptr); 359 sref.Sdt = dtb.finish(); 360 outdata(sref); 361 //#endif 362 } 363 } 364 } 365 366 if (global.params.cov) 367 { 368 /* Create coverage identifier: 369 * uint[numlines] __coverage; 370 */ 371 m.cov = toSymbolX(m, "__coverage", SCstatic, type_fake(TYint), "Z"); 372 m.cov.Sflags |= SFLhidden; 373 m.cov.Stype.Tmangle = mTYman_d; 374 m.cov.Sfl = FLdata; 375 376 auto dtb = DtBuilder(0); 377 dtb.nzeros(4 * m.numlines); 378 m.cov.Sdt = dtb.finish(); 379 380 outdata(m.cov); 381 382 m.covb = cast(uint *)calloc((m.numlines + 32) / 32, (*m.covb).sizeof); 383 } 384 385 for (int i = 0; i < m.members.dim; i++) 386 { 387 auto member = (*m.members)[i]; 388 //printf("toObjFile %s %s\n", member.kind(), member.toChars()); 389 toObjFile(member, multiobj); 390 } 391 392 if (global.params.cov) 393 { 394 /* Generate 395 * private bit[numlines] __bcoverage; 396 */ 397 Symbol *bcov = symbol_calloc("__bcoverage"); 398 bcov.Stype = type_fake(TYuint); 399 bcov.Stype.Tcount++; 400 bcov.Sclass = SCstatic; 401 bcov.Sfl = FLdata; 402 403 auto dtb = DtBuilder(0); 404 dtb.nbytes((m.numlines + 32) / 32 * (*m.covb).sizeof, cast(char *)m.covb); 405 bcov.Sdt = dtb.finish(); 406 407 outdata(bcov); 408 409 free(m.covb); 410 m.covb = null; 411 412 /* Generate: 413 * _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename); 414 * and prepend it to the static constructor. 415 */ 416 417 /* t will be the type of the functions generated: 418 * extern (C) void func(); 419 */ 420 type *t = type_function(TYnfunc, null, false, tstypes[TYvoid]); 421 t.Tmangle = mTYman_c; 422 423 m.sictor = toSymbolX(m, "__modictor", SCglobal, t, "FZv"); 424 cstate.CSpsymtab = &m.sictor.Sfunc.Flocsym; 425 localgot = ictorlocalgot; 426 427 elem *ecov = el_pair(TYdarray, el_long(TYsize_t, m.numlines), el_ptr(m.cov)); 428 elem *ebcov = el_pair(TYdarray, el_long(TYsize_t, m.numlines), el_ptr(bcov)); 429 430 if (config.exe == EX_WIN64) 431 { 432 ecov = addressElem(ecov, Type.tvoid.arrayOf(), false); 433 ebcov = addressElem(ebcov, Type.tvoid.arrayOf(), false); 434 } 435 436 elem *efilename = toEfilename(m); 437 if (config.exe == EX_WIN64) 438 efilename = addressElem(efilename, Type.tstring, true); 439 440 elem *e = el_params( 441 el_long(TYuchar, global.params.covPercent), 442 ecov, 443 ebcov, 444 efilename, 445 null); 446 e = el_bin(OPcall, TYvoid, el_var(getRtlsym(RTLSYM_DCOVER2)), e); 447 eictor = el_combine(e, eictor); 448 ictorlocalgot = localgot; 449 } 450 451 // If coverage / static constructor / destructor / unittest calls 452 if (eictor || sctors.dim || ectorgates.dim || sdtors.dim || 453 ssharedctors.dim || esharedctorgates.dim || sshareddtors.dim || stests.dim) 454 { 455 if (eictor) 456 { 457 localgot = ictorlocalgot; 458 459 block *b = block_calloc(); 460 b.BC = BCret; 461 b.Belem = eictor; 462 m.sictor.Sfunc.Fstartline.Sfilename = m.arg.xarraydup.ptr; 463 m.sictor.Sfunc.Fstartblock = b; 464 writefunc(m.sictor); 465 } 466 467 m.sctor = callFuncsAndGates(m, &sctors, &ectorgates, "__modctor"); 468 m.sdtor = callFuncsAndGates(m, &sdtors, null, "__moddtor"); 469 470 m.ssharedctor = callFuncsAndGates(m, &ssharedctors, cast(StaticDtorDeclarations *)&esharedctorgates, "__modsharedctor"); 471 m.sshareddtor = callFuncsAndGates(m, &sshareddtors, null, "__modshareddtor"); 472 m.stest = callFuncsAndGates(m, &stests, null, "__modtest"); 473 474 if (m.doppelganger) 475 genModuleInfo(m); 476 } 477 478 if (m.doppelganger) 479 { 480 objc.generateModuleInfo(m); 481 objmod.termfile(); 482 return; 483 } 484 485 /* Generate module info for templates and -cov. 486 * Don't generate ModuleInfo if `object.ModuleInfo` is not declared or 487 * explicitly disabled through compiler switches such as `-betterC`. 488 */ 489 if (global.params.useModuleInfo && Module.moduleinfo /*|| needModuleInfo()*/) 490 genModuleInfo(m); 491 492 objmod.termfile(); 493 } 494 495 496 497 /************************************** 498 * Search for a druntime array op 499 */ 500 private bool isDruntimeArrayOp(Identifier ident) 501 { 502 /* Some of the array op functions are written as library functions, 503 * presumably to optimize them with special CPU vector instructions. 504 * List those library functions here, in alpha order. 505 */ 506 __gshared const(char)*[143] libArrayopFuncs = 507 [ 508 "_arrayExpSliceAddass_a", 509 "_arrayExpSliceAddass_d", 510 "_arrayExpSliceAddass_f", // T[]+=T 511 "_arrayExpSliceAddass_g", 512 "_arrayExpSliceAddass_h", 513 "_arrayExpSliceAddass_i", 514 "_arrayExpSliceAddass_k", 515 "_arrayExpSliceAddass_s", 516 "_arrayExpSliceAddass_t", 517 "_arrayExpSliceAddass_u", 518 "_arrayExpSliceAddass_w", 519 520 "_arrayExpSliceDivass_d", // T[]/=T 521 "_arrayExpSliceDivass_f", // T[]/=T 522 523 "_arrayExpSliceMinSliceAssign_a", 524 "_arrayExpSliceMinSliceAssign_d", // T[]=T-T[] 525 "_arrayExpSliceMinSliceAssign_f", // T[]=T-T[] 526 "_arrayExpSliceMinSliceAssign_g", 527 "_arrayExpSliceMinSliceAssign_h", 528 "_arrayExpSliceMinSliceAssign_i", 529 "_arrayExpSliceMinSliceAssign_k", 530 "_arrayExpSliceMinSliceAssign_s", 531 "_arrayExpSliceMinSliceAssign_t", 532 "_arrayExpSliceMinSliceAssign_u", 533 "_arrayExpSliceMinSliceAssign_w", 534 535 "_arrayExpSliceMinass_a", 536 "_arrayExpSliceMinass_d", // T[]-=T 537 "_arrayExpSliceMinass_f", // T[]-=T 538 "_arrayExpSliceMinass_g", 539 "_arrayExpSliceMinass_h", 540 "_arrayExpSliceMinass_i", 541 "_arrayExpSliceMinass_k", 542 "_arrayExpSliceMinass_s", 543 "_arrayExpSliceMinass_t", 544 "_arrayExpSliceMinass_u", 545 "_arrayExpSliceMinass_w", 546 547 "_arrayExpSliceMulass_d", // T[]*=T 548 "_arrayExpSliceMulass_f", // T[]*=T 549 "_arrayExpSliceMulass_i", 550 "_arrayExpSliceMulass_k", 551 "_arrayExpSliceMulass_s", 552 "_arrayExpSliceMulass_t", 553 "_arrayExpSliceMulass_u", 554 "_arrayExpSliceMulass_w", 555 556 "_arraySliceExpAddSliceAssign_a", 557 "_arraySliceExpAddSliceAssign_d", // T[]=T[]+T 558 "_arraySliceExpAddSliceAssign_f", // T[]=T[]+T 559 "_arraySliceExpAddSliceAssign_g", 560 "_arraySliceExpAddSliceAssign_h", 561 "_arraySliceExpAddSliceAssign_i", 562 "_arraySliceExpAddSliceAssign_k", 563 "_arraySliceExpAddSliceAssign_s", 564 "_arraySliceExpAddSliceAssign_t", 565 "_arraySliceExpAddSliceAssign_u", 566 "_arraySliceExpAddSliceAssign_w", 567 568 "_arraySliceExpDivSliceAssign_d", // T[]=T[]/T 569 "_arraySliceExpDivSliceAssign_f", // T[]=T[]/T 570 571 "_arraySliceExpMinSliceAssign_a", 572 "_arraySliceExpMinSliceAssign_d", // T[]=T[]-T 573 "_arraySliceExpMinSliceAssign_f", // T[]=T[]-T 574 "_arraySliceExpMinSliceAssign_g", 575 "_arraySliceExpMinSliceAssign_h", 576 "_arraySliceExpMinSliceAssign_i", 577 "_arraySliceExpMinSliceAssign_k", 578 "_arraySliceExpMinSliceAssign_s", 579 "_arraySliceExpMinSliceAssign_t", 580 "_arraySliceExpMinSliceAssign_u", 581 "_arraySliceExpMinSliceAssign_w", 582 583 "_arraySliceExpMulSliceAddass_d", // T[] += T[]*T 584 "_arraySliceExpMulSliceAddass_f", 585 "_arraySliceExpMulSliceAddass_r", 586 587 "_arraySliceExpMulSliceAssign_d", // T[]=T[]*T 588 "_arraySliceExpMulSliceAssign_f", // T[]=T[]*T 589 "_arraySliceExpMulSliceAssign_i", 590 "_arraySliceExpMulSliceAssign_k", 591 "_arraySliceExpMulSliceAssign_s", 592 "_arraySliceExpMulSliceAssign_t", 593 "_arraySliceExpMulSliceAssign_u", 594 "_arraySliceExpMulSliceAssign_w", 595 596 "_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T 597 "_arraySliceExpMulSliceMinass_f", 598 "_arraySliceExpMulSliceMinass_r", 599 600 "_arraySliceSliceAddSliceAssign_a", 601 "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[] 602 "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[] 603 "_arraySliceSliceAddSliceAssign_g", 604 "_arraySliceSliceAddSliceAssign_h", 605 "_arraySliceSliceAddSliceAssign_i", 606 "_arraySliceSliceAddSliceAssign_k", 607 "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[] 608 "_arraySliceSliceAddSliceAssign_s", 609 "_arraySliceSliceAddSliceAssign_t", 610 "_arraySliceSliceAddSliceAssign_u", 611 "_arraySliceSliceAddSliceAssign_w", 612 613 "_arraySliceSliceAddass_a", 614 "_arraySliceSliceAddass_d", // T[]+=T[] 615 "_arraySliceSliceAddass_f", // T[]+=T[] 616 "_arraySliceSliceAddass_g", 617 "_arraySliceSliceAddass_h", 618 "_arraySliceSliceAddass_i", 619 "_arraySliceSliceAddass_k", 620 "_arraySliceSliceAddass_s", 621 "_arraySliceSliceAddass_t", 622 "_arraySliceSliceAddass_u", 623 "_arraySliceSliceAddass_w", 624 625 "_arraySliceSliceMinSliceAssign_a", 626 "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[] 627 "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[] 628 "_arraySliceSliceMinSliceAssign_g", 629 "_arraySliceSliceMinSliceAssign_h", 630 "_arraySliceSliceMinSliceAssign_i", 631 "_arraySliceSliceMinSliceAssign_k", 632 "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[] 633 "_arraySliceSliceMinSliceAssign_s", 634 "_arraySliceSliceMinSliceAssign_t", 635 "_arraySliceSliceMinSliceAssign_u", 636 "_arraySliceSliceMinSliceAssign_w", 637 638 "_arraySliceSliceMinass_a", 639 "_arraySliceSliceMinass_d", // T[]-=T[] 640 "_arraySliceSliceMinass_f", // T[]-=T[] 641 "_arraySliceSliceMinass_g", 642 "_arraySliceSliceMinass_h", 643 "_arraySliceSliceMinass_i", 644 "_arraySliceSliceMinass_k", 645 "_arraySliceSliceMinass_s", 646 "_arraySliceSliceMinass_t", 647 "_arraySliceSliceMinass_u", 648 "_arraySliceSliceMinass_w", 649 650 "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[] 651 "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[] 652 "_arraySliceSliceMulSliceAssign_i", 653 "_arraySliceSliceMulSliceAssign_k", 654 "_arraySliceSliceMulSliceAssign_s", 655 "_arraySliceSliceMulSliceAssign_t", 656 "_arraySliceSliceMulSliceAssign_u", 657 "_arraySliceSliceMulSliceAssign_w", 658 659 "_arraySliceSliceMulass_d", // T[]*=T[] 660 "_arraySliceSliceMulass_f", // T[]*=T[] 661 "_arraySliceSliceMulass_i", 662 "_arraySliceSliceMulass_k", 663 "_arraySliceSliceMulass_s", 664 "_arraySliceSliceMulass_t", 665 "_arraySliceSliceMulass_u", 666 "_arraySliceSliceMulass_w", 667 ]; 668 const(char)* name = ident.toChars(); 669 int i = binary(name, libArrayopFuncs.ptr, libArrayopFuncs.length); 670 if (i != -1) 671 return true; 672 673 debug // Make sure our array is alphabetized 674 { 675 foreach (s; libArrayopFuncs) 676 { 677 if (strcmp(name, s) == 0) 678 assert(0); 679 } 680 } 681 return false; 682 } 683 684 685 /* ================================================================== */ 686 687 private UnitTestDeclaration needsDeferredNested(FuncDeclaration fd) 688 { 689 while (fd && fd.isNested()) 690 { 691 FuncDeclaration fdp = fd.toParent2().isFuncDeclaration(); 692 if (!fdp) 693 break; 694 if (UnitTestDeclaration udp = fdp.isUnitTestDeclaration()) 695 return udp.semanticRun < PASS.obj ? udp : null; 696 fd = fdp; 697 } 698 return null; 699 } 700 701 702 void FuncDeclaration_toObjFile(FuncDeclaration fd, bool multiobj) 703 { 704 ClassDeclaration cd = fd.parent.isClassDeclaration(); 705 //printf("FuncDeclaration.toObjFile(%p, %s.%s)\n", fd, fd.parent.toChars(), fd.toChars()); 706 707 //if (type) printf("type = %s\n", type.toChars()); 708 version (none) 709 { 710 //printf("line = %d\n", getWhere() / LINEINC); 711 EEcontext *ee = env.getEEcontext(); 712 if (ee.EEcompile == 2) 713 { 714 if (ee.EElinnum < (getWhere() / LINEINC) || 715 ee.EElinnum > (endwhere / LINEINC) 716 ) 717 return; // don't compile this function 718 ee.EEfunc = toSymbol(this); 719 } 720 } 721 722 if (fd.semanticRun >= PASS.obj) // if toObjFile() already run 723 return; 724 725 if (fd.type && fd.type.ty == Tfunction && (cast(TypeFunction)fd.type).next is null) 726 return; 727 728 // If errors occurred compiling it, such as https://issues.dlang.org/show_bug.cgi?id=6118 729 if (fd.type && fd.type.ty == Tfunction && (cast(TypeFunction)fd.type).next.ty == Terror) 730 return; 731 732 if (fd.semantic3Errors) 733 return; 734 735 if (global.errors) 736 return; 737 738 if (!fd.fbody) 739 return; 740 741 UnitTestDeclaration ud = fd.isUnitTestDeclaration(); 742 if (ud && !global.params.useUnitTests) 743 return; 744 745 if (multiobj && !fd.isStaticDtorDeclaration() && !fd.isStaticCtorDeclaration() && !fd.isCrtCtorDtor) 746 { 747 obj_append(fd); 748 return; 749 } 750 751 if (fd.semanticRun == PASS.semanticdone) 752 { 753 /* What happened is this function failed semantic3() with errors, 754 * but the errors were gagged. 755 * Try to reproduce those errors, and then fail. 756 */ 757 fd.error("errors compiling the function"); 758 return; 759 } 760 assert(fd.semanticRun == PASS.semantic3done); 761 assert(fd.ident != Id.empty); 762 763 for (FuncDeclaration fd2 = fd; fd2; ) 764 { 765 if (fd2.inNonRoot()) 766 return; 767 if (fd2.isNested()) 768 fd2 = fd2.toParent2().isFuncDeclaration(); 769 else 770 break; 771 } 772 773 if (UnitTestDeclaration udp = needsDeferredNested(fd)) 774 { 775 /* Can't do unittest's out of order, they are order dependent in that their 776 * execution is done in lexical order. 777 */ 778 udp.deferredNested.push(fd); 779 //printf("%s @[%s]\n\t-. pushed to unittest @[%s]\n", 780 // fd.toPrettyChars(), fd.loc.toChars(), udp.loc.toChars()); 781 return; 782 } 783 784 if (fd.isArrayOp && isDruntimeArrayOp(fd.ident)) 785 { 786 // Implementation is in druntime 787 return; 788 } 789 790 // start code generation 791 fd.semanticRun = PASS.obj; 792 793 if (global.params.verbose) 794 message("function %s", fd.toPrettyChars()); 795 796 Symbol *s = toSymbol(fd); 797 func_t *f = s.Sfunc; 798 799 // tunnel type of "this" to debug info generation 800 if (AggregateDeclaration ad = fd.parent.isAggregateDeclaration()) 801 { 802 .type* t = Type_toCtype(ad.getType()); 803 if (cd) 804 t = t.Tnext; // skip reference 805 f.Fclass = cast(Classsym *)t; 806 } 807 808 /* This is done so that the 'this' pointer on the stack is the same 809 * distance away from the function parameters, so that an overriding 810 * function can call the nested fdensure or fdrequire of its overridden function 811 * and the stack offsets are the same. 812 */ 813 if (fd.isVirtual() && (fd.fensure || fd.frequire)) 814 f.Fflags3 |= Ffakeeh; 815 816 if (fd.eh_none) 817 // Same as config.ehmethod==EH_NONE, but only for this function 818 f.Fflags3 |= Feh_none; 819 820 s.Sclass = global.params.isOSX ? SCcomdat : SCglobal; 821 for (Dsymbol p = fd.parent; p; p = p.parent) 822 { 823 if (p.isTemplateInstance()) 824 { 825 // functions without D or C++ name mangling mixed in at global scope 826 // shouldn't have multiple definitions 827 if (p.isTemplateMixin() && (fd.linkage == LINK.c || fd.linkage == LINK.windows || 828 fd.linkage == LINK.pascal || fd.linkage == LINK.objc)) 829 { 830 const q = p.toParent(); 831 if (q && q.isModule()) 832 { 833 s.Sclass = SCglobal; 834 break; 835 } 836 } 837 s.Sclass = SCcomdat; 838 break; 839 } 840 } 841 842 /* Vector operations should be comdat's 843 */ 844 if (fd.isArrayOp) 845 s.Sclass = SCcomdat; 846 847 if (fd.inlinedNestedCallees) 848 { 849 /* https://issues.dlang.org/show_bug.cgi?id=15333 850 * If fd contains inlined expressions that come from 851 * nested function bodies, the enclosing of the functions must be 852 * generated first, in order to calculate correct frame pointer offset. 853 */ 854 foreach (fdc; *fd.inlinedNestedCallees) 855 { 856 FuncDeclaration fp = fdc.toParent2().isFuncDeclaration(); 857 if (fp && fp.semanticRun < PASS.obj) 858 { 859 toObjFile(fp, multiobj); 860 } 861 } 862 } 863 864 if (fd.isNested()) 865 { 866 //if (!(config.flags3 & CFG3pic)) 867 // s.Sclass = SCstatic; 868 f.Fflags3 |= Fnested; 869 870 /* The enclosing function must have its code generated first, 871 * in order to calculate correct frame pointer offset. 872 */ 873 FuncDeclaration fdp = fd.toParent2().isFuncDeclaration(); 874 if (fdp && fdp.semanticRun < PASS.obj) 875 { 876 toObjFile(fdp, multiobj); 877 } 878 } 879 else 880 { 881 specialFunctions(objmod, fd); 882 } 883 884 symtab_t *symtabsave = cstate.CSpsymtab; 885 cstate.CSpsymtab = &f.Flocsym; 886 887 // Find module m for this function 888 Module m = null; 889 for (Dsymbol p = fd.parent; p; p = p.parent) 890 { 891 m = p.isModule(); 892 if (m) 893 break; 894 } 895 896 Dsymbols deferToObj; // write these to OBJ file later 897 Array!(elem*) varsInScope; 898 Label*[void*] labels = null; 899 IRState irs = IRState(m, fd, &varsInScope, &deferToObj, &labels, &global.params); 900 901 Symbol *shidden = null; 902 Symbol *sthis = null; 903 tym_t tyf = tybasic(s.Stype.Tty); 904 //printf("linkage = %d, tyf = x%x\n", linkage, tyf); 905 int reverse = tyrevfunc(s.Stype.Tty); 906 907 assert(fd.type.ty == Tfunction); 908 TypeFunction tf = cast(TypeFunction)fd.type; 909 RET retmethod = retStyle(tf, fd.needThis()); 910 if (retmethod == RET.stack) 911 { 912 // If function returns a struct, put a pointer to that 913 // as the first argument 914 .type *thidden = Type_toCtype(tf.next.pointerTo()); 915 char[5+4+1] hiddenparam = void; 916 __gshared int hiddenparami; // how many we've generated so far 917 918 const(char)* name; 919 if (fd.nrvo_can && fd.nrvo_var) 920 name = fd.nrvo_var.ident.toChars(); 921 else 922 { 923 sprintf(hiddenparam.ptr, "__HID%d", ++hiddenparami); 924 name = hiddenparam.ptr; 925 } 926 shidden = symbol_name(name, SCparameter, thidden); 927 shidden.Sflags |= SFLtrue | SFLfree; 928 if (fd.nrvo_can && fd.nrvo_var && fd.nrvo_var.nestedrefs.dim) 929 type_setcv(&shidden.Stype, shidden.Stype.Tty | mTYvolatile); 930 irs.shidden = shidden; 931 fd.shidden = shidden; 932 } 933 else 934 { 935 // Register return style cannot make nrvo. 936 // Auto functions keep the nrvo_can flag up to here, 937 // so we should eliminate it before entering backend. 938 fd.nrvo_can = 0; 939 } 940 941 if (fd.vthis) 942 { 943 assert(!fd.vthis.csym); 944 sthis = toSymbol(fd.vthis); 945 sthis.Stype = getParentClosureType(sthis, fd); 946 irs.sthis = sthis; 947 if (!(f.Fflags3 & Fnested)) 948 f.Fflags3 |= Fmember; 949 } 950 951 // Estimate number of parameters, pi 952 size_t pi = (fd.v_arguments !is null); 953 if (fd.parameters) 954 pi += fd.parameters.dim; 955 if (fd.selector) 956 pi++; // Extra argument for Objective-C selector 957 // Create a temporary buffer, params[], to hold function parameters 958 Symbol*[10] paramsbuf = void; 959 Symbol **params = paramsbuf.ptr; // allocate on stack if possible 960 if (pi + 2 > paramsbuf.length) // allow extra 2 for sthis and shidden 961 { 962 params = cast(Symbol **)Mem.check(malloc((pi + 2) * (Symbol *).sizeof)); 963 } 964 965 // Get the actual number of parameters, pi, and fill in the params[] 966 pi = 0; 967 if (fd.v_arguments) 968 { 969 params[pi] = toSymbol(fd.v_arguments); 970 pi += 1; 971 } 972 if (fd.parameters) 973 { 974 foreach (i, v; *fd.parameters) 975 { 976 //printf("param[%d] = %p, %s\n", i, v, v.toChars()); 977 assert(!v.csym); 978 params[pi + i] = toSymbol(v); 979 } 980 pi += fd.parameters.dim; 981 } 982 983 if (reverse) 984 { 985 // Reverse params[] entries 986 foreach (i, sptmp; params[0 .. pi/2]) 987 { 988 params[i] = params[pi - 1 - i]; 989 params[pi - 1 - i] = sptmp; 990 } 991 } 992 993 if (shidden) 994 { 995 // shidden becomes last parameter 996 //params[pi] = shidden; 997 998 // shidden becomes first parameter 999 memmove(params + 1, params, pi * (params[0]).sizeof); 1000 params[0] = shidden; 1001 1002 pi++; 1003 } 1004 1005 pi = objc.addSelectorParameterSymbol(fd, params, pi); 1006 1007 if (sthis) 1008 { 1009 // sthis becomes last parameter 1010 //params[pi] = sthis; 1011 1012 // sthis becomes first parameter 1013 memmove(params + 1, params, pi * (params[0]).sizeof); 1014 params[0] = sthis; 1015 1016 pi++; 1017 } 1018 1019 if (target.isPOSIX && fd.linkage != LINK.d && shidden && sthis) 1020 { 1021 /* swap shidden and sthis 1022 */ 1023 Symbol *sp = params[0]; 1024 params[0] = params[1]; 1025 params[1] = sp; 1026 } 1027 1028 foreach (sp; params[0 .. pi]) 1029 { 1030 sp.Sclass = SCparameter; 1031 sp.Sflags &= ~SFLspill; 1032 sp.Sfl = FLpara; 1033 symbol_add(sp); 1034 } 1035 1036 // Determine register assignments 1037 if (pi) 1038 { 1039 FuncParamRegs fpr = FuncParamRegs.create(tyf); 1040 1041 foreach (sp; params[0 .. pi]) 1042 { 1043 if (fpr.alloc(sp.Stype, sp.Stype.Tty, &sp.Spreg, &sp.Spreg2)) 1044 { 1045 sp.Sclass = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar; 1046 sp.Sfl = (sp.Sclass == SCshadowreg) ? FLpara : FLfast; 1047 } 1048 } 1049 } 1050 1051 // Done with params 1052 if (params != paramsbuf.ptr) 1053 free(params); 1054 params = null; 1055 1056 localgot = null; 1057 1058 Statement sbody = fd.fbody; 1059 1060 Blockx bx; 1061 bx.startblock = block_calloc(); 1062 bx.curblock = bx.startblock; 1063 bx.funcsym = s; 1064 bx.scope_index = -1; 1065 bx.classdec = cast(void*)cd; 1066 bx.member = cast(void*)fd; 1067 bx._module = cast(void*)fd.getModule(); 1068 irs.blx = &bx; 1069 1070 // Initialize argptr 1071 if (fd.v_argptr) 1072 { 1073 // Declare va_argsave 1074 if (global.params.is64bit && 1075 !global.params.isWindows) 1076 { 1077 type *t = type_struct_class("__va_argsave_t", 16, 8 * 6 + 8 * 16 + 8 * 3, null, null, false, false, true, false); 1078 // The backend will pick this up by name 1079 Symbol *sv = symbol_name("__va_argsave", SCauto, t); 1080 sv.Stype.Tty |= mTYvolatile; 1081 symbol_add(sv); 1082 } 1083 1084 Symbol *sa = toSymbol(fd.v_argptr); 1085 symbol_add(sa); 1086 elem *e = el_una(OPva_start, TYnptr, el_ptr(sa)); 1087 block_appendexp(irs.blx.curblock, e); 1088 } 1089 1090 /* Doing this in semantic3() caused all kinds of problems: 1091 * 1. couldn't reliably get the final mangling of the function name due to fwd refs 1092 * 2. impact on function inlining 1093 * 3. what to do when writing out .di files, or other pretty printing 1094 */ 1095 if (global.params.trace && !fd.isCMain() && !fd.naked) 1096 { 1097 /* The profiler requires TLS, and TLS may not be set up yet when C main() 1098 * gets control (i.e. OSX), leading to a crash. 1099 */ 1100 /* Wrap the entire function body in: 1101 * trace_pro("funcname"); 1102 * try 1103 * body; 1104 * finally 1105 * _c_trace_epi(); 1106 */ 1107 StringExp se = StringExp.create(Loc.initial, s.Sident.ptr); 1108 se.type = Type.tstring; 1109 se.type = se.type.typeSemantic(Loc.initial, null); 1110 Expressions *exps = new Expressions(); 1111 exps.push(se); 1112 FuncDeclaration fdpro = FuncDeclaration.genCfunc(null, Type.tvoid, "trace_pro"); 1113 Expression ec = VarExp.create(Loc.initial, fdpro); 1114 Expression e = CallExp.create(Loc.initial, ec, exps); 1115 e.type = Type.tvoid; 1116 Statement sp = ExpStatement.create(fd.loc, e); 1117 1118 FuncDeclaration fdepi = FuncDeclaration.genCfunc(null, Type.tvoid, "_c_trace_epi"); 1119 ec = VarExp.create(Loc.initial, fdepi); 1120 e = CallExp.create(Loc.initial, ec); 1121 e.type = Type.tvoid; 1122 Statement sf = ExpStatement.create(fd.loc, e); 1123 1124 Statement stf; 1125 if (sbody.blockExit(fd, false) == BE.fallthru) 1126 stf = CompoundStatement.create(Loc.initial, sbody, sf); 1127 else 1128 stf = TryFinallyStatement.create(Loc.initial, sbody, sf); 1129 sbody = CompoundStatement.create(Loc.initial, sp, stf); 1130 } 1131 1132 if (fd.interfaceVirtual) 1133 { 1134 // Adjust the 'this' pointer instead of using a thunk 1135 assert(irs.sthis); 1136 elem *ethis = el_var(irs.sthis); 1137 ethis = fixEthis2(ethis, fd); 1138 elem *e = el_bin(OPminass, TYnptr, ethis, el_long(TYsize_t, fd.interfaceVirtual.offset)); 1139 block_appendexp(irs.blx.curblock, e); 1140 } 1141 1142 buildClosure(fd, &irs); 1143 1144 if (config.ehmethod == EHmethod.EH_WIN32 && fd.isSynchronized() && cd && 1145 !fd.isStatic() && !sbody.usesEH() && !global.params.trace) 1146 { 1147 /* The "jmonitor" hack uses an optimized exception handling frame 1148 * which is a little shorter than the more general EH frame. 1149 */ 1150 s.Sfunc.Fflags3 |= Fjmonitor; 1151 } 1152 1153 Statement_toIR(sbody, &irs); 1154 1155 if (global.errors) 1156 { 1157 // Restore symbol table 1158 cstate.CSpsymtab = symtabsave; 1159 return; 1160 } 1161 1162 bx.curblock.BC = BCret; 1163 1164 f.Fstartblock = bx.startblock; 1165 // einit = el_combine(einit,bx.init); 1166 1167 if (fd.isCtorDeclaration()) 1168 { 1169 assert(sthis); 1170 foreach (b; BlockRange(f.Fstartblock)) 1171 { 1172 if (b.BC == BCret) 1173 { 1174 elem *ethis = el_var(sthis); 1175 ethis = fixEthis2(ethis, fd); 1176 b.BC = BCretexp; 1177 b.Belem = el_combine(b.Belem, ethis); 1178 } 1179 } 1180 } 1181 if (config.ehmethod == EHmethod.EH_NONE || f.Fflags3 & Feh_none) 1182 insertFinallyBlockGotos(f.Fstartblock); 1183 else if (config.ehmethod == EHmethod.EH_DWARF) 1184 insertFinallyBlockCalls(f.Fstartblock); 1185 1186 // If static constructor 1187 if (fd.isSharedStaticCtorDeclaration()) // must come first because it derives from StaticCtorDeclaration 1188 { 1189 ssharedctors.push(s); 1190 } 1191 else if (fd.isStaticCtorDeclaration()) 1192 { 1193 sctors.push(s); 1194 } 1195 1196 // If static destructor 1197 if (fd.isSharedStaticDtorDeclaration()) // must come first because it derives from StaticDtorDeclaration 1198 { 1199 SharedStaticDtorDeclaration fs = fd.isSharedStaticDtorDeclaration(); 1200 assert(fs); 1201 if (fs.vgate) 1202 { 1203 /* Increment destructor's vgate at construction time 1204 */ 1205 esharedctorgates.push(fs); 1206 } 1207 1208 sshareddtors.shift(s); 1209 } 1210 else if (fd.isStaticDtorDeclaration()) 1211 { 1212 StaticDtorDeclaration fs = fd.isStaticDtorDeclaration(); 1213 assert(fs); 1214 if (fs.vgate) 1215 { 1216 /* Increment destructor's vgate at construction time 1217 */ 1218 ectorgates.push(fs); 1219 } 1220 1221 sdtors.shift(s); 1222 } 1223 1224 // If unit test 1225 if (ud) 1226 { 1227 stests.push(s); 1228 } 1229 1230 if (global.errors) 1231 { 1232 // Restore symbol table 1233 cstate.CSpsymtab = symtabsave; 1234 return; 1235 } 1236 1237 writefunc(s); 1238 1239 buildCapture(fd); 1240 1241 // Restore symbol table 1242 cstate.CSpsymtab = symtabsave; 1243 1244 if (fd.isExport()) 1245 objmod.export_symbol(s, cast(uint)Para.offset); 1246 1247 if (fd.isCrtCtorDtor & 1) 1248 objmod.setModuleCtorDtor(s, true); 1249 if (fd.isCrtCtorDtor & 2) 1250 objmod.setModuleCtorDtor(s, false); 1251 1252 foreach (sd; *irs.deferToObj) 1253 { 1254 toObjFile(sd, false); 1255 } 1256 1257 if (ud) 1258 { 1259 foreach (fdn; ud.deferredNested) 1260 { 1261 toObjFile(fdn, false); 1262 } 1263 } 1264 1265 if (irs.startaddress) 1266 { 1267 //printf("Setting start address\n"); 1268 objmod.startaddress(irs.startaddress); 1269 } 1270 } 1271 1272 1273 /******************************************* 1274 * Detect special functions like `main()` and do special handling for them, 1275 * like special mangling, including libraries, setting the storage class, etc. 1276 * `objmod` and `fd` are updated. 1277 * 1278 * Params: 1279 * objmod = object module 1280 * fd = function symbol 1281 */ 1282 private void specialFunctions(Obj objmod, FuncDeclaration fd) 1283 { 1284 const libname = global.finalDefaultlibname(); 1285 1286 Symbol* s = fd.toSymbol(); // backend symbol corresponding to fd 1287 1288 // Pull in RTL startup code (but only once) 1289 if (fd.isMain() && onlyOneMain(fd.loc)) 1290 { 1291 if (target.isPOSIX) 1292 { 1293 objmod.external_def("_main"); 1294 } 1295 else if (global.params.mscoff) 1296 { 1297 objmod.external_def("main"); 1298 } 1299 else if (config.exe == EX_WIN32) 1300 { 1301 objmod.external_def("_main"); 1302 objmod.external_def("__acrtused_con"); 1303 } 1304 if (libname) 1305 obj_includelib(libname); 1306 s.Sclass = SCglobal; 1307 } 1308 else if (fd.isRtInit()) 1309 { 1310 if (target.isPOSIX || global.params.mscoff) 1311 { 1312 objmod.ehsections(); // initialize exception handling sections 1313 } 1314 } 1315 else if (fd.isCMain()) 1316 { 1317 if (global.params.mscoff) 1318 { 1319 if (global.params.mscrtlib.length && global.params.mscrtlib[0]) 1320 obj_includelib(global.params.mscrtlib); 1321 objmod.includelib("OLDNAMES"); 1322 } 1323 else if (config.exe == EX_WIN32) 1324 { 1325 objmod.external_def("__acrtused_con"); // bring in C startup code 1326 objmod.includelib("snn.lib"); // bring in C runtime library 1327 } 1328 s.Sclass = SCglobal; 1329 } 1330 else if (global.params.isWindows && fd.isWinMain() && onlyOneMain(fd.loc)) 1331 { 1332 if (global.params.mscoff) 1333 { 1334 objmod.includelib("uuid"); 1335 if (global.params.mscrtlib.length && global.params.mscrtlib[0]) 1336 obj_includelib(global.params.mscrtlib); 1337 objmod.includelib("OLDNAMES"); 1338 } 1339 else 1340 { 1341 objmod.external_def("__acrtused"); 1342 } 1343 if (libname) 1344 obj_includelib(libname); 1345 s.Sclass = SCglobal; 1346 } 1347 1348 // Pull in RTL startup code 1349 else if (global.params.isWindows && fd.isDllMain() && onlyOneMain(fd.loc)) 1350 { 1351 if (global.params.mscoff) 1352 { 1353 objmod.includelib("uuid"); 1354 if (global.params.mscrtlib.length && global.params.mscrtlib[0]) 1355 obj_includelib(global.params.mscrtlib); 1356 objmod.includelib("OLDNAMES"); 1357 } 1358 else 1359 { 1360 objmod.external_def("__acrtused_dll"); 1361 } 1362 if (libname) 1363 obj_includelib(libname); 1364 s.Sclass = SCglobal; 1365 } 1366 } 1367 1368 1369 private bool onlyOneMain(Loc loc) 1370 { 1371 __gshared Loc lastLoc; 1372 __gshared bool hasMain = false; 1373 if (hasMain) 1374 { 1375 const(char)* msg = ""; 1376 if (global.params.addMain) 1377 msg = ", -main switch added another `main()`"; 1378 const(char)* otherMainNames = ""; 1379 if (config.exe == EX_WIN32 || config.exe == EX_WIN64) 1380 otherMainNames = ", `WinMain`, or `DllMain`"; 1381 error(loc, "only one `main`%s allowed%s. Previously found `main` at %s", 1382 otherMainNames, msg, lastLoc.toChars()); 1383 return false; 1384 } 1385 lastLoc = loc; 1386 hasMain = true; 1387 return true; 1388 } 1389 1390 /* ================================================================== */ 1391 1392 /***************************** 1393 * Return back end type corresponding to D front end type. 1394 */ 1395 1396 tym_t totym(Type tx) 1397 { 1398 tym_t t; 1399 switch (tx.ty) 1400 { 1401 case Tvoid: t = TYvoid; break; 1402 case Tint8: t = TYschar; break; 1403 case Tuns8: t = TYuchar; break; 1404 case Tint16: t = TYshort; break; 1405 case Tuns16: t = TYushort; break; 1406 case Tint32: t = TYint; break; 1407 case Tuns32: t = TYuint; break; 1408 case Tint64: t = TYllong; break; 1409 case Tuns64: t = TYullong; break; 1410 case Tfloat32: t = TYfloat; break; 1411 case Tfloat64: t = TYdouble; break; 1412 case Tfloat80: t = TYldouble; break; 1413 case Timaginary32: t = TYifloat; break; 1414 case Timaginary64: t = TYidouble; break; 1415 case Timaginary80: t = TYildouble; break; 1416 case Tcomplex32: t = TYcfloat; break; 1417 case Tcomplex64: t = TYcdouble; break; 1418 case Tcomplex80: t = TYcldouble; break; 1419 case Tbool: t = TYbool; break; 1420 case Tchar: t = TYchar; break; 1421 case Twchar: t = TYwchar_t; break; 1422 case Tdchar: 1423 t = (global.params.symdebug == 1 || !global.params.isWindows) ? TYdchar : TYulong; 1424 break; 1425 1426 case Taarray: t = TYaarray; break; 1427 case Tclass: 1428 case Treference: 1429 case Tpointer: t = TYnptr; break; 1430 case Tdelegate: t = TYdelegate; break; 1431 case Tarray: t = TYdarray; break; 1432 case Tsarray: t = TYstruct; break; 1433 1434 case Tstruct: 1435 t = TYstruct; 1436 break; 1437 1438 case Tenum: 1439 { 1440 Type tb = tx.toBasetype(); 1441 const id = tx.toDsymbol(null).ident; 1442 if (id == Id.__c_long) 1443 t = tb.ty == Tint32 ? TYlong : TYllong; 1444 else if (id == Id.__c_ulong) 1445 t = tb.ty == Tuns32 ? TYulong : TYullong; 1446 else if (id == Id.__c_long_double) 1447 t = TYdouble; 1448 else 1449 t = totym(tb); 1450 break; 1451 } 1452 1453 case Tident: 1454 case Ttypeof: 1455 case Tmixin: 1456 //printf("ty = %d, '%s'\n", tx.ty, tx.toChars()); 1457 error(Loc.initial, "forward reference of `%s`", tx.toChars()); 1458 t = TYint; 1459 break; 1460 1461 case Tnull: 1462 t = TYnptr; 1463 break; 1464 1465 case Tvector: 1466 { 1467 auto tv = cast(TypeVector)tx; 1468 const tb = tv.elementType(); 1469 const s32 = tv.alignsize() == 32; // if 32 byte, 256 bit vector 1470 switch (tb.ty) 1471 { 1472 case Tvoid: 1473 case Tint8: t = s32 ? TYschar32 : TYschar16; break; 1474 case Tuns8: t = s32 ? TYuchar32 : TYuchar16; break; 1475 case Tint16: t = s32 ? TYshort16 : TYshort8; break; 1476 case Tuns16: t = s32 ? TYushort16 : TYushort8; break; 1477 case Tint32: t = s32 ? TYlong8 : TYlong4; break; 1478 case Tuns32: t = s32 ? TYulong8 : TYulong4; break; 1479 case Tint64: t = s32 ? TYllong4 : TYllong2; break; 1480 case Tuns64: t = s32 ? TYullong4 : TYullong2; break; 1481 case Tfloat32: t = s32 ? TYfloat8 : TYfloat4; break; 1482 case Tfloat64: t = s32 ? TYdouble4 : TYdouble2; break; 1483 default: 1484 assert(0); 1485 } 1486 break; 1487 } 1488 1489 case Tfunction: 1490 { 1491 auto tf = cast(TypeFunction)tx; 1492 final switch (tf.linkage) 1493 { 1494 case LINK.windows: 1495 if (global.params.is64bit) 1496 goto case LINK.c; 1497 t = (tf.parameterList.varargs == VarArg.variadic) ? TYnfunc : TYnsfunc; 1498 break; 1499 1500 case LINK.pascal: 1501 t = (tf.parameterList.varargs == VarArg.variadic) ? TYnfunc : TYnpfunc; 1502 break; 1503 1504 case LINK.c: 1505 case LINK.cpp: 1506 case LINK.objc: 1507 t = TYnfunc; 1508 if (global.params.isWindows) 1509 { 1510 } 1511 else if (!global.params.is64bit && retStyle(tf, false) == RET.stack) 1512 t = TYhfunc; 1513 break; 1514 1515 case LINK.d: 1516 t = (tf.parameterList.varargs == VarArg.variadic) ? TYnfunc : TYjfunc; 1517 break; 1518 1519 case LINK.default_: 1520 case LINK.system: 1521 printf("linkage = %d\n", tf.linkage); 1522 assert(0); 1523 } 1524 if (tf.isnothrow) 1525 t |= mTYnothrow; 1526 return t; 1527 } 1528 default: 1529 //printf("ty = %d, '%s'\n", tx.ty, tx.toChars()); 1530 assert(0); 1531 } 1532 1533 t |= modToTym(tx.mod); // Add modifiers 1534 1535 return t; 1536 } 1537 1538 /************************************** 1539 */ 1540 1541 Symbol *toSymbol(Type t) 1542 { 1543 if (t.ty == Tclass) 1544 { 1545 return toSymbol((cast(TypeClass)t).sym); 1546 } 1547 assert(0); 1548 } 1549 1550 /******************************************* 1551 * Generate readonly symbol that consists of a bunch of zeros. 1552 * Immutable Symbol instances can be mapped over it. 1553 * Only one is generated per object file. 1554 * Returns: 1555 * bzero symbol 1556 */ 1557 Symbol* getBzeroSymbol() 1558 { 1559 Symbol* s = bzeroSymbol; 1560 if (s) 1561 return s; 1562 1563 s = symbol_calloc("__bzeroBytes"); 1564 s.Stype = type_static_array(128, type_fake(TYuchar)); 1565 s.Stype.Tmangle = mTYman_c; 1566 s.Stype.Tcount++; 1567 s.Sclass = SCglobal; 1568 s.Sfl = FLdata; 1569 s.Sflags |= SFLnodebug; 1570 s.Salignment = 16; 1571 1572 auto dtb = DtBuilder(0); 1573 dtb.nzeros(128); 1574 s.Sdt = dtb.finish(); 1575 dt2common(&s.Sdt); 1576 1577 outdata(s); 1578 1579 bzeroSymbol = s; 1580 return s; 1581 } 1582 1583 1584 1585 /************************************** 1586 * Generate elem that is a dynamic array slice of the module file name. 1587 */ 1588 1589 private elem *toEfilename(Module m) 1590 { 1591 //printf("toEfilename(%s)\n", m.toChars()); 1592 const(char)* id = m.srcfile.toChars(); 1593 size_t len = strlen(id); 1594 1595 if (!m.sfilename) 1596 { 1597 // Put out as a static array 1598 m.sfilename = toStringSymbol(id, len, 1); 1599 } 1600 1601 // Turn static array into dynamic array 1602 return el_pair(TYdarray, el_long(TYsize_t, len), el_ptr(m.sfilename)); 1603 } 1604 1605 // Used in e2ir.d 1606 elem *toEfilenamePtr(Module m) 1607 { 1608 //printf("toEfilenamePtr(%s)\n", m.toChars()); 1609 const(char)* id = m.srcfile.toChars(); 1610 size_t len = strlen(id); 1611 Symbol* s = toStringSymbol(id, len, 1); 1612 return el_ptr(s); 1613 }