1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/backconfig.d, backend/backconfig.d) 9 */ 10 11 // Configure the back end (optimizer and code generator) 12 13 module dmd.backend.backconfig; 14 15 import core.stdc.stdio; 16 17 import dmd.backend.cdef; 18 import dmd.backend.cc; 19 import dmd.backend.code; 20 import dmd.backend.global; 21 import dmd.backend.ty; 22 import dmd.backend.type; 23 24 extern (C++): 25 26 nothrow: 27 28 version (MARS) 29 { 30 void ph_init(); 31 } 32 33 /************************************** 34 * Initialize configuration variables. 35 */ 36 37 extern (C) void out_config_init( 38 int model, // 32: 32 bit code 39 // 64: 64 bit code 40 // Windows: set bit 0 to generate MS-COFF instead of OMF 41 bool exe, // true: exe file 42 // false: dll or shared library (generate PIC code) 43 bool trace, // add profiling code 44 bool nofloat, // do not pull in floating point code 45 bool verbose, // verbose compile 46 bool optimize, // optimize code 47 int symdebug, // add symbolic debug information 48 // 1: D 49 // 2: fake it with C symbolic debug info 50 bool alwaysframe, // always create standard function frame 51 bool stackstomp, // add stack stomping code 52 ubyte avx, // use AVX instruction set (0, 1, 2) 53 ubyte pic, // position independence level (0, 1, 2) 54 bool useModuleInfo, // implement ModuleInfo 55 bool useTypeInfo, // implement TypeInfo 56 bool useExceptions, // implement exception handling 57 ubyte dwarf, // DWARF version used 58 string _version // Compiler version 59 ) 60 { 61 version (MARS) 62 { 63 //printf("out_config_init()\n"); 64 65 config._version = _version; 66 if (!config.target_cpu) 67 { config.target_cpu = TARGET_PentiumPro; 68 config.target_scheduler = config.target_cpu; 69 } 70 config.fulltypes = CVNONE; 71 config.fpxmmregs = false; 72 config.inline8087 = 1; 73 config.memmodel = 0; 74 config.flags |= CFGuchar; // make sure TYchar is unsigned 75 tytab[TYchar] |= TYFLuns; 76 bool mscoff = model & 1; 77 model &= 32 | 64; 78 79 if (dwarf < 3 || dwarf > 5) 80 { 81 if (dwarf) 82 { 83 import dmd.backend.errors; 84 error(null, 0, 0, "DWARF version %u is not supported", dwarf); 85 } 86 87 // Default DWARF version 88 config.dwarf = 3; 89 } 90 else 91 { 92 config.dwarf = dwarf; 93 } 94 95 static if (TARGET_WINDOS) 96 { 97 if (model == 64) 98 { config.exe = EX_WIN64; 99 config.fpxmmregs = true; 100 config.avx = avx; 101 config.ehmethod = useExceptions ? EHmethod.EH_DM : EHmethod.EH_NONE; 102 103 config.flags |= CFGnoebp; // test suite fails without this 104 //config.flags |= CFGalwaysframe; 105 config.flags |= CFGromable; // put switch tables in code segment 106 config.objfmt = OBJ_MSCOFF; 107 } 108 else 109 { 110 config.exe = EX_WIN32; 111 config.ehmethod = useExceptions ? EHmethod.EH_WIN32 : EHmethod.EH_NONE; 112 config.objfmt = mscoff ? OBJ_MSCOFF : OBJ_OMF; 113 } 114 115 if (exe) 116 config.wflags |= WFexe; // EXE file only optimizations 117 config.flags4 |= CFG4underscore; 118 } 119 static if (TARGET_LINUX) 120 { 121 config.fpxmmregs = true; 122 config.avx = avx; 123 if (model == 64) 124 { config.exe = EX_LINUX64; 125 config.ehmethod = useExceptions ? EHmethod.EH_DWARF : EHmethod.EH_NONE; 126 } 127 else 128 { 129 config.exe = EX_LINUX; 130 config.ehmethod = useExceptions ? EHmethod.EH_DWARF : EHmethod.EH_NONE; 131 if (!exe) 132 config.flags |= CFGromable; // put switch tables in code segment 133 } 134 config.flags |= CFGnoebp; 135 switch (pic) 136 { 137 case 0: // PIC.fixed 138 break; 139 140 case 1: // PIC.pic 141 config.flags3 |= CFG3pic; 142 break; 143 144 case 2: // PIC.pie 145 config.flags3 |= CFG3pic | CFG3pie; 146 break; 147 148 default: 149 assert(0); 150 } 151 if (symdebug) 152 config.flags |= CFGalwaysframe; 153 154 config.objfmt = OBJ_ELF; 155 } 156 static if (TARGET_OSX) 157 { 158 config.fpxmmregs = true; 159 config.avx = avx; 160 if (model == 64) 161 { config.exe = EX_OSX64; 162 config.ehmethod = useExceptions ? EHmethod.EH_DWARF : EHmethod.EH_NONE; 163 } 164 else 165 { 166 config.exe = EX_OSX; 167 config.ehmethod = useExceptions ? EHmethod.EH_DWARF : EHmethod.EH_NONE; 168 } 169 config.flags |= CFGnoebp; 170 if (!exe) 171 { 172 config.flags3 |= CFG3pic; 173 if (model == 64) 174 config.flags |= CFGalwaysframe; // autotester fails without this 175 // https://issues.dlang.org/show_bug.cgi?id=21042 176 } 177 if (symdebug) 178 config.flags |= CFGalwaysframe; 179 config.flags |= CFGromable; // put switch tables in code segment 180 config.objfmt = OBJ_MACH; 181 } 182 static if (TARGET_FREEBSD) 183 { 184 if (model == 64) 185 { config.exe = EX_FREEBSD64; 186 config.ehmethod = useExceptions ? EHmethod.EH_DWARF : EHmethod.EH_NONE; 187 config.fpxmmregs = true; 188 config.avx = avx; 189 } 190 else 191 { 192 config.exe = EX_FREEBSD; 193 config.ehmethod = useExceptions ? EHmethod.EH_DWARF : EHmethod.EH_NONE; 194 if (!exe) 195 config.flags |= CFGromable; // put switch tables in code segment 196 } 197 config.flags |= CFGnoebp; 198 if (!exe) 199 { 200 config.flags3 |= CFG3pic; 201 } 202 if (symdebug) 203 config.flags |= CFGalwaysframe; 204 config.objfmt = OBJ_ELF; 205 } 206 static if (TARGET_OPENBSD) 207 { 208 if (model == 64) 209 { config.exe = EX_OPENBSD64; 210 config.fpxmmregs = true; 211 config.avx = avx; 212 } 213 else 214 { 215 config.exe = EX_OPENBSD; 216 if (!exe) 217 config.flags |= CFGromable; // put switch tables in code segment 218 } 219 config.flags |= CFGnoebp; 220 config.flags |= CFGalwaysframe; 221 if (!exe) 222 config.flags3 |= CFG3pic; 223 config.objfmt = OBJ_ELF; 224 config.ehmethod = useExceptions ? EHmethod.EH_DM : EHmethod.EH_NONE; 225 } 226 static if (TARGET_DRAGONFLYBSD) 227 { 228 if (model == 64) 229 { config.exe = EX_DRAGONFLYBSD64; 230 config.ehmethod = useExceptions ? EHmethod.EH_DWARF : EHmethod.EH_NONE; 231 config.fpxmmregs = true; 232 config.avx = avx; 233 } 234 else 235 { 236 assert(0); // Only 64-bit supported on DragonFlyBSD 237 } 238 config.flags |= CFGnoebp; 239 if (!exe) 240 { 241 config.flags3 |= CFG3pic; 242 config.flags |= CFGalwaysframe; // PIC needs a frame for TLS fixups 243 } 244 config.objfmt = OBJ_ELF; 245 } 246 static if (TARGET_SOLARIS) 247 { 248 if (model == 64) 249 { config.exe = EX_SOLARIS64; 250 config.fpxmmregs = true; 251 config.avx = avx; 252 } 253 else 254 { 255 config.exe = EX_SOLARIS; 256 if (!exe) 257 config.flags |= CFGromable; // put switch tables in code segment 258 } 259 config.flags |= CFGnoebp; 260 config.flags |= CFGalwaysframe; 261 if (!exe) 262 config.flags3 |= CFG3pic; 263 config.objfmt = OBJ_ELF; 264 config.ehmethod = useExceptions ? EHmethod.EH_DM : EHmethod.EH_NONE; 265 } 266 config.flags2 |= CFG2nodeflib; // no default library 267 config.flags3 |= CFG3eseqds; 268 static if (0) 269 { 270 if (env.getEEcontext().EEcompile != 2) 271 config.flags4 |= CFG4allcomdat; 272 if (env.nochecks()) 273 config.flags4 |= CFG4nochecks; // no runtime checking 274 } 275 else static if (TARGET_OSX) 276 { 277 } 278 else 279 { 280 config.flags4 |= CFG4allcomdat; 281 } 282 if (trace) 283 config.flags |= CFGtrace; // turn on profiler 284 if (nofloat) 285 config.flags3 |= CFG3wkfloat; 286 287 configv.verbose = verbose; 288 289 if (optimize) 290 go_flag(cast(char*)"-o".ptr); 291 292 if (symdebug) 293 { 294 static if (SYMDEB_DWARF) 295 { 296 configv.addlinenumbers = 1; 297 config.fulltypes = (symdebug == 1) ? CVDWARF_D : CVDWARF_C; 298 } 299 static if (SYMDEB_CODEVIEW) 300 { 301 if (config.objfmt == OBJ_MSCOFF) 302 { 303 configv.addlinenumbers = 1; 304 config.fulltypes = CV8; 305 if(symdebug > 1) 306 config.flags2 |= CFG2gms; 307 } 308 else 309 { 310 configv.addlinenumbers = 1; 311 config.fulltypes = CV4; 312 } 313 } 314 if (!optimize) 315 config.flags |= CFGalwaysframe; 316 } 317 else 318 { 319 configv.addlinenumbers = 0; 320 config.fulltypes = CVNONE; 321 //config.flags &= ~CFGalwaysframe; 322 } 323 324 if (alwaysframe) 325 config.flags |= CFGalwaysframe; 326 if (stackstomp) 327 config.flags2 |= CFG2stomp; 328 329 config.useModuleInfo = useModuleInfo; 330 config.useTypeInfo = useTypeInfo; 331 config.useExceptions = useExceptions; 332 333 ph_init(); 334 block_init(); 335 336 cod3_setdefault(); 337 if (model == 64) 338 { 339 util_set64(); 340 type_init(); 341 cod3_set64(); 342 } 343 else 344 { 345 util_set32(); 346 type_init(); 347 cod3_set32(); 348 } 349 350 rtlsym_init(); // uses fregsaved, so must be after it's set inside cod3_set* 351 } 352 } 353 354 debug 355 { 356 357 /**************************** 358 * Transmit internal compiler debugging flags. 359 */ 360 void out_config_debug( 361 bool b, 362 bool c, 363 bool f, 364 bool r, 365 bool w, 366 bool x, 367 bool y 368 ) 369 { 370 debugb = b; 371 debugc = c; 372 debugf = f; 373 debugr = r; 374 debugw = w; 375 debugx = x; 376 debugy = y; 377 } 378 379 } 380 381 /************************************* 382 */ 383 384 void util_set16() 385 { 386 // The default is 16 bits 387 _tysize[TYldouble] = 10; 388 _tysize[TYildouble] = 10; 389 _tysize[TYcldouble] = 20; 390 391 _tyalignsize[TYldouble] = 2; 392 _tyalignsize[TYildouble] = 2; 393 _tyalignsize[TYcldouble] = 2; 394 } 395 396 /******************************* 397 * Redo tables from 8086/286 to 386/486. 398 */ 399 400 void util_set32() 401 { 402 _tyrelax[TYenum] = TYlong; 403 _tyrelax[TYint] = TYlong; 404 _tyrelax[TYuint] = TYlong; 405 406 tyequiv[TYint] = TYlong; 407 tyequiv[TYuint] = TYulong; 408 409 _tysize[TYenum] = LONGSIZE; 410 _tysize[TYint ] = LONGSIZE; 411 _tysize[TYuint] = LONGSIZE; 412 _tysize[TYnullptr] = LONGSIZE; 413 _tysize[TYnptr] = LONGSIZE; 414 _tysize[TYnref] = LONGSIZE; 415 static if (TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS) 416 { 417 _tysize[TYldouble] = 12; 418 _tysize[TYildouble] = 12; 419 _tysize[TYcldouble] = 24; 420 } 421 else static if (TARGET_OSX) 422 { 423 _tysize[TYldouble] = 16; 424 _tysize[TYildouble] = 16; 425 _tysize[TYcldouble] = 32; 426 } 427 else static if (TARGET_WINDOS) 428 { 429 _tysize[TYldouble] = 10; 430 _tysize[TYildouble] = 10; 431 _tysize[TYcldouble] = 20; 432 } 433 else 434 { 435 assert(0); 436 } 437 _tysize[TYsptr] = LONGSIZE; 438 _tysize[TYcptr] = LONGSIZE; 439 _tysize[TYfptr] = 6; // NOTE: There are codgen test that check 440 _tysize[TYvptr] = 6; // _tysize[x] == _tysize[TYfptr] so don't set 441 _tysize[TYfref] = 6; // _tysize[TYfptr] to _tysize[TYnptr] 442 443 _tyalignsize[TYenum] = LONGSIZE; 444 _tyalignsize[TYint ] = LONGSIZE; 445 _tyalignsize[TYuint] = LONGSIZE; 446 _tyalignsize[TYnullptr] = LONGSIZE; 447 _tyalignsize[TYnref] = LONGSIZE; 448 _tyalignsize[TYnptr] = LONGSIZE; 449 static if (TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS) 450 { 451 _tyalignsize[TYldouble] = 4; 452 _tyalignsize[TYildouble] = 4; 453 _tyalignsize[TYcldouble] = 4; 454 } 455 else static if (TARGET_OSX) 456 { 457 _tyalignsize[TYldouble] = 16; 458 _tyalignsize[TYildouble] = 16; 459 _tyalignsize[TYcldouble] = 16; 460 } 461 else static if (TARGET_WINDOS) 462 { 463 _tyalignsize[TYldouble] = 2; 464 _tyalignsize[TYildouble] = 2; 465 _tyalignsize[TYcldouble] = 2; 466 } 467 else 468 { 469 assert(0); 470 } 471 _tyalignsize[TYsptr] = LONGSIZE; 472 _tyalignsize[TYcptr] = LONGSIZE; 473 _tyalignsize[TYfptr] = LONGSIZE; // NOTE: There are codgen test that check 474 _tyalignsize[TYvptr] = LONGSIZE; // _tysize[x] == _tysize[TYfptr] so don't set 475 _tyalignsize[TYfref] = LONGSIZE; // _tysize[TYfptr] to _tysize[TYnptr] 476 477 _tysize[TYimmutPtr] = _tysize[TYnptr]; 478 _tysize[TYsharePtr] = _tysize[TYnptr]; 479 _tysize[TYrestrictPtr] = _tysize[TYnptr]; 480 _tysize[TYfgPtr] = _tysize[TYnptr]; 481 _tyalignsize[TYimmutPtr] = _tyalignsize[TYnptr]; 482 _tyalignsize[TYsharePtr] = _tyalignsize[TYnptr]; 483 _tyalignsize[TYrestrictPtr] = _tyalignsize[TYnptr]; 484 _tyalignsize[TYfgPtr] = _tyalignsize[TYnptr]; 485 } 486 487 /******************************* 488 * Redo tables from 8086/286 to I64. 489 */ 490 491 void util_set64() 492 { 493 _tyrelax[TYenum] = TYlong; 494 _tyrelax[TYint] = TYlong; 495 _tyrelax[TYuint] = TYlong; 496 497 tyequiv[TYint] = TYlong; 498 tyequiv[TYuint] = TYulong; 499 500 _tysize[TYenum] = LONGSIZE; 501 _tysize[TYint ] = LONGSIZE; 502 _tysize[TYuint] = LONGSIZE; 503 _tysize[TYnullptr] = 8; 504 _tysize[TYnptr] = 8; 505 _tysize[TYnref] = 8; 506 static if (TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS || TARGET_OSX) 507 { 508 _tysize[TYldouble] = 16; 509 _tysize[TYildouble] = 16; 510 _tysize[TYcldouble] = 32; 511 } 512 else static if (TARGET_WINDOS) 513 { 514 _tysize[TYldouble] = 10; 515 _tysize[TYildouble] = 10; 516 _tysize[TYcldouble] = 20; 517 } 518 else 519 { 520 assert(0); 521 } 522 _tysize[TYsptr] = 8; 523 _tysize[TYcptr] = 8; 524 _tysize[TYfptr] = 10; // NOTE: There are codgen test that check 525 _tysize[TYvptr] = 10; // _tysize[x] == _tysize[TYfptr] so don't set 526 _tysize[TYfref] = 10; // _tysize[TYfptr] to _tysize[TYnptr] 527 528 _tyalignsize[TYenum] = LONGSIZE; 529 _tyalignsize[TYint ] = LONGSIZE; 530 _tyalignsize[TYuint] = LONGSIZE; 531 _tyalignsize[TYnullptr] = 8; 532 _tyalignsize[TYnptr] = 8; 533 _tyalignsize[TYnref] = 8; 534 static if (TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS) 535 { 536 _tyalignsize[TYldouble] = 16; 537 _tyalignsize[TYildouble] = 16; 538 _tyalignsize[TYcldouble] = 16; 539 } 540 else static if (TARGET_OSX) 541 { 542 _tyalignsize[TYldouble] = 16; 543 _tyalignsize[TYildouble] = 16; 544 _tyalignsize[TYcldouble] = 16; 545 } 546 else static if (TARGET_WINDOS) 547 { 548 _tyalignsize[TYldouble] = 2; 549 _tyalignsize[TYildouble] = 2; 550 _tyalignsize[TYcldouble] = 2; 551 } 552 else 553 { 554 assert(0); 555 } 556 _tyalignsize[TYsptr] = 8; 557 _tyalignsize[TYcptr] = 8; 558 _tyalignsize[TYfptr] = 8; 559 _tyalignsize[TYvptr] = 8; 560 _tyalignsize[TYfref] = 8; 561 tytab[TYjfunc] &= ~TYFLpascal; // set so caller cleans the stack (as in C) 562 563 TYptrdiff = TYllong; 564 TYsize = TYullong; 565 TYsize_t = TYullong; 566 TYdelegate = TYcent; 567 TYdarray = TYucent; 568 569 _tysize[TYimmutPtr] = _tysize[TYnptr]; 570 _tysize[TYsharePtr] = _tysize[TYnptr]; 571 _tysize[TYrestrictPtr] = _tysize[TYnptr]; 572 _tysize[TYfgPtr] = _tysize[TYnptr]; 573 _tyalignsize[TYimmutPtr] = _tyalignsize[TYnptr]; 574 _tyalignsize[TYsharePtr] = _tyalignsize[TYnptr]; 575 _tyalignsize[TYrestrictPtr] = _tyalignsize[TYnptr]; 576 _tyalignsize[TYfgPtr] = _tyalignsize[TYnptr]; 577 } 578