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