c++: Implement __is_member_function_pointer built-in trait
[official-gcc.git] / gcc / d / d-target.cc
blob4c7a212703e52794460908a02197d39af7835fcb
1 /* d-target.cc -- Target interface for the D front end.
2 Copyright (C) 2013-2023 Free Software Foundation, Inc.
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.
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.
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/>. */
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
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"
30 #include "tree.h"
31 #include "memmodel.h"
32 #include "fold-const.h"
33 #include "diagnostic.h"
34 #include "stor-layout.h"
35 #include "tm.h"
36 #include "tm_p.h"
37 #include "target.h"
38 #include "calls.h"
40 #include "d-tree.h"
41 #include "d-target.h"
43 /* Implements the Target interface defined by the front end.
44 Used for retrieving target-specific information. */
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);
49 static tree d_handle_target_object_format (void);
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[] =
55 /* { name, handler } */
56 { "cppStd", d_handle_target_cpp_std },
57 { "cppRuntimeLibrary", d_handle_target_cpp_runtime_library },
58 { "floatAbi", NULL },
59 { "objectFormat", d_handle_target_object_format },
60 { NULL, NULL },
63 /* Table `__traits(getTargetInfo)' keys. */
64 static vec<d_target_info_spec> d_target_info_table;
67 /* Initialize the floating-point constants for TYPE. */
69 template <typename T>
70 static void
71 define_float_constants (T &f, tree type)
73 const double log10_2 = 0.30102999566398119521;
74 char buf[128];
76 /* Get back-end real mode format. */
77 const machine_mode mode = TYPE_MODE (type);
78 const real_format *fmt = REAL_MODE_FORMAT (mode);
80 /* The largest representable value that's not infinity. */
81 get_max_float (fmt, buf, sizeof (buf), false);
82 real_from_string (&f.max.rv (), buf);
84 /* The smallest representable normalized value that's not 0. */
85 snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - 1);
86 real_from_string (&f.min_normal.rv (), buf);
88 /* Floating-point NaN. */
89 real_nan (&f.nan.rv (), "", 1, mode);
91 /* Floating-point +Infinity if the target supports infinities. */
92 real_inf (&f.infinity.rv ());
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);
99 real_from_string (&f.epsilon.rv (), buf);
101 /* The number of decimal digits of precision. */
102 f.dig = (fmt->p - 1) * log10_2;
104 /* The number of bits in mantissa. */
105 f.mant_dig = fmt->p;
107 /* The maximum int value such that 2** (value-1) is representable. */
108 f.max_exp = fmt->emax;
110 /* The minimum int value such that 2** (value-1) is representable as a
111 normalized value. */
112 f.min_exp = fmt->emin;
114 /* The maximum int value such that 10**value is representable. */
115 f.max_10_exp = fmt->emax * log10_2;
117 /* The minimum int value such that 10**value is representable as a
118 normalized value. */
119 f.min_10_exp = (fmt->emin - 1) * log10_2;
122 /* Initialize all variables of the Target structure. */
124 void
125 Target::_init (const Param &)
127 /* Map D frontend type and sizes to GCC back-end types. */
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);
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. */
136 this->maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (integer_type_node));
138 /* Define what type to use for size_t, ptrdiff_t. */
139 if (this->ptrsize == 8)
141 this->isLP64 = true;
142 Type::tsize_t = Type::basic[(int)TY::Tuns64];
143 Type::tptrdiff_t = Type::basic[(int)TY::Tint64];
145 else if (this->ptrsize == 4)
147 Type::tsize_t = Type::basic[(int)TY::Tuns32];
148 Type::tptrdiff_t = Type::basic[(int)TY::Tint32];
150 else if (this->ptrsize == 2)
152 Type::tsize_t = Type::basic[(int)TY::Tuns16];
153 Type::tptrdiff_t = Type::basic[(int)TY::Tint16];
155 else
156 sorry ("D does not support pointers on this target.");
158 Type::thash_t = Type::tsize_t;
160 /* Set-up target C ABI. */
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);
167 this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT);
169 this->c.bitFieldStyle = targetm.ms_bitfield_layout_p (unknown_type_node)
170 ? TargetC::BitFieldStyle::MS : TargetC::BitFieldStyle::Gcc_Clang;
172 /* Set-up target C++ ABI. */
173 this->cpp.reverseOverloads = false;
174 this->cpp.exceptions = true;
175 this->cpp.twoDtorInVtable = true;
177 /* Set-up target Objective-C ABI. */
178 this->objc.supported = false;
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;
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));
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);
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);
201 /* Initialize target info tables, the keys required by the language are added
202 last, so that the OS and CPU handlers can override. */
203 targetdm.d_register_cpu_target_info ();
204 targetdm.d_register_os_target_info ();
205 d_add_target_info_handlers (d_language_target_info);
208 /* Return GCC memory alignment size for type TYPE. */
210 unsigned
211 Target::alignsize (Type *type)
213 gcc_assert (type->isTypeBasic ());
214 return min_align_of_type (build_ctype (type));
217 /* Return GCC field alignment size for type TYPE. */
219 unsigned
220 Target::fieldalign (Type *type)
222 /* Work out the correct alignment for the field decl. */
223 unsigned int align = type->alignsize () * BITS_PER_UNIT;
225 #ifdef BIGGEST_FIELD_ALIGNMENT
226 align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
227 #endif
229 #ifdef ADJUST_FIELD_ALIGN
230 if (type->isTypeBasic ())
231 align = ADJUST_FIELD_ALIGN (NULL_TREE, build_ctype (type), align);
232 #endif
234 /* Also controlled by -fpack-struct= */
235 if (maximum_field_alignment)
236 align = MIN (align, maximum_field_alignment);
238 return align / BITS_PER_UNIT;
241 /* Returns a Type for the va_list type of the target. */
243 Type *
244 Target::va_listType (const Loc &, Scope *)
246 if (this->tvalist)
247 return this->tvalist;
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");
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);
259 return this->tvalist;
262 /* Checks whether the target supports a vector type with total size SZ
263 (in bytes) and element type TYPE. */
266 Target::isVectorTypeSupported (int sz, Type *type)
268 /* Size must be greater than zero, and a power of two. */
269 if (sz <= 0 || sz & (sz - 1))
270 return 3;
272 /* __vector(void[]) is treated same as __vector(ubyte[]) */
273 if (type == Type::tvoid)
274 type = Type::tuns8;
276 /* No support for non-trivial types, complex types, or booleans. */
277 if (!type->isTypeBasic () || type->iscomplex () || type->ty == TY::Tbool)
278 return 2;
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);
286 if (!targetm.vector_mode_supported_p (TYPE_MODE (ctype)))
287 return 2;
289 return 0;
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. */
296 bool
297 Target::isVectorOpSupported (Type *type, EXP op, Type *)
299 if (type->ty != TY::Tvector)
300 return true;
302 /* Don't support if type is non-scalar, such as __vector(void[]). */
303 if (!type->isscalar ())
304 return false;
306 /* Don't support if expression cannot be represented. */
307 switch (op)
309 case EXP::pow:
310 case EXP::powAssign:
311 /* pow() is lowered as a function call. */
312 return false;
314 case EXP::mod:
315 case EXP::modAssign:
316 /* fmod() is lowered as a function call. */
317 if (type->isfloating ())
318 return false;
319 break;
321 case EXP::andAnd:
322 case EXP::orOr:
323 /* Logical operators must have a result type of bool. */
324 return false;
326 default:
327 break;
330 return true;
333 /* Return the symbol mangling of S for C++ linkage. */
335 const char *
336 TargetCPP::toMangle (Dsymbol *s)
338 return toCppMangleItanium (s);
341 /* Return the symbol mangling of CD for C++ linkage. */
343 const char *
344 TargetCPP::typeInfoMangle (ClassDeclaration *cd)
346 return cppTypeInfoMangleItanium (cd);
349 /* Get mangle name of a this-adjusting thunk to the function declaration FD
350 at call offset OFFSET for C++ linkage. */
352 const char *
353 TargetCPP::thunkMangle (FuncDeclaration *fd, int offset)
355 return cppThunkMangleItanium (fd, offset);
358 /* For a vendor-specific type, return a string containing the C++ mangling.
359 In all other cases, return NULL. */
361 const char *
362 TargetCPP::typeMangle (Type *type)
364 if (type->isTypeBasic () || type->ty == TY::Tvector
365 || type->ty == TY::Tstruct)
367 tree ctype = build_ctype (type);
368 return targetm.mangle_type (ctype);
371 return NULL;
374 /* Return the type that will really be used for passing the given parameter
375 ARG to an extern(C++) function. */
377 Type *
378 TargetCPP::parameterType (Type *type)
380 /* Could be a va_list, which we mangle as a pointer. */
381 Type *tvalist = target.va_listType (Loc (), NULL);
382 if (type->ty == TY::Tsarray && tvalist->ty == TY::Tsarray)
384 Type *tb = type->toBasetype ()->mutableOf ();
385 if (tb == tvalist)
387 tb = type->nextOf ()->pointerTo ();
388 type = tb->castMod (type->mod);
392 return type;
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. */
398 bool
399 TargetCPP::fundamentalType (const Type *, bool &)
401 return false;
404 /* Get the starting offset position for fields of an `extern(C++)` class
405 that is derived from the given BASE_CLASS. */
407 unsigned
408 TargetCPP::derivedClassOffset(ClassDeclaration *base_class)
410 return base_class->structsize;
413 /* Return the default `extern (System)' linkage for the target. */
415 LINK
416 Target::systemLinkage (void)
418 unsigned link_system, link_windows;
420 if (targetdm.d_has_stdcall_convention (&link_system, &link_windows))
422 /* In [attribute/linkage], `System' is the same as `Windows' on Windows
423 platforms, and `C' on other platforms. */
424 if (link_system)
425 return LINK::windows;
428 return LINK::c;
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. */
436 TypeTuple *
437 Target::toArgTypes (Type *)
439 /* Not implemented, however this is not currently used anywhere. */
440 return NULL;
443 /* Determine return style of function, whether in registers or through a
444 hidden pointer to the caller's stack. */
446 bool
447 Target::isReturnOnStack (TypeFunction *tf, bool)
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. */
452 if (tf->isref ())
453 return false;
455 Type *tn = tf->next->toBasetype ();
456 if (tn->size () == SIZE_INVALID)
457 return false;
459 return (tn->ty == TY::Tstruct || tn->ty == TY::Tsarray);
462 /* Add all target info in HANDLERS to D_TARGET_INFO_TABLE for use by
463 Target::getTargetInfo(). */
465 void
466 d_add_target_info_handlers (const d_target_info_spec *handlers)
468 gcc_assert (handlers != NULL);
470 if (d_target_info_table.is_empty ())
471 d_target_info_table.create (8);
473 for (size_t i = 0; handlers[i].name != NULL; i++)
474 d_target_info_table.safe_push (handlers[i]);
477 /* Handle a call to `__traits(getTargetInfo, "cppStd")'. */
479 tree
480 d_handle_target_cpp_std (void)
482 return build_integer_cst (global.params.cplusplus);
485 /* Handle a call to `__traits(getTargetInfo, "cppRuntimeLibrary")'. */
487 tree
488 d_handle_target_cpp_runtime_library (void)
490 /* The driver only ever optionally links to libstdc++. */
491 const char *libstdcxx = "libstdc++";
492 return build_string_literal (strlen (libstdcxx) + 1, libstdcxx);
495 /* Handle a call to `__traits(getTargetInfo, "objectFormat")'. */
497 tree
498 d_handle_target_object_format (void)
500 const char *objfmt;
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
511 return build_string_literal (strlen (objfmt) + 1, objfmt);
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. */
519 Expression *
520 Target::getTargetInfo (const char *key, const Loc &loc)
522 unsigned ix;
523 d_target_info_spec *spec;
525 FOR_EACH_VEC_ELT (d_target_info_table, ix, spec)
527 tree result;
529 if (strcmp (key, spec->name) != 0)
530 continue;
532 /* Get the requested information, or empty string if unhandled. */
533 if (spec->handler)
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;
542 else
543 result = build_string_literal (1, "");
545 gcc_assert (result);
546 return d_eval_constant_expression (loc, result);
549 return NULL;
552 /* Returns true if the callee invokes destructors for arguments. */
554 bool
555 Target::isCalleeDestroyingArgs (TypeFunction *tf)
557 return tf->linkage == LINK::d;
560 /* Returns true if the implementation for object monitors is always defined
561 in the D runtime library (rt/monitor_.d). */
563 bool
564 Target::libraryObjectMonitors (FuncDeclaration *, Statement *)
566 return true;
569 /* Returns true if the target supports `pragma(linkerDirective)'. */
571 bool
572 Target::supportsLinkerDirective (void) const
574 return false;
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. */
581 bool
582 Target::preferPassByRef (Type *param_type)
584 if (param_type->size () == SIZE_INVALID)
585 return false;
587 tree type = build_ctype (param_type);
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;
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;
600 /* If returning the parameter means the caller will do RVO. */
601 if (targetm.calls.return_in_memory (type, NULL_TREE))
602 return true;
604 return false;