]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/target.d
d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6.
[thirdparty/gcc.git] / gcc / d / dmd / target.d
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
30 enum 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 */
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;
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 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 */
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 * 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,
320 DM, /// Digital Mars 32 bit C compiler
321 MS, /// Microsoft 32 and 64 bit C compilers
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;