]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/d-target.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / d / d-target.cc
CommitLineData
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
4GCC is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 3, or (at your option)
7any later version.
8
9GCC is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along 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)'. */
47static tree d_handle_target_cpp_std (void);
48static tree d_handle_target_cpp_runtime_library (void);
d81bc495 49static 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. */
53static 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. */
64static vec<d_target_info_spec> d_target_info_table;
65
b4c522fa
IB
66
67/* Initialize the floating-point constants for TYPE. */
68
69template <typename T>
70static void
5905cbdb 71define_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
124void
5905cbdb 125Target::_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
210unsigned
211Target::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
219unsigned
220Target::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
243Type *
5905cbdb 244Target::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
265int
266Target::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
296bool
9c7d5e88 297Target::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
335const char *
5905cbdb 336TargetCPP::toMangle (Dsymbol *s)
b4c522fa
IB
337{
338 return toCppMangleItanium (s);
339}
340
341/* Return the symbol mangling of CD for C++ linkage. */
342
343const char *
5905cbdb 344TargetCPP::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
352const char *
353TargetCPP::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
361const char *
5905cbdb 362TargetCPP::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
377Type *
d7569187 378TargetCPP::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
398bool
5905cbdb 399TargetCPP::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
407unsigned
408TargetCPP::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
415LINK
416Target::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
436TypeTuple *
437Target::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
446bool
447Target::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
465void
466d_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
479tree
480d_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
487tree
488d_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
497tree
498d_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
519Expression *
520Target::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
554bool
555Target::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
563bool
564Target::libraryObjectMonitors (FuncDeclaration *, Statement *)
565{
566 return true;
567}
5fee5ec3 568
d7569187
IB
569/* Returns true if the target supports `pragma(linkerDirective)'. */
570
571bool
572Target::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
581bool
582Target::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}