]>
Commit | Line | Data |
---|---|---|
b4c522fa | 1 | /* d-target.cc -- Target interface for the D front end. |
a945c346 | 2 | Copyright (C) 2013-2024 Free Software Foundation, Inc. |
b4c522fa IB |
3 | |
4 | GCC is free software; you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation; either version 3, or (at your option) | |
7 | any later version. | |
8 | ||
9 | GCC is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with GCC; see the file COPYING3. If not see | |
16 | <http://www.gnu.org/licenses/>. */ | |
17 | ||
18 | #include "config.h" | |
19 | #include "system.h" | |
20 | #include "coretypes.h" | |
21 | ||
22 | #include "dmd/aggregate.h" | |
23 | #include "dmd/declaration.h" | |
24 | #include "dmd/expression.h" | |
25 | #include "dmd/mangle.h" | |
26 | #include "dmd/mtype.h" | |
27 | #include "dmd/tokens.h" | |
28 | #include "dmd/target.h" | |
29 | ||
30 | #include "tree.h" | |
31 | #include "memmodel.h" | |
32 | #include "fold-const.h" | |
de83a4c1 | 33 | #include "diagnostic.h" |
b4c522fa IB |
34 | #include "stor-layout.h" |
35 | #include "tm.h" | |
36 | #include "tm_p.h" | |
37 | #include "target.h" | |
5fee5ec3 | 38 | #include "calls.h" |
b4c522fa IB |
39 | |
40 | #include "d-tree.h" | |
41 | #include "d-target.h" | |
42 | ||
43 | /* Implements the Target interface defined by the front end. | |
44 | Used for retrieving target-specific information. */ | |
45 | ||
c5e94699 IB |
46 | /* Internal key handlers for `__traits(getTargetInfo)'. */ |
47 | static tree d_handle_target_cpp_std (void); | |
48 | static tree d_handle_target_cpp_runtime_library (void); | |
d81bc495 | 49 | static tree d_handle_target_object_format (void); |
c5e94699 IB |
50 | |
51 | /* In [traits/getTargetInfo], a reliable subset of getTargetInfo keys exists | |
52 | which are always available. */ | |
53 | static const struct d_target_info_spec d_language_target_info[] = | |
54 | { | |
55 | /* { name, handler } */ | |
56 | { "cppStd", d_handle_target_cpp_std }, | |
57 | { "cppRuntimeLibrary", d_handle_target_cpp_runtime_library }, | |
58 | { "floatAbi", NULL }, | |
d81bc495 | 59 | { "objectFormat", d_handle_target_object_format }, |
c5e94699 IB |
60 | { NULL, NULL }, |
61 | }; | |
62 | ||
63 | /* Table `__traits(getTargetInfo)' keys. */ | |
64 | static vec<d_target_info_spec> d_target_info_table; | |
65 | ||
b4c522fa IB |
66 | |
67 | /* Initialize the floating-point constants for TYPE. */ | |
68 | ||
69 | template <typename T> | |
70 | static void | |
5905cbdb | 71 | define_float_constants (T &f, tree type) |
b4c522fa IB |
72 | { |
73 | const double log10_2 = 0.30102999566398119521; | |
74 | char buf[128]; | |
75 | ||
76 | /* Get back-end real mode format. */ | |
77 | const machine_mode mode = TYPE_MODE (type); | |
78 | const real_format *fmt = REAL_MODE_FORMAT (mode); | |
79 | ||
80 | /* The largest representable value that's not infinity. */ | |
00be2a5f | 81 | get_max_float (fmt, buf, sizeof (buf), false); |
5905cbdb | 82 | real_from_string (&f.max.rv (), buf); |
b4c522fa IB |
83 | |
84 | /* The smallest representable normalized value that's not 0. */ | |
85 | snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - 1); | |
5905cbdb | 86 | real_from_string (&f.min_normal.rv (), buf); |
b4c522fa IB |
87 | |
88 | /* Floating-point NaN. */ | |
5905cbdb | 89 | real_nan (&f.nan.rv (), "", 1, mode); |
b4c522fa | 90 | |
b4c522fa | 91 | /* Floating-point +Infinity if the target supports infinities. */ |
5905cbdb | 92 | real_inf (&f.infinity.rv ()); |
b4c522fa IB |
93 | |
94 | /* The smallest increment to the value 1. */ | |
95 | if (fmt->pnan < fmt->p) | |
96 | snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - fmt->p); | |
97 | else | |
98 | snprintf (buf, sizeof (buf), "0x1p%d", 1 - fmt->p); | |
5905cbdb | 99 | real_from_string (&f.epsilon.rv (), buf); |
b4c522fa IB |
100 | |
101 | /* The number of decimal digits of precision. */ | |
5905cbdb | 102 | f.dig = (fmt->p - 1) * log10_2; |
b4c522fa IB |
103 | |
104 | /* The number of bits in mantissa. */ | |
5905cbdb | 105 | f.mant_dig = fmt->p; |
b4c522fa IB |
106 | |
107 | /* The maximum int value such that 2** (value-1) is representable. */ | |
5905cbdb | 108 | f.max_exp = fmt->emax; |
b4c522fa IB |
109 | |
110 | /* The minimum int value such that 2** (value-1) is representable as a | |
111 | normalized value. */ | |
5905cbdb | 112 | f.min_exp = fmt->emin; |
b4c522fa IB |
113 | |
114 | /* The maximum int value such that 10**value is representable. */ | |
5905cbdb | 115 | f.max_10_exp = fmt->emax * log10_2; |
b4c522fa IB |
116 | |
117 | /* The minimum int value such that 10**value is representable as a | |
118 | normalized value. */ | |
5905cbdb | 119 | f.min_10_exp = (fmt->emin - 1) * log10_2; |
b4c522fa IB |
120 | } |
121 | ||
122 | /* Initialize all variables of the Target structure. */ | |
123 | ||
124 | void | |
5905cbdb | 125 | Target::_init (const Param &) |
b4c522fa IB |
126 | { |
127 | /* Map D frontend type and sizes to GCC back-end types. */ | |
5905cbdb IB |
128 | this->ptrsize = (POINTER_SIZE / BITS_PER_UNIT); |
129 | this->realsize = int_size_in_bytes (long_double_type_node); | |
130 | this->realpad = (this->realsize - | |
131 | (TYPE_PRECISION (long_double_type_node) / BITS_PER_UNIT)); | |
132 | this->realalignsize = TYPE_ALIGN_UNIT (long_double_type_node); | |
b4c522fa | 133 | |
b0a55e66 IB |
134 | /* Much of the dmd front-end uses ints for sizes and offsets, and cannot |
135 | handle any larger data type without some pervasive rework. */ | |
5905cbdb | 136 | this->maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (integer_type_node)); |
b4c522fa IB |
137 | |
138 | /* Define what type to use for size_t, ptrdiff_t. */ | |
5905cbdb | 139 | if (this->ptrsize == 8) |
b4c522fa | 140 | { |
5fee5ec3 IB |
141 | this->isLP64 = true; |
142 | Type::tsize_t = Type::basic[(int)TY::Tuns64]; | |
143 | Type::tptrdiff_t = Type::basic[(int)TY::Tint64]; | |
b4c522fa | 144 | } |
5905cbdb | 145 | else if (this->ptrsize == 4) |
b4c522fa | 146 | { |
5fee5ec3 IB |
147 | Type::tsize_t = Type::basic[(int)TY::Tuns32]; |
148 | Type::tptrdiff_t = Type::basic[(int)TY::Tint32]; | |
b4c522fa | 149 | } |
5905cbdb | 150 | else if (this->ptrsize == 2) |
de83a4c1 | 151 | { |
5fee5ec3 IB |
152 | Type::tsize_t = Type::basic[(int)TY::Tuns16]; |
153 | Type::tptrdiff_t = Type::basic[(int)TY::Tint16]; | |
de83a4c1 IB |
154 | } |
155 | else | |
156 | sorry ("D does not support pointers on this target."); | |
b4c522fa | 157 | |
b4c522fa IB |
158 | Type::thash_t = Type::tsize_t; |
159 | ||
160 | /* Set-up target C ABI. */ | |
1027dc45 IB |
161 | this->c.boolsize = (BOOL_TYPE_SIZE / BITS_PER_UNIT); |
162 | this->c.shortsize = (SHORT_TYPE_SIZE / BITS_PER_UNIT); | |
163 | this->c.intsize = (INT_TYPE_SIZE / BITS_PER_UNIT); | |
164 | this->c.longsize = (LONG_TYPE_SIZE / BITS_PER_UNIT); | |
165 | this->c.long_longsize = (LONG_LONG_TYPE_SIZE / BITS_PER_UNIT); | |
166 | this->c.long_doublesize = (LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT); | |
5fee5ec3 | 167 | this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT); |
1027dc45 | 168 | |
d7569187 IB |
169 | this->c.bitFieldStyle = targetm.ms_bitfield_layout_p (unknown_type_node) |
170 | ? TargetC::BitFieldStyle::MS : TargetC::BitFieldStyle::Gcc_Clang; | |
5a0aa603 | 171 | |
b4c522fa | 172 | /* Set-up target C++ ABI. */ |
5905cbdb IB |
173 | this->cpp.reverseOverloads = false; |
174 | this->cpp.exceptions = true; | |
175 | this->cpp.twoDtorInVtable = true; | |
176 | ||
177 | /* Set-up target Objective-C ABI. */ | |
178 | this->objc.supported = false; | |
b4c522fa | 179 | |
5fee5ec3 IB |
180 | /* Set-up environmental settings. */ |
181 | this->obj_ext = "o"; | |
182 | this->lib_ext = "a"; | |
183 | this->dll_ext = "so"; | |
184 | this->run_noext = true; | |
185 | ||
b4c522fa IB |
186 | /* Initialize all compile-time properties for floating-point types. |
187 | Should ensure that our real_t type is able to represent real_value. */ | |
188 | gcc_assert (sizeof (real_t) >= sizeof (real_value)); | |
189 | ||
5905cbdb IB |
190 | define_float_constants (this->FloatProperties, float_type_node); |
191 | define_float_constants (this->DoubleProperties, double_type_node); | |
192 | define_float_constants (this->RealProperties, long_double_type_node); | |
b4c522fa IB |
193 | |
194 | /* Commonly used floating-point constants. */ | |
195 | const machine_mode mode = TYPE_MODE (long_double_type_node); | |
196 | real_convert (&CTFloat::zero.rv (), mode, &dconst0); | |
197 | real_convert (&CTFloat::one.rv (), mode, &dconst1); | |
198 | real_convert (&CTFloat::minusone.rv (), mode, &dconstm1); | |
199 | real_convert (&CTFloat::half.rv (), mode, &dconsthalf); | |
c5e94699 IB |
200 | |
201 | /* Initialize target info tables, the keys required by the language are added | |
202 | last, so that the OS and CPU handlers can override. */ | |
3785d2b2 | 203 | targetdm.d_register_cpu_target_info (); |
527bc018 | 204 | targetdm.d_register_os_target_info (); |
c5e94699 | 205 | d_add_target_info_handlers (d_language_target_info); |
b4c522fa IB |
206 | } |
207 | ||
208 | /* Return GCC memory alignment size for type TYPE. */ | |
209 | ||
210 | unsigned | |
211 | Target::alignsize (Type *type) | |
212 | { | |
213 | gcc_assert (type->isTypeBasic ()); | |
d7815fc4 | 214 | return min_align_of_type (build_ctype (type)); |
b4c522fa IB |
215 | } |
216 | ||
217 | /* Return GCC field alignment size for type TYPE. */ | |
218 | ||
219 | unsigned | |
220 | Target::fieldalign (Type *type) | |
221 | { | |
222 | /* Work out the correct alignment for the field decl. */ | |
223 | unsigned int align = type->alignsize () * BITS_PER_UNIT; | |
224 | ||
225 | #ifdef BIGGEST_FIELD_ALIGNMENT | |
226 | align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT); | |
227 | #endif | |
228 | ||
229 | #ifdef ADJUST_FIELD_ALIGN | |
230 | if (type->isTypeBasic ()) | |
231 | align = ADJUST_FIELD_ALIGN (NULL_TREE, build_ctype (type), align); | |
232 | #endif | |
233 | ||
234 | /* Also controlled by -fpack-struct= */ | |
235 | if (maximum_field_alignment) | |
236 | align = MIN (align, maximum_field_alignment); | |
237 | ||
238 | return align / BITS_PER_UNIT; | |
239 | } | |
240 | ||
b4c522fa IB |
241 | /* Returns a Type for the va_list type of the target. */ |
242 | ||
243 | Type * | |
5905cbdb | 244 | Target::va_listType (const Loc &, Scope *) |
b4c522fa | 245 | { |
5905cbdb IB |
246 | if (this->tvalist) |
247 | return this->tvalist; | |
248 | ||
249 | /* Build the "standard" abi va_list. */ | |
250 | this->tvalist = build_frontend_type (va_list_type_node); | |
251 | if (!this->tvalist) | |
252 | sorry ("cannot represent built-in %<va_list%> type in D"); | |
253 | ||
254 | /* Map the va_list type to the D frontend Type. This is to prevent both | |
255 | errors in gimplification or an ICE in targetm.canonical_va_list_type. */ | |
256 | this->tvalist->ctype = va_list_type_node; | |
257 | TYPE_LANG_SPECIFIC (va_list_type_node) = build_lang_type (this->tvalist); | |
258 | ||
259 | return this->tvalist; | |
b4c522fa IB |
260 | } |
261 | ||
262 | /* Checks whether the target supports a vector type with total size SZ | |
263 | (in bytes) and element type TYPE. */ | |
264 | ||
265 | int | |
266 | Target::isVectorTypeSupported (int sz, Type *type) | |
267 | { | |
268 | /* Size must be greater than zero, and a power of two. */ | |
269 | if (sz <= 0 || sz & (sz - 1)) | |
19f6b41a | 270 | return 3; |
b4c522fa IB |
271 | |
272 | /* __vector(void[]) is treated same as __vector(ubyte[]) */ | |
273 | if (type == Type::tvoid) | |
274 | type = Type::tuns8; | |
275 | ||
f0a3bab4 | 276 | /* No support for non-trivial types, complex types, or booleans. */ |
5fee5ec3 | 277 | if (!type->isTypeBasic () || type->iscomplex () || type->ty == TY::Tbool) |
19f6b41a | 278 | return 2; |
b4c522fa | 279 | |
f0a3bab4 IB |
280 | /* In [simd/vector extensions], which vector types are supported depends on |
281 | the target. The implementation is expected to only support the vector | |
282 | types that are implemented in the target's hardware. */ | |
283 | unsigned HOST_WIDE_INT nunits = sz / type->size (); | |
284 | tree ctype = build_vector_type (build_ctype (type), nunits); | |
b4c522fa | 285 | |
f0a3bab4 | 286 | if (!targetm.vector_mode_supported_p (TYPE_MODE (ctype))) |
19f6b41a | 287 | return 2; |
b4c522fa IB |
288 | |
289 | return 0; | |
290 | } | |
291 | ||
292 | /* Checks whether the target supports operation OP for vectors of type TYPE. | |
293 | For binary ops T2 is the type of the right-hand operand. | |
294 | Returns true if the operation is supported or type is not a vector. */ | |
295 | ||
296 | bool | |
9c7d5e88 | 297 | Target::isVectorOpSupported (Type *type, EXP op, Type *) |
b4c522fa | 298 | { |
5fee5ec3 | 299 | if (type->ty != TY::Tvector) |
b4c522fa IB |
300 | return true; |
301 | ||
302 | /* Don't support if type is non-scalar, such as __vector(void[]). */ | |
303 | if (!type->isscalar ()) | |
304 | return false; | |
305 | ||
306 | /* Don't support if expression cannot be represented. */ | |
307 | switch (op) | |
308 | { | |
9c7d5e88 IB |
309 | case EXP::pow: |
310 | case EXP::powAssign: | |
b4c522fa IB |
311 | /* pow() is lowered as a function call. */ |
312 | return false; | |
313 | ||
9c7d5e88 IB |
314 | case EXP::mod: |
315 | case EXP::modAssign: | |
b4c522fa IB |
316 | /* fmod() is lowered as a function call. */ |
317 | if (type->isfloating ()) | |
318 | return false; | |
319 | break; | |
320 | ||
9c7d5e88 IB |
321 | case EXP::andAnd: |
322 | case EXP::orOr: | |
b4c522fa IB |
323 | /* Logical operators must have a result type of bool. */ |
324 | return false; | |
325 | ||
b4c522fa IB |
326 | default: |
327 | break; | |
328 | } | |
329 | ||
330 | return true; | |
331 | } | |
332 | ||
333 | /* Return the symbol mangling of S for C++ linkage. */ | |
334 | ||
335 | const char * | |
5905cbdb | 336 | TargetCPP::toMangle (Dsymbol *s) |
b4c522fa IB |
337 | { |
338 | return toCppMangleItanium (s); | |
339 | } | |
340 | ||
341 | /* Return the symbol mangling of CD for C++ linkage. */ | |
342 | ||
343 | const char * | |
5905cbdb | 344 | TargetCPP::typeInfoMangle (ClassDeclaration *cd) |
b4c522fa IB |
345 | { |
346 | return cppTypeInfoMangleItanium (cd); | |
347 | } | |
348 | ||
5d4b824f IB |
349 | /* Get mangle name of a this-adjusting thunk to the function declaration FD |
350 | at call offset OFFSET for C++ linkage. */ | |
351 | ||
352 | const char * | |
353 | TargetCPP::thunkMangle (FuncDeclaration *fd, int offset) | |
354 | { | |
355 | return cppThunkMangleItanium (fd, offset); | |
356 | } | |
357 | ||
b4c522fa IB |
358 | /* For a vendor-specific type, return a string containing the C++ mangling. |
359 | In all other cases, return NULL. */ | |
360 | ||
361 | const char * | |
5905cbdb | 362 | TargetCPP::typeMangle (Type *type) |
b4c522fa | 363 | { |
5fee5ec3 IB |
364 | if (type->isTypeBasic () || type->ty == TY::Tvector |
365 | || type->ty == TY::Tstruct) | |
b4c522fa IB |
366 | { |
367 | tree ctype = build_ctype (type); | |
368 | return targetm.mangle_type (ctype); | |
369 | } | |
370 | ||
371 | return NULL; | |
372 | } | |
373 | ||
374 | /* Return the type that will really be used for passing the given parameter | |
375 | ARG to an extern(C++) function. */ | |
376 | ||
377 | Type * | |
d7569187 | 378 | TargetCPP::parameterType (Type *type) |
b4c522fa | 379 | { |
b4c522fa | 380 | /* Could be a va_list, which we mangle as a pointer. */ |
5905cbdb | 381 | Type *tvalist = target.va_listType (Loc (), NULL); |
d7569187 | 382 | if (type->ty == TY::Tsarray && tvalist->ty == TY::Tsarray) |
b4c522fa | 383 | { |
d7569187 | 384 | Type *tb = type->toBasetype ()->mutableOf (); |
5905cbdb | 385 | if (tb == tvalist) |
b4c522fa | 386 | { |
d7569187 IB |
387 | tb = type->nextOf ()->pointerTo (); |
388 | type = tb->castMod (type->mod); | |
b4c522fa IB |
389 | } |
390 | } | |
391 | ||
d7569187 | 392 | return type; |
b4c522fa IB |
393 | } |
394 | ||
c9634470 IB |
395 | /* Checks whether TYPE is a vendor-specific fundamental type. Stores the result |
396 | in IS_FUNDAMENTAL and returns true if the parameter was set. */ | |
397 | ||
398 | bool | |
5905cbdb | 399 | TargetCPP::fundamentalType (const Type *, bool &) |
c9634470 IB |
400 | { |
401 | return false; | |
402 | } | |
403 | ||
5a0aa603 IB |
404 | /* Get the starting offset position for fields of an `extern(C++)` class |
405 | that is derived from the given BASE_CLASS. */ | |
406 | ||
407 | unsigned | |
408 | TargetCPP::derivedClassOffset(ClassDeclaration *base_class) | |
409 | { | |
410 | return base_class->structsize; | |
411 | } | |
412 | ||
d253a6f7 | 413 | /* Return the default `extern (System)' linkage for the target. */ |
b4c522fa IB |
414 | |
415 | LINK | |
416 | Target::systemLinkage (void) | |
417 | { | |
d253a6f7 IB |
418 | unsigned link_system, link_windows; |
419 | ||
420 | if (targetdm.d_has_stdcall_convention (&link_system, &link_windows)) | |
421 | { | |
422 | /* In [attribute/linkage], `System' is the same as `Windows' on Windows | |
423 | platforms, and `C' on other platforms. */ | |
424 | if (link_system) | |
5fee5ec3 | 425 | return LINK::windows; |
d253a6f7 IB |
426 | } |
427 | ||
5fee5ec3 | 428 | return LINK::c; |
b4c522fa | 429 | } |
a1ccbae6 IB |
430 | |
431 | /* Generate a TypeTuple of the equivalent types used to determine if a | |
432 | function argument of the given type can be passed in registers. | |
433 | The results of this are highly platform dependent, and intended | |
434 | primarly for use in implementing va_arg() with RTTI. */ | |
435 | ||
436 | TypeTuple * | |
437 | Target::toArgTypes (Type *) | |
438 | { | |
439 | /* Not implemented, however this is not currently used anywhere. */ | |
440 | return NULL; | |
441 | } | |
c5e94699 IB |
442 | |
443 | /* Determine return style of function, whether in registers or through a | |
444 | hidden pointer to the caller's stack. */ | |
445 | ||
446 | bool | |
447 | Target::isReturnOnStack (TypeFunction *tf, bool) | |
448 | { | |
449 | /* Need the back-end type to determine this, but this is called from the | |
450 | frontend before semantic processing is finished. An accurate value | |
451 | is not currently needed anyway. */ | |
5fee5ec3 | 452 | if (tf->isref ()) |
c5e94699 IB |
453 | return false; |
454 | ||
455 | Type *tn = tf->next->toBasetype (); | |
4b0253b0 IB |
456 | if (tn->size () == SIZE_INVALID) |
457 | return false; | |
c5e94699 | 458 | |
5fee5ec3 | 459 | return (tn->ty == TY::Tstruct || tn->ty == TY::Tsarray); |
c5e94699 IB |
460 | } |
461 | ||
462 | /* Add all target info in HANDLERS to D_TARGET_INFO_TABLE for use by | |
463 | Target::getTargetInfo(). */ | |
464 | ||
465 | void | |
466 | d_add_target_info_handlers (const d_target_info_spec *handlers) | |
467 | { | |
468 | gcc_assert (handlers != NULL); | |
469 | ||
470 | if (d_target_info_table.is_empty ()) | |
471 | d_target_info_table.create (8); | |
472 | ||
473 | for (size_t i = 0; handlers[i].name != NULL; i++) | |
474 | d_target_info_table.safe_push (handlers[i]); | |
475 | } | |
476 | ||
477 | /* Handle a call to `__traits(getTargetInfo, "cppStd")'. */ | |
478 | ||
479 | tree | |
480 | d_handle_target_cpp_std (void) | |
481 | { | |
482 | return build_integer_cst (global.params.cplusplus); | |
483 | } | |
484 | ||
485 | /* Handle a call to `__traits(getTargetInfo, "cppRuntimeLibrary")'. */ | |
486 | ||
487 | tree | |
488 | d_handle_target_cpp_runtime_library (void) | |
489 | { | |
490 | /* The driver only ever optionally links to libstdc++. */ | |
491 | const char *libstdcxx = "libstdc++"; | |
492 | return build_string_literal (strlen (libstdcxx) + 1, libstdcxx); | |
493 | } | |
494 | ||
d81bc495 IB |
495 | /* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ |
496 | ||
497 | tree | |
498 | d_handle_target_object_format (void) | |
499 | { | |
500 | const char *objfmt; | |
501 | ||
502 | #ifdef OBJECT_FORMAT_ELF | |
503 | objfmt = "elf"; | |
504 | #else | |
505 | if (TARGET_COFF || TARGET_PECOFF) | |
506 | objfmt = "coff"; | |
507 | else | |
508 | objfmt = ""; | |
509 | #endif | |
510 | ||
511 | return build_string_literal (strlen (objfmt) + 1, objfmt); | |
512 | } | |
513 | ||
c5e94699 IB |
514 | /* Look up the target info KEY in the available getTargetInfo tables, and return |
515 | the result as an Expression, or NULL if KEY is not found. When the key must | |
516 | always exist, but is not supported, an empty string expression is returned. | |
517 | LOC is the location to use for the returned expression. */ | |
518 | ||
519 | Expression * | |
520 | Target::getTargetInfo (const char *key, const Loc &loc) | |
521 | { | |
522 | unsigned ix; | |
523 | d_target_info_spec *spec; | |
524 | ||
525 | FOR_EACH_VEC_ELT (d_target_info_table, ix, spec) | |
526 | { | |
527 | tree result; | |
528 | ||
529 | if (strcmp (key, spec->name) != 0) | |
d81bc495 | 530 | continue; |
c5e94699 IB |
531 | |
532 | /* Get the requested information, or empty string if unhandled. */ | |
533 | if (spec->handler) | |
d81bc495 IB |
534 | { |
535 | result = (spec->handler) (); | |
536 | /* Handler didn't return a result, meaning it really does not support | |
537 | the key in the current target configuration. Check whether there | |
538 | are any other handlers which may recognize the key. */ | |
539 | if (result == NULL_TREE) | |
540 | continue; | |
541 | } | |
c5e94699 | 542 | else |
d81bc495 | 543 | result = build_string_literal (1, ""); |
c5e94699 IB |
544 | |
545 | gcc_assert (result); | |
546 | return d_eval_constant_expression (loc, result); | |
547 | } | |
548 | ||
549 | return NULL; | |
550 | } | |
5a0aa603 | 551 | |
5fee5ec3 IB |
552 | /* Returns true if the callee invokes destructors for arguments. */ |
553 | ||
554 | bool | |
555 | Target::isCalleeDestroyingArgs (TypeFunction *tf) | |
556 | { | |
557 | return tf->linkage == LINK::d; | |
558 | } | |
559 | ||
560 | /* Returns true if the implementation for object monitors is always defined | |
561 | in the D runtime library (rt/monitor_.d). */ | |
5a0aa603 IB |
562 | |
563 | bool | |
564 | Target::libraryObjectMonitors (FuncDeclaration *, Statement *) | |
565 | { | |
566 | return true; | |
567 | } | |
5fee5ec3 | 568 | |
d7569187 IB |
569 | /* Returns true if the target supports `pragma(linkerDirective)'. */ |
570 | ||
571 | bool | |
572 | Target::supportsLinkerDirective (void) const | |
573 | { | |
574 | return false; | |
575 | } | |
576 | ||
5fee5ec3 IB |
577 | /* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to |
578 | be passed by reference or by valie. This is used only when compiling with | |
579 | `-fpreview=in' enabled. */ | |
580 | ||
581 | bool | |
582 | Target::preferPassByRef (Type *param_type) | |
583 | { | |
584 | if (param_type->size () == SIZE_INVALID) | |
585 | return false; | |
586 | ||
587 | tree type = build_ctype (param_type); | |
588 | ||
589 | /* Prefer a `ref' if the type is an aggregate, and its size is greater than | |
590 | its alignment. */ | |
591 | if (AGGREGATE_TYPE_P (type) | |
592 | && (!valid_constant_size_p (TYPE_SIZE_UNIT (type)) | |
593 | || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0)) | |
594 | return true; | |
595 | ||
596 | /* If the back-end is always going to pass this by invisible reference. */ | |
597 | if (pass_by_reference (NULL, function_arg_info (type, true))) | |
598 | return true; | |
599 | ||
600 | /* If returning the parameter means the caller will do RVO. */ | |
601 | if (targetm.calls.return_in_memory (type, NULL_TREE)) | |
602 | return true; | |
603 | ||
604 | return false; | |
605 | } |