]>
Commit | Line | Data |
---|---|---|
b4c522fa | 1 | /* d-target.cc -- Target interface for the D front end. |
7adcbafe | 2 | Copyright (C) 2013-2022 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. */ | |
5905cbdb IB |
161 | this->c.longsize = int_size_in_bytes (long_integer_type_node); |
162 | this->c.long_doublesize = int_size_in_bytes (long_double_type_node); | |
5fee5ec3 | 163 | this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT); |
5a0aa603 | 164 | |
b4c522fa | 165 | /* Set-up target C++ ABI. */ |
5905cbdb IB |
166 | this->cpp.reverseOverloads = false; |
167 | this->cpp.exceptions = true; | |
168 | this->cpp.twoDtorInVtable = true; | |
169 | ||
170 | /* Set-up target Objective-C ABI. */ | |
171 | this->objc.supported = false; | |
b4c522fa | 172 | |
5fee5ec3 IB |
173 | /* Set-up environmental settings. */ |
174 | this->obj_ext = "o"; | |
175 | this->lib_ext = "a"; | |
176 | this->dll_ext = "so"; | |
177 | this->run_noext = true; | |
178 | ||
b4c522fa IB |
179 | /* Initialize all compile-time properties for floating-point types. |
180 | Should ensure that our real_t type is able to represent real_value. */ | |
181 | gcc_assert (sizeof (real_t) >= sizeof (real_value)); | |
182 | ||
5905cbdb IB |
183 | define_float_constants (this->FloatProperties, float_type_node); |
184 | define_float_constants (this->DoubleProperties, double_type_node); | |
185 | define_float_constants (this->RealProperties, long_double_type_node); | |
b4c522fa IB |
186 | |
187 | /* Commonly used floating-point constants. */ | |
188 | const machine_mode mode = TYPE_MODE (long_double_type_node); | |
189 | real_convert (&CTFloat::zero.rv (), mode, &dconst0); | |
190 | real_convert (&CTFloat::one.rv (), mode, &dconst1); | |
191 | real_convert (&CTFloat::minusone.rv (), mode, &dconstm1); | |
192 | real_convert (&CTFloat::half.rv (), mode, &dconsthalf); | |
c5e94699 IB |
193 | |
194 | /* Initialize target info tables, the keys required by the language are added | |
195 | last, so that the OS and CPU handlers can override. */ | |
3785d2b2 | 196 | targetdm.d_register_cpu_target_info (); |
527bc018 | 197 | targetdm.d_register_os_target_info (); |
c5e94699 | 198 | d_add_target_info_handlers (d_language_target_info); |
b4c522fa IB |
199 | } |
200 | ||
201 | /* Return GCC memory alignment size for type TYPE. */ | |
202 | ||
203 | unsigned | |
204 | Target::alignsize (Type *type) | |
205 | { | |
206 | gcc_assert (type->isTypeBasic ()); | |
d7815fc4 | 207 | return min_align_of_type (build_ctype (type)); |
b4c522fa IB |
208 | } |
209 | ||
210 | /* Return GCC field alignment size for type TYPE. */ | |
211 | ||
212 | unsigned | |
213 | Target::fieldalign (Type *type) | |
214 | { | |
215 | /* Work out the correct alignment for the field decl. */ | |
216 | unsigned int align = type->alignsize () * BITS_PER_UNIT; | |
217 | ||
218 | #ifdef BIGGEST_FIELD_ALIGNMENT | |
219 | align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT); | |
220 | #endif | |
221 | ||
222 | #ifdef ADJUST_FIELD_ALIGN | |
223 | if (type->isTypeBasic ()) | |
224 | align = ADJUST_FIELD_ALIGN (NULL_TREE, build_ctype (type), align); | |
225 | #endif | |
226 | ||
227 | /* Also controlled by -fpack-struct= */ | |
228 | if (maximum_field_alignment) | |
229 | align = MIN (align, maximum_field_alignment); | |
230 | ||
231 | return align / BITS_PER_UNIT; | |
232 | } | |
233 | ||
b4c522fa IB |
234 | /* Returns a Type for the va_list type of the target. */ |
235 | ||
236 | Type * | |
5905cbdb | 237 | Target::va_listType (const Loc &, Scope *) |
b4c522fa | 238 | { |
5905cbdb IB |
239 | if (this->tvalist) |
240 | return this->tvalist; | |
241 | ||
242 | /* Build the "standard" abi va_list. */ | |
243 | this->tvalist = build_frontend_type (va_list_type_node); | |
244 | if (!this->tvalist) | |
245 | sorry ("cannot represent built-in %<va_list%> type in D"); | |
246 | ||
247 | /* Map the va_list type to the D frontend Type. This is to prevent both | |
248 | errors in gimplification or an ICE in targetm.canonical_va_list_type. */ | |
249 | this->tvalist->ctype = va_list_type_node; | |
250 | TYPE_LANG_SPECIFIC (va_list_type_node) = build_lang_type (this->tvalist); | |
251 | ||
252 | return this->tvalist; | |
b4c522fa IB |
253 | } |
254 | ||
255 | /* Checks whether the target supports a vector type with total size SZ | |
256 | (in bytes) and element type TYPE. */ | |
257 | ||
258 | int | |
259 | Target::isVectorTypeSupported (int sz, Type *type) | |
260 | { | |
261 | /* Size must be greater than zero, and a power of two. */ | |
262 | if (sz <= 0 || sz & (sz - 1)) | |
19f6b41a | 263 | return 3; |
b4c522fa IB |
264 | |
265 | /* __vector(void[]) is treated same as __vector(ubyte[]) */ | |
266 | if (type == Type::tvoid) | |
267 | type = Type::tuns8; | |
268 | ||
f0a3bab4 | 269 | /* No support for non-trivial types, complex types, or booleans. */ |
5fee5ec3 | 270 | if (!type->isTypeBasic () || type->iscomplex () || type->ty == TY::Tbool) |
19f6b41a | 271 | return 2; |
b4c522fa | 272 | |
f0a3bab4 IB |
273 | /* In [simd/vector extensions], which vector types are supported depends on |
274 | the target. The implementation is expected to only support the vector | |
275 | types that are implemented in the target's hardware. */ | |
276 | unsigned HOST_WIDE_INT nunits = sz / type->size (); | |
277 | tree ctype = build_vector_type (build_ctype (type), nunits); | |
b4c522fa | 278 | |
f0a3bab4 | 279 | if (!targetm.vector_mode_supported_p (TYPE_MODE (ctype))) |
19f6b41a | 280 | return 2; |
b4c522fa IB |
281 | |
282 | return 0; | |
283 | } | |
284 | ||
285 | /* Checks whether the target supports operation OP for vectors of type TYPE. | |
286 | For binary ops T2 is the type of the right-hand operand. | |
287 | Returns true if the operation is supported or type is not a vector. */ | |
288 | ||
289 | bool | |
9c7d5e88 | 290 | Target::isVectorOpSupported (Type *type, EXP op, Type *) |
b4c522fa | 291 | { |
5fee5ec3 | 292 | if (type->ty != TY::Tvector) |
b4c522fa IB |
293 | return true; |
294 | ||
295 | /* Don't support if type is non-scalar, such as __vector(void[]). */ | |
296 | if (!type->isscalar ()) | |
297 | return false; | |
298 | ||
299 | /* Don't support if expression cannot be represented. */ | |
300 | switch (op) | |
301 | { | |
9c7d5e88 IB |
302 | case EXP::pow: |
303 | case EXP::powAssign: | |
b4c522fa IB |
304 | /* pow() is lowered as a function call. */ |
305 | return false; | |
306 | ||
9c7d5e88 IB |
307 | case EXP::mod: |
308 | case EXP::modAssign: | |
b4c522fa IB |
309 | /* fmod() is lowered as a function call. */ |
310 | if (type->isfloating ()) | |
311 | return false; | |
312 | break; | |
313 | ||
9c7d5e88 IB |
314 | case EXP::andAnd: |
315 | case EXP::orOr: | |
b4c522fa IB |
316 | /* Logical operators must have a result type of bool. */ |
317 | return false; | |
318 | ||
9c7d5e88 IB |
319 | case EXP::lessOrEqual: |
320 | case EXP::lessThan: | |
321 | case EXP::greaterOrEqual: | |
322 | case EXP::greaterThan: | |
323 | case EXP::equal: | |
324 | case EXP::notEqual: | |
325 | case EXP::identity: | |
326 | case EXP::notIdentity: | |
b4c522fa IB |
327 | /* Comparison operators must have a result type of bool. */ |
328 | return false; | |
329 | ||
330 | default: | |
331 | break; | |
332 | } | |
333 | ||
334 | return true; | |
335 | } | |
336 | ||
337 | /* Return the symbol mangling of S for C++ linkage. */ | |
338 | ||
339 | const char * | |
5905cbdb | 340 | TargetCPP::toMangle (Dsymbol *s) |
b4c522fa IB |
341 | { |
342 | return toCppMangleItanium (s); | |
343 | } | |
344 | ||
345 | /* Return the symbol mangling of CD for C++ linkage. */ | |
346 | ||
347 | const char * | |
5905cbdb | 348 | TargetCPP::typeInfoMangle (ClassDeclaration *cd) |
b4c522fa IB |
349 | { |
350 | return cppTypeInfoMangleItanium (cd); | |
351 | } | |
352 | ||
5d4b824f IB |
353 | /* Get mangle name of a this-adjusting thunk to the function declaration FD |
354 | at call offset OFFSET for C++ linkage. */ | |
355 | ||
356 | const char * | |
357 | TargetCPP::thunkMangle (FuncDeclaration *fd, int offset) | |
358 | { | |
359 | return cppThunkMangleItanium (fd, offset); | |
360 | } | |
361 | ||
b4c522fa IB |
362 | /* For a vendor-specific type, return a string containing the C++ mangling. |
363 | In all other cases, return NULL. */ | |
364 | ||
365 | const char * | |
5905cbdb | 366 | TargetCPP::typeMangle (Type *type) |
b4c522fa | 367 | { |
5fee5ec3 IB |
368 | if (type->isTypeBasic () || type->ty == TY::Tvector |
369 | || type->ty == TY::Tstruct) | |
b4c522fa IB |
370 | { |
371 | tree ctype = build_ctype (type); | |
372 | return targetm.mangle_type (ctype); | |
373 | } | |
374 | ||
375 | return NULL; | |
376 | } | |
377 | ||
378 | /* Return the type that will really be used for passing the given parameter | |
379 | ARG to an extern(C++) function. */ | |
380 | ||
381 | Type * | |
5905cbdb | 382 | TargetCPP::parameterType (Parameter *arg) |
b4c522fa IB |
383 | { |
384 | Type *t = arg->type->merge2 (); | |
385 | if (arg->storageClass & (STCout | STCref)) | |
386 | t = t->referenceTo (); | |
387 | else if (arg->storageClass & STClazy) | |
388 | { | |
389 | /* Mangle as delegate. */ | |
5fee5ec3 IB |
390 | TypeFunction *tf = TypeFunction::create (NULL, t, VARARGnone, LINK::d); |
391 | TypeDelegate *td = TypeDelegate::create (tf); | |
392 | t = td->merge2 (); | |
b4c522fa IB |
393 | } |
394 | ||
395 | /* Could be a va_list, which we mangle as a pointer. */ | |
5905cbdb | 396 | Type *tvalist = target.va_listType (Loc (), NULL); |
5fee5ec3 | 397 | if (t->ty == TY::Tsarray && tvalist->ty == TY::Tsarray) |
b4c522fa IB |
398 | { |
399 | Type *tb = t->toBasetype ()->mutableOf (); | |
5905cbdb | 400 | if (tb == tvalist) |
b4c522fa IB |
401 | { |
402 | tb = t->nextOf ()->pointerTo (); | |
403 | t = tb->castMod (t->mod); | |
404 | } | |
405 | } | |
406 | ||
407 | return t; | |
408 | } | |
409 | ||
c9634470 IB |
410 | /* Checks whether TYPE is a vendor-specific fundamental type. Stores the result |
411 | in IS_FUNDAMENTAL and returns true if the parameter was set. */ | |
412 | ||
413 | bool | |
5905cbdb | 414 | TargetCPP::fundamentalType (const Type *, bool &) |
c9634470 IB |
415 | { |
416 | return false; | |
417 | } | |
418 | ||
5a0aa603 IB |
419 | /* Get the starting offset position for fields of an `extern(C++)` class |
420 | that is derived from the given BASE_CLASS. */ | |
421 | ||
422 | unsigned | |
423 | TargetCPP::derivedClassOffset(ClassDeclaration *base_class) | |
424 | { | |
425 | return base_class->structsize; | |
426 | } | |
427 | ||
d253a6f7 | 428 | /* Return the default `extern (System)' linkage for the target. */ |
b4c522fa IB |
429 | |
430 | LINK | |
431 | Target::systemLinkage (void) | |
432 | { | |
d253a6f7 IB |
433 | unsigned link_system, link_windows; |
434 | ||
435 | if (targetdm.d_has_stdcall_convention (&link_system, &link_windows)) | |
436 | { | |
437 | /* In [attribute/linkage], `System' is the same as `Windows' on Windows | |
438 | platforms, and `C' on other platforms. */ | |
439 | if (link_system) | |
5fee5ec3 | 440 | return LINK::windows; |
d253a6f7 IB |
441 | } |
442 | ||
5fee5ec3 | 443 | return LINK::c; |
b4c522fa | 444 | } |
a1ccbae6 IB |
445 | |
446 | /* Generate a TypeTuple of the equivalent types used to determine if a | |
447 | function argument of the given type can be passed in registers. | |
448 | The results of this are highly platform dependent, and intended | |
449 | primarly for use in implementing va_arg() with RTTI. */ | |
450 | ||
451 | TypeTuple * | |
452 | Target::toArgTypes (Type *) | |
453 | { | |
454 | /* Not implemented, however this is not currently used anywhere. */ | |
455 | return NULL; | |
456 | } | |
c5e94699 IB |
457 | |
458 | /* Determine return style of function, whether in registers or through a | |
459 | hidden pointer to the caller's stack. */ | |
460 | ||
461 | bool | |
462 | Target::isReturnOnStack (TypeFunction *tf, bool) | |
463 | { | |
464 | /* Need the back-end type to determine this, but this is called from the | |
465 | frontend before semantic processing is finished. An accurate value | |
466 | is not currently needed anyway. */ | |
5fee5ec3 | 467 | if (tf->isref ()) |
c5e94699 IB |
468 | return false; |
469 | ||
470 | Type *tn = tf->next->toBasetype (); | |
471 | ||
5fee5ec3 | 472 | return (tn->ty == TY::Tstruct || tn->ty == TY::Tsarray); |
c5e94699 IB |
473 | } |
474 | ||
475 | /* Add all target info in HANDLERS to D_TARGET_INFO_TABLE for use by | |
476 | Target::getTargetInfo(). */ | |
477 | ||
478 | void | |
479 | d_add_target_info_handlers (const d_target_info_spec *handlers) | |
480 | { | |
481 | gcc_assert (handlers != NULL); | |
482 | ||
483 | if (d_target_info_table.is_empty ()) | |
484 | d_target_info_table.create (8); | |
485 | ||
486 | for (size_t i = 0; handlers[i].name != NULL; i++) | |
487 | d_target_info_table.safe_push (handlers[i]); | |
488 | } | |
489 | ||
490 | /* Handle a call to `__traits(getTargetInfo, "cppStd")'. */ | |
491 | ||
492 | tree | |
493 | d_handle_target_cpp_std (void) | |
494 | { | |
495 | return build_integer_cst (global.params.cplusplus); | |
496 | } | |
497 | ||
498 | /* Handle a call to `__traits(getTargetInfo, "cppRuntimeLibrary")'. */ | |
499 | ||
500 | tree | |
501 | d_handle_target_cpp_runtime_library (void) | |
502 | { | |
503 | /* The driver only ever optionally links to libstdc++. */ | |
504 | const char *libstdcxx = "libstdc++"; | |
505 | return build_string_literal (strlen (libstdcxx) + 1, libstdcxx); | |
506 | } | |
507 | ||
d81bc495 IB |
508 | /* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */ |
509 | ||
510 | tree | |
511 | d_handle_target_object_format (void) | |
512 | { | |
513 | const char *objfmt; | |
514 | ||
515 | #ifdef OBJECT_FORMAT_ELF | |
516 | objfmt = "elf"; | |
517 | #else | |
518 | if (TARGET_COFF || TARGET_PECOFF) | |
519 | objfmt = "coff"; | |
520 | else | |
521 | objfmt = ""; | |
522 | #endif | |
523 | ||
524 | return build_string_literal (strlen (objfmt) + 1, objfmt); | |
525 | } | |
526 | ||
c5e94699 IB |
527 | /* Look up the target info KEY in the available getTargetInfo tables, and return |
528 | the result as an Expression, or NULL if KEY is not found. When the key must | |
529 | always exist, but is not supported, an empty string expression is returned. | |
530 | LOC is the location to use for the returned expression. */ | |
531 | ||
532 | Expression * | |
533 | Target::getTargetInfo (const char *key, const Loc &loc) | |
534 | { | |
535 | unsigned ix; | |
536 | d_target_info_spec *spec; | |
537 | ||
538 | FOR_EACH_VEC_ELT (d_target_info_table, ix, spec) | |
539 | { | |
540 | tree result; | |
541 | ||
542 | if (strcmp (key, spec->name) != 0) | |
d81bc495 | 543 | continue; |
c5e94699 IB |
544 | |
545 | /* Get the requested information, or empty string if unhandled. */ | |
546 | if (spec->handler) | |
d81bc495 IB |
547 | { |
548 | result = (spec->handler) (); | |
549 | /* Handler didn't return a result, meaning it really does not support | |
550 | the key in the current target configuration. Check whether there | |
551 | are any other handlers which may recognize the key. */ | |
552 | if (result == NULL_TREE) | |
553 | continue; | |
554 | } | |
c5e94699 | 555 | else |
d81bc495 | 556 | result = build_string_literal (1, ""); |
c5e94699 IB |
557 | |
558 | gcc_assert (result); | |
559 | return d_eval_constant_expression (loc, result); | |
560 | } | |
561 | ||
562 | return NULL; | |
563 | } | |
5a0aa603 | 564 | |
5fee5ec3 IB |
565 | /* Returns true if the callee invokes destructors for arguments. */ |
566 | ||
567 | bool | |
568 | Target::isCalleeDestroyingArgs (TypeFunction *tf) | |
569 | { | |
570 | return tf->linkage == LINK::d; | |
571 | } | |
572 | ||
573 | /* Returns true if the implementation for object monitors is always defined | |
574 | in the D runtime library (rt/monitor_.d). */ | |
5a0aa603 IB |
575 | |
576 | bool | |
577 | Target::libraryObjectMonitors (FuncDeclaration *, Statement *) | |
578 | { | |
579 | return true; | |
580 | } | |
5fee5ec3 IB |
581 | |
582 | /* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to | |
583 | be passed by reference or by valie. This is used only when compiling with | |
584 | `-fpreview=in' enabled. */ | |
585 | ||
586 | bool | |
587 | Target::preferPassByRef (Type *param_type) | |
588 | { | |
589 | if (param_type->size () == SIZE_INVALID) | |
590 | return false; | |
591 | ||
592 | tree type = build_ctype (param_type); | |
593 | ||
594 | /* Prefer a `ref' if the type is an aggregate, and its size is greater than | |
595 | its alignment. */ | |
596 | if (AGGREGATE_TYPE_P (type) | |
597 | && (!valid_constant_size_p (TYPE_SIZE_UNIT (type)) | |
598 | || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0)) | |
599 | return true; | |
600 | ||
601 | /* If the back-end is always going to pass this by invisible reference. */ | |
602 | if (pass_by_reference (NULL, function_arg_info (type, true))) | |
603 | return true; | |
604 | ||
605 | /* If returning the parameter means the caller will do RVO. */ | |
606 | if (targetm.calls.return_in_memory (type, NULL_TREE)) | |
607 | return true; | |
608 | ||
609 | return false; | |
610 | } |