]> 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.
7adcbafe 2 Copyright (C) 2013-2022 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. */
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
203unsigned
204Target::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
212unsigned
213Target::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
236Type *
5905cbdb 237Target::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
258int
259Target::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
289bool
9c7d5e88 290Target::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
339const char *
5905cbdb 340TargetCPP::toMangle (Dsymbol *s)
b4c522fa
IB
341{
342 return toCppMangleItanium (s);
343}
344
345/* Return the symbol mangling of CD for C++ linkage. */
346
347const char *
5905cbdb 348TargetCPP::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
356const char *
357TargetCPP::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
365const char *
5905cbdb 366TargetCPP::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
381Type *
5905cbdb 382TargetCPP::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
413bool
5905cbdb 414TargetCPP::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
422unsigned
423TargetCPP::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
430LINK
431Target::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
451TypeTuple *
452Target::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
461bool
462Target::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
478void
479d_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
492tree
493d_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
500tree
501d_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
510tree
511d_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
532Expression *
533Target::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
567bool
568Target::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
576bool
577Target::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
586bool
587Target::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}