1 /** 2 * Handles target-specific parameters 3 * 4 * In order to allow for cross compilation, when the compiler produces a binary 5 * for a different platform than it is running on, target information needs 6 * to be abstracted. This is done in this module, primarily through `Target`. 7 * 8 * Note: 9 * While DMD itself does not support cross-compilation, GDC and LDC do. 10 * Hence, this module is (sometimes heavily) modified by them, 11 * and contributors should review how their changes affect them. 12 * 13 * See_Also: 14 * - $(LINK2 https://wiki.osdev.org/Target_Triplet, Target Triplets) 15 * - $(LINK2 https://github.com/ldc-developers/ldc, LDC repository) 16 * - $(LINK2 https://github.com/D-Programming-GDC/gcc, GDC repository) 17 * 18 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 19 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 20 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 21 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/target.d, _target.d) 22 * Documentation: https://dlang.org/phobos/dmd_target.html 23 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/target.d 24 */ 25 26 module dmd.target; 27 28 import dmd.argtypes; 29 import core.stdc.string : strlen; 30 import dmd.cppmangle; 31 import dmd.cppmanglewin; 32 import dmd.dclass; 33 import dmd.declaration; 34 import dmd.dstruct; 35 import dmd.dsymbol; 36 import dmd.expression; 37 import dmd.func; 38 import dmd.globals; 39 import dmd.id; 40 import dmd.identifier; 41 import dmd.mtype; 42 import dmd.typesem; 43 import dmd.tokens : TOK; 44 import dmd.root.ctfloat; 45 import dmd.root.outbuffer; 46 import dmd.root.string : toDString; 47 48 //////////////////////////////////////////////////////////////////////////////// 49 /** 50 * Describes a back-end target. At present it is incomplete, but in the future 51 * it should grow to contain most or all target machine and target O/S specific 52 * information. 53 * 54 * In many cases, calls to sizeof() can't be used directly for getting data type 55 * sizes since cross compiling is supported and would end up using the host 56 * sizes rather than the target sizes. 57 */ 58 extern (C++) struct Target 59 { 60 // D ABI 61 uint ptrsize; /// size of a pointer in bytes 62 uint realsize; /// size a real consumes in memory 63 uint realpad; /// padding added to the CPU real size to bring it up to realsize 64 uint realalignsize; /// alignment for reals 65 uint classinfosize; /// size of `ClassInfo` 66 ulong maxStaticDataSize; /// maximum size of static data 67 68 /// C ABI 69 TargetC c; 70 71 /// C++ ABI 72 TargetCPP cpp; 73 74 /// Objective-C ABI 75 TargetObjC objc; 76 77 /** 78 * Values representing all properties for floating point types 79 */ 80 extern (C++) struct FPTypeProperties(T) 81 { 82 real_t max; /// largest representable value that's not infinity 83 real_t min_normal; /// smallest representable normalized value that's not 0 84 real_t nan; /// NaN value 85 real_t infinity; /// infinity value 86 real_t epsilon; /// smallest increment to the value 1 87 88 d_int64 dig = T.dig; /// number of decimal digits of precision 89 d_int64 mant_dig = T.mant_dig; /// number of bits in mantissa 90 d_int64 max_exp = T.max_exp; /// maximum int value such that 2$(SUPERSCRIPT `max_exp-1`) is representable 91 d_int64 min_exp = T.min_exp; /// minimum int value such that 2$(SUPERSCRIPT `min_exp-1`) is representable as a normalized value 92 d_int64 max_10_exp = T.max_10_exp; /// maximum int value such that 10$(SUPERSCRIPT `max_10_exp` is representable) 93 d_int64 min_10_exp = T.min_10_exp; /// minimum int value such that 10$(SUPERSCRIPT `min_10_exp`) is representable as a normalized value 94 95 extern (D) void initialize() 96 { 97 max = T.max; 98 min_normal = T.min_normal; 99 nan = T.nan; 100 infinity = T.infinity; 101 epsilon = T.epsilon; 102 } 103 } 104 105 FPTypeProperties!float FloatProperties; /// 106 FPTypeProperties!double DoubleProperties; /// 107 FPTypeProperties!real_t RealProperties; /// 108 109 /** 110 * Initialize the Target 111 */ 112 extern (C++) void _init(ref const Param params) 113 { 114 FloatProperties.initialize(); 115 DoubleProperties.initialize(); 116 RealProperties.initialize(); 117 118 // These have default values for 32 bit code, they get 119 // adjusted for 64 bit code. 120 ptrsize = 4; 121 classinfosize = 0x4C; // 76 122 123 /* gcc uses int.max for 32 bit compilations, and long.max for 64 bit ones. 124 * Set to int.max for both, because the rest of the compiler cannot handle 125 * 2^64-1 without some pervasive rework. The trouble is that much of the 126 * front and back end uses 32 bit ints for sizes and offsets. Since C++ 127 * silently truncates 64 bit ints to 32, finding all these dependencies will be a problem. 128 */ 129 maxStaticDataSize = int.max; 130 131 if (params.isLP64) 132 { 133 ptrsize = 8; 134 classinfosize = 0x98; // 152 135 } 136 if (params.isLinux || params.isFreeBSD || params.isOpenBSD || params.isDragonFlyBSD || params.isSolaris) 137 { 138 realsize = 12; 139 realpad = 2; 140 realalignsize = 4; 141 } 142 else if (params.isOSX) 143 { 144 realsize = 16; 145 realpad = 6; 146 realalignsize = 16; 147 } 148 else if (params.isWindows) 149 { 150 realsize = 10; 151 realpad = 0; 152 realalignsize = 2; 153 if (ptrsize == 4) 154 { 155 /* Optlink cannot deal with individual data chunks 156 * larger than 16Mb 157 */ 158 maxStaticDataSize = 0x100_0000; // 16Mb 159 } 160 } 161 else 162 assert(0); 163 if (params.is64bit) 164 { 165 if (params.isLinux || params.isFreeBSD || params.isDragonFlyBSD || params.isSolaris) 166 { 167 realsize = 16; 168 realpad = 6; 169 realalignsize = 16; 170 } 171 } 172 173 c.initialize(params, this); 174 cpp.initialize(params, this); 175 objc.initialize(params, this); 176 } 177 178 /** 179 * Deinitializes the global state of the compiler. 180 * 181 * This can be used to restore the state set by `_init` to its original 182 * state. 183 */ 184 void deinitialize() 185 { 186 this = this.init; 187 } 188 189 /** 190 * Requested target memory alignment size of the given type. 191 * Params: 192 * type = type to inspect 193 * Returns: 194 * alignment in bytes 195 */ 196 extern (C++) uint alignsize(Type type) 197 { 198 assert(type.isTypeBasic()); 199 switch (type.ty) 200 { 201 case Tfloat80: 202 case Timaginary80: 203 case Tcomplex80: 204 return target.realalignsize; 205 case Tcomplex32: 206 if (global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isOpenBSD || 207 global.params.isDragonFlyBSD || global.params.isSolaris) 208 return 4; 209 break; 210 case Tint64: 211 case Tuns64: 212 case Tfloat64: 213 case Timaginary64: 214 case Tcomplex64: 215 if (global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isOpenBSD || 216 global.params.isDragonFlyBSD || global.params.isSolaris) 217 return global.params.is64bit ? 8 : 4; 218 break; 219 default: 220 break; 221 } 222 return cast(uint)type.size(Loc.initial); 223 } 224 225 /** 226 * Requested target field alignment size of the given type. 227 * Params: 228 * type = type to inspect 229 * Returns: 230 * alignment in bytes 231 */ 232 extern (C++) uint fieldalign(Type type) 233 { 234 const size = type.alignsize(); 235 236 if ((global.params.is64bit || global.params.isOSX) && (size == 16 || size == 32)) 237 return size; 238 239 return (8 < size) ? 8 : size; 240 } 241 242 /** 243 * Size of the target OS critical section. 244 * Returns: 245 * size in bytes 246 */ 247 extern (C++) uint critsecsize() 248 { 249 return c.criticalSectionSize; 250 } 251 252 /** 253 * Type for the `va_list` type for the target. 254 * NOTE: For Posix/x86_64 this returns the type which will really 255 * be used for passing an argument of type va_list. 256 * Returns: 257 * `Type` that represents `va_list`. 258 */ 259 extern (C++) Type va_listType() 260 { 261 if (global.params.isWindows) 262 { 263 return Type.tchar.pointerTo(); 264 } 265 else if (global.params.isLinux || global.params.isFreeBSD || global.params.isOpenBSD || global.params.isDragonFlyBSD || 266 global.params.isSolaris || global.params.isOSX) 267 { 268 if (global.params.is64bit) 269 { 270 return (new TypeIdentifier(Loc.initial, Identifier.idPool("__va_list_tag"))).pointerTo(); 271 } 272 else 273 { 274 return Type.tchar.pointerTo(); 275 } 276 } 277 else 278 { 279 assert(0); 280 } 281 } 282 283 /** 284 * Checks whether the target supports a vector type. 285 * Params: 286 * sz = vector type size in bytes 287 * type = vector element type 288 * Returns: 289 * 0 vector type is supported, 290 * 1 vector type is not supported on the target at all 291 * 2 vector element type is not supported 292 * 3 vector size is not supported 293 */ 294 extern (C++) int isVectorTypeSupported(int sz, Type type) 295 { 296 if (!isXmmSupported()) 297 return 1; // not supported 298 299 switch (type.ty) 300 { 301 case Tvoid: 302 case Tint8: 303 case Tuns8: 304 case Tint16: 305 case Tuns16: 306 case Tint32: 307 case Tuns32: 308 case Tfloat32: 309 case Tint64: 310 case Tuns64: 311 case Tfloat64: 312 break; 313 default: 314 return 2; // wrong base type 315 } 316 if (sz != 16 && !(global.params.cpu >= CPU.avx && sz == 32)) 317 return 3; // wrong size 318 return 0; 319 } 320 321 /** 322 * Checks whether the target supports the given operation for vectors. 323 * Params: 324 * type = target type of operation 325 * op = the unary or binary op being done on the `type` 326 * t2 = type of second operand if `op` is a binary operation 327 * Returns: 328 * true if the operation is supported or type is not a vector 329 */ 330 extern (C++) bool isVectorOpSupported(Type type, ubyte op, Type t2 = null) 331 { 332 import dmd.tokens; 333 334 if (type.ty != Tvector) 335 return true; // not a vector op 336 auto tvec = cast(TypeVector) type; 337 338 bool supported; 339 switch (op) 340 { 341 case TOK.negate, TOK.uadd: 342 supported = tvec.isscalar(); 343 break; 344 345 case TOK.lessThan, TOK.greaterThan, TOK.lessOrEqual, TOK.greaterOrEqual, TOK.equal, TOK.notEqual, TOK.identity, TOK.notIdentity: 346 supported = false; 347 break; 348 349 case TOK.leftShift, TOK.leftShiftAssign, TOK.rightShift, TOK.rightShiftAssign, TOK.unsignedRightShift, TOK.unsignedRightShiftAssign: 350 supported = false; 351 break; 352 353 case TOK.add, TOK.addAssign, TOK.min, TOK.minAssign: 354 supported = tvec.isscalar(); 355 break; 356 357 case TOK.mul, TOK.mulAssign: 358 // only floats and short[8]/ushort[8] (PMULLW) 359 if (tvec.isfloating() || tvec.elementType().size(Loc.initial) == 2 || 360 // int[4]/uint[4] with SSE4.1 (PMULLD) 361 global.params.cpu >= CPU.sse4_1 && tvec.elementType().size(Loc.initial) == 4) 362 supported = true; 363 else 364 supported = false; 365 break; 366 367 case TOK.div, TOK.divAssign: 368 supported = tvec.isfloating(); 369 break; 370 371 case TOK.mod, TOK.modAssign: 372 supported = false; 373 break; 374 375 case TOK.and, TOK.andAssign, TOK.or, TOK.orAssign, TOK.xor, TOK.xorAssign: 376 supported = tvec.isintegral(); 377 break; 378 379 case TOK.not: 380 supported = false; 381 break; 382 383 case TOK.tilde: 384 supported = tvec.isintegral(); 385 break; 386 387 case TOK.pow, TOK.powAssign: 388 supported = false; 389 break; 390 391 default: 392 // import std.stdio : stderr, writeln; 393 // stderr.writeln(op); 394 assert(0, "unhandled op " ~ Token.toString(cast(TOK)op)); 395 } 396 return supported; 397 } 398 399 /** 400 * Default system linkage for the target. 401 * Returns: 402 * `LINK` to use for `extern(System)` 403 */ 404 extern (C++) LINK systemLinkage() 405 { 406 return global.params.isWindows ? LINK.windows : LINK.c; 407 } 408 409 /** 410 * Describes how an argument type is passed to a function on target. 411 * Params: 412 * t = type to break down 413 * Returns: 414 * tuple of types if type is passed in one or more registers 415 * empty tuple if type is always passed on the stack 416 * null if the type is a `void` or argtypes aren't supported by the target 417 */ 418 extern (C++) TypeTuple toArgTypes(Type t) 419 { 420 if (global.params.is64bit && global.params.isWindows) 421 return null; 422 return .toArgTypes(t); 423 } 424 425 /** 426 * Determine return style of function - whether in registers or 427 * through a hidden pointer to the caller's stack. 428 * Params: 429 * tf = function type to check 430 * needsThis = true if the function type is for a non-static member function 431 * Returns: 432 * true if return value from function is on the stack 433 */ 434 extern (C++) bool isReturnOnStack(TypeFunction tf, bool needsThis) 435 { 436 if (tf.isref) 437 { 438 //printf(" ref false\n"); 439 return false; // returns a pointer 440 } 441 442 Type tn = tf.next.toBasetype(); 443 //printf("tn = %s\n", tn.toChars()); 444 d_uns64 sz = tn.size(); 445 Type tns = tn; 446 447 if (global.params.isWindows && global.params.is64bit) 448 { 449 // http://msdn.microsoft.com/en-us/library/7572ztz4.aspx 450 if (tns.ty == Tcomplex32) 451 return true; 452 if (tns.isscalar()) 453 return false; 454 455 tns = tns.baseElemOf(); 456 if (tns.ty == Tstruct) 457 { 458 StructDeclaration sd = (cast(TypeStruct)tns).sym; 459 if (tf.linkage == LINK.cpp && needsThis) 460 return true; 461 if (!sd.isPOD() || sz > 8) 462 return true; 463 if (sd.fields.dim == 0) 464 return true; 465 } 466 if (sz <= 16 && !(sz & (sz - 1))) 467 return false; 468 return true; 469 } 470 else if (global.params.isWindows && global.params.mscoff) 471 { 472 Type tb = tns.baseElemOf(); 473 if (tb.ty == Tstruct) 474 { 475 if (tf.linkage == LINK.cpp && needsThis) 476 return true; 477 } 478 } 479 480 Lagain: 481 if (tns.ty == Tsarray) 482 { 483 tns = tns.baseElemOf(); 484 if (tns.ty != Tstruct) 485 { 486 L2: 487 if (global.params.isLinux && tf.linkage != LINK.d && !global.params.is64bit) 488 { 489 // 32 bit C/C++ structs always on stack 490 } 491 else 492 { 493 switch (sz) 494 { 495 case 1: 496 case 2: 497 case 4: 498 case 8: 499 //printf(" sarray false\n"); 500 return false; // return small structs in regs 501 // (not 3 byte structs!) 502 default: 503 break; 504 } 505 } 506 //printf(" sarray true\n"); 507 return true; 508 } 509 } 510 511 if (tns.ty == Tstruct) 512 { 513 StructDeclaration sd = (cast(TypeStruct)tns).sym; 514 if (global.params.isLinux && tf.linkage != LINK.d && !global.params.is64bit) 515 { 516 //printf(" 2 true\n"); 517 return true; // 32 bit C/C++ structs always on stack 518 } 519 if (global.params.isWindows && tf.linkage == LINK.cpp && !global.params.is64bit && 520 sd.isPOD() && sd.ctor) 521 { 522 // win32 returns otherwise POD structs with ctors via memory 523 return true; 524 } 525 if (sd.arg1type && !sd.arg2type) 526 { 527 tns = sd.arg1type; 528 if (tns.ty != Tstruct) 529 goto L2; 530 goto Lagain; 531 } 532 else if (global.params.is64bit && !sd.arg1type && !sd.arg2type) 533 return true; 534 else if (sd.isPOD()) 535 { 536 switch (sz) 537 { 538 case 1: 539 case 2: 540 case 4: 541 case 8: 542 //printf(" 3 false\n"); 543 return false; // return small structs in regs 544 // (not 3 byte structs!) 545 case 16: 546 if (!global.params.isWindows && global.params.is64bit) 547 return false; 548 break; 549 550 default: 551 break; 552 } 553 } 554 //printf(" 3 true\n"); 555 return true; 556 } 557 else if ((global.params.isLinux || global.params.isOSX || 558 global.params.isFreeBSD || global.params.isSolaris || 559 global.params.isDragonFlyBSD) && 560 tf.linkage == LINK.c && 561 tns.iscomplex()) 562 { 563 if (tns.ty == Tcomplex32) 564 return false; // in EDX:EAX, not ST1:ST0 565 else 566 return true; 567 } 568 else 569 { 570 //assert(sz <= 16); 571 //printf(" 4 false\n"); 572 return false; 573 } 574 } 575 576 /*** 577 * Determine the size a value of type `t` will be when it 578 * is passed on the function parameter stack. 579 * Params: 580 * loc = location to use for error messages 581 * t = type of parameter 582 * Returns: 583 * size used on parameter stack 584 */ 585 extern (C++) ulong parameterSize(const ref Loc loc, Type t) 586 { 587 if (!global.params.is64bit && 588 (global.params.isFreeBSD || global.params.isOSX)) 589 { 590 /* These platforms use clang, which regards a struct 591 * with size 0 as being of size 0 on the parameter stack, 592 * even while sizeof(struct) is 1. 593 * It's an ABI incompatibility with gcc. 594 */ 595 if (t.ty == Tstruct) 596 { 597 auto ts = cast(TypeStruct)t; 598 if (ts.sym.hasNoFields) 599 return 0; 600 } 601 } 602 const sz = t.size(loc); 603 return global.params.is64bit ? (sz + 7) & ~7 : (sz + 3) & ~3; 604 } 605 606 // this guarantees `getTargetInfo` and `allTargetInfos` remain in sync 607 private enum TargetInfoKeys 608 { 609 cppRuntimeLibrary, 610 cppStd, 611 floatAbi, 612 objectFormat, 613 } 614 615 /** 616 * Get targetInfo by key 617 * Params: 618 * name = name of targetInfo to get 619 * loc = location to use for error messages 620 * Returns: 621 * Expression for the requested targetInfo 622 */ 623 extern (C++) Expression getTargetInfo(const(char)* name, const ref Loc loc) 624 { 625 StringExp stringExp(const(char)[] sval) 626 { 627 return new StringExp(loc, sval); 628 } 629 630 switch (name.toDString) with (TargetInfoKeys) 631 { 632 case objectFormat.stringof: 633 if (global.params.isWindows) 634 return stringExp(global.params.mscoff ? "coff" : "omf"); 635 else if (global.params.isOSX) 636 return stringExp("macho"); 637 else 638 return stringExp("elf"); 639 case floatAbi.stringof: 640 return stringExp("hard"); 641 case cppRuntimeLibrary.stringof: 642 if (global.params.isWindows) 643 { 644 if (global.params.mscoff) 645 return stringExp(global.params.mscrtlib); 646 return stringExp("snn"); 647 } 648 return stringExp(""); 649 case cppStd.stringof: 650 return new IntegerExp(cast(uint)global.params.cplusplus); 651 652 default: 653 return null; 654 } 655 } 656 657 //////////////////////////////////////////////////////////////////////////// 658 /* All functions after this point are extern (D), as they are only relevant 659 * for targets of DMD, and should not be used in front-end code. 660 */ 661 662 /****************** 663 * Returns: 664 * true if xmm usage is supported 665 */ 666 extern (D) bool isXmmSupported() 667 { 668 return global.params.is64bit || global.params.isOSX; 669 } 670 671 /** 672 * Returns: 673 * true if generating code for POSIX 674 */ 675 extern (D) @property bool isPOSIX() scope const nothrow @nogc 676 out(result) { assert(result || global.params.isWindows); } 677 do 678 { 679 return global.params.isLinux 680 || global.params.isOSX 681 || global.params.isFreeBSD 682 || global.params.isOpenBSD 683 || global.params.isDragonFlyBSD 684 || global.params.isSolaris; 685 } 686 } 687 688 //////////////////////////////////////////////////////////////////////////////// 689 /** 690 * Functions and variables specific to interfacing with extern(C) ABI. 691 */ 692 struct TargetC 693 { 694 uint longsize; /// size of a C `long` or `unsigned long` type 695 uint long_doublesize; /// size of a C `long double` 696 uint criticalSectionSize; /// size of os critical section 697 698 extern (D) void initialize(ref const Param params, ref const Target target) 699 { 700 if (params.isLinux || params.isFreeBSD || params.isOpenBSD || params.isDragonFlyBSD || params.isSolaris) 701 longsize = 4; 702 else if (params.isOSX) 703 longsize = 4; 704 else if (params.isWindows) 705 longsize = 4; 706 else 707 assert(0); 708 if (params.is64bit) 709 { 710 if (params.isLinux || params.isFreeBSD || params.isDragonFlyBSD || params.isSolaris) 711 longsize = 8; 712 else if (params.isOSX) 713 longsize = 8; 714 } 715 if (params.is64bit && params.isWindows) 716 long_doublesize = 8; 717 else 718 long_doublesize = target.realsize; 719 720 criticalSectionSize = getCriticalSectionSize(params); 721 } 722 723 private static uint getCriticalSectionSize(ref const Param params) pure 724 { 725 if (params.isWindows) 726 { 727 // sizeof(CRITICAL_SECTION) for Windows. 728 return params.isLP64 ? 40 : 24; 729 } 730 else if (params.isLinux) 731 { 732 // sizeof(pthread_mutex_t) for Linux. 733 if (params.is64bit) 734 return params.isLP64 ? 40 : 32; 735 else 736 return params.isLP64 ? 40 : 24; 737 } 738 else if (params.isFreeBSD) 739 { 740 // sizeof(pthread_mutex_t) for FreeBSD. 741 return params.isLP64 ? 8 : 4; 742 } 743 else if (params.isOpenBSD) 744 { 745 // sizeof(pthread_mutex_t) for OpenBSD. 746 return params.isLP64 ? 8 : 4; 747 } 748 else if (params.isDragonFlyBSD) 749 { 750 // sizeof(pthread_mutex_t) for DragonFlyBSD. 751 return params.isLP64 ? 8 : 4; 752 } 753 else if (params.isOSX) 754 { 755 // sizeof(pthread_mutex_t) for OSX. 756 return params.isLP64 ? 64 : 44; 757 } 758 else if (params.isSolaris) 759 { 760 // sizeof(pthread_mutex_t) for Solaris. 761 return 24; 762 } 763 assert(0); 764 } 765 } 766 767 //////////////////////////////////////////////////////////////////////////////// 768 /** 769 * Functions and variables specific to interface with extern(C++) ABI. 770 */ 771 struct TargetCPP 772 { 773 bool reverseOverloads; /// set if overloaded functions are grouped and in reverse order (such as in dmc and cl) 774 bool exceptions; /// set if catching C++ exceptions is supported 775 bool twoDtorInVtable; /// target C++ ABI puts deleting and non-deleting destructor into vtable 776 777 extern (D) void initialize(ref const Param params, ref const Target target) 778 { 779 if (params.isLinux || params.isFreeBSD || params.isOpenBSD || params.isDragonFlyBSD || params.isSolaris) 780 twoDtorInVtable = true; 781 else if (params.isOSX) 782 twoDtorInVtable = true; 783 else if (params.isWindows) 784 reverseOverloads = true; 785 else 786 assert(0); 787 exceptions = params.isLinux || params.isFreeBSD || 788 params.isDragonFlyBSD || params.isOSX; 789 } 790 791 /** 792 * Mangle the given symbol for C++ ABI. 793 * Params: 794 * s = declaration with C++ linkage 795 * Returns: 796 * string mangling of symbol 797 */ 798 extern (C++) const(char)* toMangle(Dsymbol s) 799 { 800 static if (TARGET.Linux || TARGET.OSX || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.DragonFlyBSD || TARGET.Solaris) 801 return toCppMangleItanium(s); 802 else static if (TARGET.Windows) 803 return toCppMangleMSVC(s); 804 else 805 static assert(0, "fix this"); 806 } 807 808 /** 809 * Get RTTI mangling of the given class declaration for C++ ABI. 810 * Params: 811 * cd = class with C++ linkage 812 * Returns: 813 * string mangling of C++ typeinfo 814 */ 815 extern (C++) const(char)* typeInfoMangle(ClassDeclaration cd) 816 { 817 static if (TARGET.Linux || TARGET.OSX || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD) 818 return cppTypeInfoMangleItanium(cd); 819 else static if (TARGET.Windows) 820 return cppTypeInfoMangleMSVC(cd); 821 else 822 static assert(0, "fix this"); 823 } 824 825 /** 826 * Gets vendor-specific type mangling for C++ ABI. 827 * Params: 828 * t = type to inspect 829 * Returns: 830 * string if type is mangled specially on target 831 * null if unhandled 832 */ 833 extern (C++) const(char)* typeMangle(Type t) 834 { 835 return null; 836 } 837 838 /** 839 * Get the type that will really be used for passing the given argument 840 * to an `extern(C++)` function. 841 * Params: 842 * p = parameter to be passed. 843 * Returns: 844 * `Type` to use for parameter `p`. 845 */ 846 extern (C++) Type parameterType(Parameter p) 847 { 848 Type t = p.type.merge2(); 849 if (p.storageClass & (STC.out_ | STC.ref_)) 850 t = t.referenceTo(); 851 else if (p.storageClass & STC.lazy_) 852 { 853 // Mangle as delegate 854 Type td = new TypeFunction(ParameterList(), t, LINK.d); 855 td = new TypeDelegate(td); 856 t = merge(t); 857 } 858 return t; 859 } 860 861 /** 862 * Checks whether type is a vendor-specific fundamental type. 863 * Params: 864 * t = type to inspect 865 * isFundamental = where to store result 866 * Returns: 867 * true if isFundamental was set by function 868 */ 869 extern (C++) bool fundamentalType(const Type t, ref bool isFundamental) 870 { 871 return false; 872 } 873 } 874 875 //////////////////////////////////////////////////////////////////////////////// 876 /** 877 * Functions and variables specific to interface with extern(Objective-C) ABI. 878 */ 879 struct TargetObjC 880 { 881 bool supported; /// set if compiler can interface with Objective-C 882 883 extern (D) void initialize(ref const Param params, ref const Target target) 884 { 885 if (params.isOSX && params.is64bit) 886 supported = true; 887 } 888 } 889 890 //////////////////////////////////////////////////////////////////////////////// 891 extern (C++) __gshared Target target;