]>
Commit | Line | Data |
---|---|---|
5fee5ec3 IB |
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-2021 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.globals : Param; | |
29 | ||
9c7d5e88 | 30 | enum CPU : ubyte |
5fee5ec3 IB |
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 | */ | |
59 | extern (C++) struct Target | |
60 | { | |
61 | import dmd.dscope : Scope; | |
62 | import dmd.expression : Expression; | |
63 | import dmd.func : FuncDeclaration; | |
64 | import dmd.globals : LINK, Loc, d_int64; | |
65 | import dmd.astenums : TY; | |
66 | import dmd.mtype : Type, TypeFunction, TypeTuple; | |
67 | import dmd.root.ctfloat : real_t; | |
68 | import dmd.statement : Statement; | |
9c7d5e88 | 69 | import dmd.tokens : EXP; |
5fee5ec3 IB |
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 | Freestanding = 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 mscoff = false; // for Win32: write MsCoff object files instead of OMF | |
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 | d_int64 dig; /// number of decimal digits of precision | |
135 | d_int64 mant_dig; /// number of bits in mantissa | |
136 | d_int64 max_exp; /// maximum int value such that 2$(SUPERSCRIPT `max_exp-1`) is representable | |
137 | d_int64 min_exp; /// minimum int value such that 2$(SUPERSCRIPT `min_exp-1`) is representable as a normalized value | |
138 | d_int64 max_10_exp; /// maximum int value such that 10$(SUPERSCRIPT `max_10_exp` is representable) | |
139 | d_int64 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 | */ | |
9c7d5e88 | 217 | extern (C++) bool isVectorOpSupported(Type type, EXP op, Type t2 = null); |
5fee5ec3 IB |
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 | * Determine the size a value of type `t` will be when it | |
250 | * is passed on the function parameter stack. | |
251 | * Params: | |
252 | * loc = location to use for error messages | |
253 | * t = type of parameter | |
254 | * Returns: | |
255 | * size used on parameter stack | |
256 | */ | |
257 | extern (C++) ulong parameterSize(const ref Loc loc, Type t); | |
258 | ||
259 | /** | |
260 | * Decides whether an `in` parameter of the specified POD type is to be | |
261 | * passed by reference or by value. To be used with `-preview=in` only! | |
262 | * Params: | |
263 | * t = type of the `in` parameter, must be a POD | |
264 | * Returns: | |
265 | * `true` if the `in` parameter is to be passed by reference | |
266 | */ | |
267 | extern(C++) bool preferPassByRef(Type t); | |
268 | ||
269 | /** | |
270 | * Get targetInfo by key | |
271 | * Params: | |
272 | * name = name of targetInfo to get | |
273 | * loc = location to use for error messages | |
274 | * Returns: | |
275 | * Expression for the requested targetInfo | |
276 | */ | |
277 | extern (C++) Expression getTargetInfo(const(char)* name, const ref Loc loc); | |
278 | ||
279 | /** | |
280 | * Params: | |
281 | * tf = type of function being called | |
282 | * Returns: `true` if the callee invokes destructors for arguments. | |
283 | */ | |
284 | extern (C++) bool isCalleeDestroyingArgs(TypeFunction tf); | |
285 | ||
286 | /** | |
287 | * Returns true if the implementation for object monitors is always defined | |
288 | * in the D runtime library (rt/monitor_.d). | |
289 | * Params: | |
290 | * fd = function with `synchronized` storage class. | |
291 | * fbody = entire function body of `fd` | |
292 | * Returns: | |
293 | * `false` if the target backend handles synchronizing monitors. | |
294 | */ | |
295 | extern (C++) bool libraryObjectMonitors(FuncDeclaration fd, Statement fbody); | |
296 | } | |
297 | ||
298 | //////////////////////////////////////////////////////////////////////////////// | |
299 | /** | |
300 | * Functions and variables specific to interfacing with extern(C) ABI. | |
301 | */ | |
302 | struct TargetC | |
303 | { | |
304 | enum Runtime : ubyte | |
305 | { | |
306 | Unspecified, | |
307 | Bionic, | |
308 | DigitalMars, | |
309 | Glibc, | |
310 | Microsoft, | |
311 | Musl, | |
312 | Newlib, | |
313 | UClibc, | |
314 | WASI, | |
315 | } | |
316 | ||
317 | enum BitFieldStyle : ubyte | |
318 | { | |
319 | Unspecified, | |
0fb57034 IB |
320 | DM, /// Digital Mars 32 bit C compiler |
321 | MS, /// Microsoft 32 and 64 bit C compilers | |
5fee5ec3 IB |
322 | /// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160 |
323 | /// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160 | |
324 | Gcc_Clang, /// gcc and clang | |
325 | } | |
326 | ||
327 | ubyte longsize; /// size of a C `long` or `unsigned 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 | */ | |
338 | struct TargetCPP | |
339 | { | |
340 | import dmd.dsymbol : Dsymbol; | |
341 | import dmd.dclass : ClassDeclaration; | |
342 | import dmd.func : FuncDeclaration; | |
343 | import dmd.mtype : Parameter, 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 wrapDtorInExternD; /// set if C++ dtors require a D wrapper to be callable from runtime | |
358 | Runtime runtime; /// vendor of the C++ runtime to link against | |
359 | ||
360 | /** | |
361 | * Mangle the given symbol for C++ ABI. | |
362 | * Params: | |
363 | * s = declaration with C++ linkage | |
364 | * Returns: | |
365 | * string mangling of symbol | |
366 | */ | |
367 | extern (C++) const(char)* toMangle(Dsymbol s); | |
368 | ||
369 | /** | |
370 | * Get RTTI mangling of the given class declaration for C++ ABI. | |
371 | * Params: | |
372 | * cd = class with C++ linkage | |
373 | * Returns: | |
374 | * string mangling of C++ typeinfo | |
375 | */ | |
376 | extern (C++) const(char)* typeInfoMangle(ClassDeclaration cd); | |
377 | ||
378 | /** | |
379 | * Get mangle name of a this-adjusting thunk to the given function | |
380 | * declaration for C++ ABI. | |
381 | * Params: | |
382 | * fd = function with C++ linkage | |
383 | * offset = call offset to the vptr | |
384 | * Returns: | |
385 | * string mangling of C++ thunk, or null if unhandled | |
386 | */ | |
387 | extern (C++) const(char)* thunkMangle(FuncDeclaration fd, int offset); | |
388 | ||
389 | /** | |
390 | * Gets vendor-specific type mangling for C++ ABI. | |
391 | * Params: | |
392 | * t = type to inspect | |
393 | * Returns: | |
394 | * string if type is mangled specially on target | |
395 | * null if unhandled | |
396 | */ | |
397 | extern (C++) const(char)* typeMangle(Type t); | |
398 | ||
399 | /** | |
400 | * Get the type that will really be used for passing the given argument | |
401 | * to an `extern(C++)` function. | |
402 | * Params: | |
403 | * p = parameter to be passed. | |
404 | * Returns: | |
405 | * `Type` to use for parameter `p`. | |
406 | */ | |
407 | extern (C++) Type parameterType(Parameter p); | |
408 | ||
409 | /** | |
410 | * Checks whether type is a vendor-specific fundamental type. | |
411 | * Params: | |
412 | * t = type to inspect | |
413 | * isFundamental = where to store result | |
414 | * Returns: | |
415 | * true if isFundamental was set by function | |
416 | */ | |
417 | extern (C++) bool fundamentalType(const Type t, ref bool isFundamental); | |
418 | ||
419 | /** | |
420 | * Get the starting offset position for fields of an `extern(C++)` class | |
421 | * that is derived from the given base class. | |
422 | * Params: | |
423 | * baseClass = base class with C++ linkage | |
424 | * Returns: | |
425 | * starting offset to lay out derived class fields | |
426 | */ | |
427 | extern (C++) uint derivedClassOffset(ClassDeclaration baseClass); | |
428 | } | |
429 | ||
430 | //////////////////////////////////////////////////////////////////////////////// | |
431 | /** | |
432 | * Functions and variables specific to interface with extern(Objective-C) ABI. | |
433 | */ | |
434 | struct TargetObjC | |
435 | { | |
436 | bool supported; /// set if compiler can interface with Objective-C | |
437 | } | |
438 | ||
439 | //////////////////////////////////////////////////////////////////////////////// | |
440 | extern (C++) __gshared Target target; |