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-2022 by The D Language Foundation, All Rights Reserved 19 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 20 * License: $(LINK2 https://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 26module dmd.target; 27 28import dmd.globals : Param; 29 30enum CPU : ubyte 31{ 32 x87, 33 mmx, 34 sse, 35 sse2, 36 sse3, 37 ssse3, 38 sse4_1, 39 sse4_2, 40 avx, // AVX1 instruction set 41 avx2, // AVX2 instruction set 42 avx512, // AVX-512 instruction set 43 44 // Special values that don't survive past the command line processing 45 baseline, // (default) the minimum capability CPU 46 native // the machine the compiler is being run on 47} 48 49//////////////////////////////////////////////////////////////////////////////// 50/** 51 * Describes a back-end target. At present it is incomplete, but in the future 52 * it should grow to contain most or all target machine and target O/S specific 53 * information. 54 * 55 * In many cases, calls to sizeof() can't be used directly for getting data type 56 * sizes since cross compiling is supported and would end up using the host 57 * sizes rather than the target sizes. 58 */ 59extern (C++) struct Target 60{ 61 import dmd.dscope : Scope; 62 import dmd.expression : Expression; 63 import dmd.func : FuncDeclaration; 64 import dmd.globals : Loc; 65 import dmd.astenums : LINK, TY; 66 import dmd.mtype : Type, TypeFunction, TypeTuple; 67 import dmd.root.ctfloat : real_t; 68 import dmd.statement : Statement; 69 import dmd.tokens : EXP; 70 71 /// Bit decoding of the Target.OS 72 enum OS : ubyte 73 { 74 /* These are mutually exclusive; one and only one is set. 75 * Match spelling and casing of corresponding version identifiers 76 */ 77 none = 0, 78 linux = 1, 79 Windows = 2, 80 OSX = 4, 81 OpenBSD = 8, 82 FreeBSD = 0x10, 83 Solaris = 0x20, 84 DragonFlyBSD = 0x40, 85 86 // Combination masks 87 all = linux | Windows | OSX | OpenBSD | FreeBSD | Solaris | DragonFlyBSD, 88 Posix = linux | OSX | OpenBSD | FreeBSD | Solaris | DragonFlyBSD, 89 } 90 91 OS os; 92 ubyte osMajor; 93 94 // D ABI 95 ubyte ptrsize; /// size of a pointer in bytes 96 ubyte realsize; /// size a real consumes in memory 97 ubyte realpad; /// padding added to the CPU real size to bring it up to realsize 98 ubyte realalignsize; /// alignment for reals 99 ubyte classinfosize; /// size of `ClassInfo` 100 ulong maxStaticDataSize; /// maximum size of static data 101 102 /// C ABI 103 TargetC c; 104 105 /// C++ ABI 106 TargetCPP cpp; 107 108 /// Objective-C ABI 109 TargetObjC objc; 110 111 /// Architecture name 112 const(char)[] architectureName; 113 CPU cpu = CPU.baseline; // CPU instruction set to target 114 bool is64bit; // generate 64 bit code for x86_64; true by default for 64 bit dmd 115 bool isLP64; // pointers are 64 bits 116 117 // Environmental 118 const(char)[] obj_ext; /// extension for object files 119 const(char)[] lib_ext; /// extension for static library files 120 const(char)[] dll_ext; /// extension for dynamic library files 121 bool run_noext; /// allow -run sources without extensions 122 bool omfobj = false; // for Win32: write OMF object files instead of MsCoff 123 /** 124 * Values representing all properties for floating point types 125 */ 126 extern (C++) struct FPTypeProperties(T) 127 { 128 real_t max; /// largest representable value that's not infinity 129 real_t min_normal; /// smallest representable normalized value that's not 0 130 real_t nan; /// NaN value 131 real_t infinity; /// infinity value 132 real_t epsilon; /// smallest increment to the value 1 133 134 long dig; /// number of decimal digits of precision 135 long mant_dig; /// number of bits in mantissa 136 long max_exp; /// maximum int value such that 2$(SUPERSCRIPT `max_exp-1`) is representable 137 long min_exp; /// minimum int value such that 2$(SUPERSCRIPT `min_exp-1`) is representable as a normalized value 138 long max_10_exp; /// maximum int value such that 10$(SUPERSCRIPT `max_10_exp` is representable) 139 long min_10_exp; /// minimum int value such that 10$(SUPERSCRIPT `min_10_exp`) is representable as a normalized value 140 } 141 142 FPTypeProperties!float FloatProperties; /// 143 FPTypeProperties!double DoubleProperties; /// 144 FPTypeProperties!real_t RealProperties; /// 145 146 private Type tvalist; // cached lazy result of va_listType() 147 148 private const(Param)* params; // cached reference to global.params 149 150 /** 151 * Initialize the Target 152 */ 153 extern (C++) void _init(ref const Param params); 154 155 156 /** 157 * Deinitializes the global state of the compiler. 158 * 159 * This can be used to restore the state set by `_init` to its original 160 * state. 161 */ 162 void deinitialize() 163 { 164 this = this.init; 165 } 166 167 /** 168 * Requested target memory alignment size of the given type. 169 * Params: 170 * type = type to inspect 171 * Returns: 172 * alignment in bytes 173 */ 174 extern (C++) uint alignsize(Type type); 175 176 /** 177 * Requested target field alignment size of the given type. 178 * Params: 179 * type = type to inspect 180 * Returns: 181 * alignment in bytes 182 */ 183 extern (C++) uint fieldalign(Type type); 184 185 /** 186 * Type for the `va_list` type for the target; e.g., required for `_argptr` 187 * declarations. 188 * NOTE: For Posix/x86_64 this returns the type which will really 189 * be used for passing an argument of type va_list. 190 * Returns: 191 * `Type` that represents `va_list`. 192 */ 193 extern (C++) Type va_listType(const ref Loc loc, Scope* sc); 194 195 /** 196 * Checks whether the target supports a vector type. 197 * Params: 198 * sz = vector type size in bytes 199 * type = vector element type 200 * Returns: 201 * 0 vector type is supported, 202 * 1 vector type is not supported on the target at all 203 * 2 vector element type is not supported 204 * 3 vector size is not supported 205 */ 206 extern (C++) int isVectorTypeSupported(int sz, Type type); 207 208 /** 209 * Checks whether the target supports the given operation for vectors. 210 * Params: 211 * type = target type of operation 212 * op = the unary or binary op being done on the `type` 213 * t2 = type of second operand if `op` is a binary operation 214 * Returns: 215 * true if the operation is supported or type is not a vector 216 */ 217 extern (C++) bool isVectorOpSupported(Type type, EXP op, Type t2 = null); 218 219 /** 220 * Default system linkage for the target. 221 * Returns: 222 * `LINK` to use for `extern(System)` 223 */ 224 extern (C++) LINK systemLinkage(); 225 226 /** 227 * Describes how an argument type is passed to a function on target. 228 * Params: 229 * t = type to break down 230 * Returns: 231 * tuple of types if type is passed in one or more registers 232 * empty tuple if type is always passed on the stack 233 * null if the type is a `void` or argtypes aren't supported by the target 234 */ 235 extern (C++) TypeTuple toArgTypes(Type t); 236 237 /** 238 * Determine return style of function - whether in registers or 239 * through a hidden pointer to the caller's stack. 240 * Params: 241 * tf = function type to check 242 * needsThis = true if the function type is for a non-static member function 243 * Returns: 244 * true if return value from function is on the stack 245 */ 246 extern (C++) bool isReturnOnStack(TypeFunction tf, bool needsThis); 247 248 /** 249 * Decides whether an `in` parameter of the specified POD type is to be 250 * passed by reference or by value. To be used with `-preview=in` only! 251 * Params: 252 * t = type of the `in` parameter, must be a POD 253 * Returns: 254 * `true` if the `in` parameter is to be passed by reference 255 */ 256 extern(C++) bool preferPassByRef(Type t); 257 258 /** 259 * Get targetInfo by key 260 * Params: 261 * name = name of targetInfo to get 262 * loc = location to use for error messages 263 * Returns: 264 * Expression for the requested targetInfo 265 */ 266 extern (C++) Expression getTargetInfo(const(char)* name, const ref Loc loc); 267 268 /** 269 * Params: 270 * tf = type of function being called 271 * Returns: `true` if the callee invokes destructors for arguments. 272 */ 273 extern (C++) bool isCalleeDestroyingArgs(TypeFunction tf); 274 275 /** 276 * Returns true if the implementation for object monitors is always defined 277 * in the D runtime library (rt/monitor_.d). 278 * Params: 279 * fd = function with `synchronized` storage class. 280 * fbody = entire function body of `fd` 281 * Returns: 282 * `false` if the target backend handles synchronizing monitors. 283 */ 284 extern (C++) bool libraryObjectMonitors(FuncDeclaration fd, Statement fbody); 285 286 /** 287 * Returns true if the target supports `pragma(linkerDirective)`. 288 * Returns: 289 * `false` if the target does not support `pragma(linkerDirective)`. 290 */ 291 extern (C++) bool supportsLinkerDirective() const; 292} 293 294//////////////////////////////////////////////////////////////////////////////// 295/** 296 * Functions and variables specific to interfacing with extern(C) ABI. 297 */ 298struct TargetC 299{ 300 enum Runtime : ubyte 301 { 302 Unspecified, 303 Bionic, 304 DigitalMars, 305 Glibc, 306 Microsoft, 307 Musl, 308 Newlib, 309 UClibc, 310 WASI, 311 } 312 313 enum BitFieldStyle : ubyte 314 { 315 Unspecified, 316 DM, /// Digital Mars 32 bit C compiler 317 MS, /// Microsoft 32 and 64 bit C compilers 318 /// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160 319 /// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160 320 Gcc_Clang, /// gcc and clang 321 } 322 bool crtDestructorsSupported = true; /// Not all platforms support crt_destructor 323 ubyte boolsize; /// size of a C `_Bool` type 324 ubyte shortsize; /// size of a C `short` or `unsigned short` type 325 ubyte intsize; /// size of a C `int` or `unsigned int` type 326 ubyte longsize; /// size of a C `long` or `unsigned long` type 327 ubyte long_longsize; /// size of a C `long long` or `unsigned long long` type 328 ubyte long_doublesize; /// size of a C `long double` 329 ubyte wchar_tsize; /// size of a C `wchar_t` type 330 Runtime runtime; /// vendor of the C runtime to link against 331 BitFieldStyle bitFieldStyle; /// different C compilers do it differently 332} 333 334//////////////////////////////////////////////////////////////////////////////// 335/** 336 * Functions and variables specific to interface with extern(C++) ABI. 337 */ 338struct TargetCPP 339{ 340 import dmd.dsymbol : Dsymbol; 341 import dmd.dclass : ClassDeclaration; 342 import dmd.func : FuncDeclaration; 343 import dmd.mtype : Type; 344 345 enum Runtime : ubyte 346 { 347 Unspecified, 348 Clang, 349 DigitalMars, 350 Gcc, 351 Microsoft, 352 Sun 353 } 354 bool reverseOverloads; /// set if overloaded functions are grouped and in reverse order (such as in dmc and cl) 355 bool exceptions; /// set if catching C++ exceptions is supported 356 bool twoDtorInVtable; /// target C++ ABI puts deleting and non-deleting destructor into vtable 357 bool splitVBasetable; /// set if C++ ABI uses separate tables for virtual functions and virtual bases 358 bool wrapDtorInExternD; /// set if C++ dtors require a D wrapper to be callable from runtime 359 Runtime runtime; /// vendor of the C++ runtime to link against 360 361 /** 362 * Mangle the given symbol for C++ ABI. 363 * Params: 364 * s = declaration with C++ linkage 365 * Returns: 366 * string mangling of symbol 367 */ 368 extern (C++) const(char)* toMangle(Dsymbol s); 369 370 /** 371 * Get RTTI mangling of the given class declaration for C++ ABI. 372 * Params: 373 * cd = class with C++ linkage 374 * Returns: 375 * string mangling of C++ typeinfo 376 */ 377 extern (C++) const(char)* typeInfoMangle(ClassDeclaration cd); 378 379 /** 380 * Get mangle name of a this-adjusting thunk to the given function 381 * declaration for C++ ABI. 382 * Params: 383 * fd = function with C++ linkage 384 * offset = call offset to the vptr 385 * Returns: 386 * string mangling of C++ thunk, or null if unhandled 387 */ 388 extern (C++) const(char)* thunkMangle(FuncDeclaration fd, int offset); 389 390 /** 391 * Gets vendor-specific type mangling for C++ ABI. 392 * Params: 393 * t = type to inspect 394 * Returns: 395 * string if type is mangled specially on target 396 * null if unhandled 397 */ 398 extern (C++) const(char)* typeMangle(Type t); 399 400 /** 401 * Get the type that will really be used for passing the given argument 402 * to an `extern(C++)` function, or `null` if unhandled. 403 * Params: 404 * t = type to be passed. 405 * Returns: 406 * `Type` to use for type `t`. 407 */ 408 extern (C++) Type parameterType(Type t); 409 410 /** 411 * Checks whether type is a vendor-specific fundamental type. 412 * Params: 413 * t = type to inspect 414 * isFundamental = where to store result 415 * Returns: 416 * true if isFundamental was set by function 417 */ 418 extern (C++) bool fundamentalType(const Type t, ref bool isFundamental); 419 420 /** 421 * Get the starting offset position for fields of an `extern(C++)` class 422 * that is derived from the given base class. 423 * Params: 424 * baseClass = base class with C++ linkage 425 * Returns: 426 * starting offset to lay out derived class fields 427 */ 428 extern (C++) uint derivedClassOffset(ClassDeclaration baseClass); 429} 430 431//////////////////////////////////////////////////////////////////////////////// 432/** 433 * Functions and variables specific to interface with extern(Objective-C) ABI. 434 */ 435struct TargetObjC 436{ 437 bool supported; /// set if compiler can interface with Objective-C 438} 439 440//////////////////////////////////////////////////////////////////////////////// 441extern (C++) __gshared Target target; 442