]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/d-target.cc
d: Fix ICE: Segmentation fault in build_function_type at gcc/tree.c:8539
[thirdparty/gcc.git] / gcc / d / d-target.cc
CommitLineData
b4c522fa 1/* d-target.cc -- Target interface for the D front end.
a5544970 2 Copyright (C) 2013-2019 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"
33#include "stor-layout.h"
34#include "tm.h"
35#include "tm_p.h"
36#include "target.h"
37
38#include "d-tree.h"
39#include "d-target.h"
40
41/* Implements the Target interface defined by the front end.
42 Used for retrieving target-specific information. */
43
44/* Type size information used by frontend. */
45int Target::ptrsize;
46int Target::c_longsize;
47int Target::realsize;
48int Target::realpad;
49int Target::realalignsize;
50bool Target::reverseCppOverloads;
51bool Target::cppExceptions;
52int Target::classinfosize;
53unsigned long long Target::maxStaticDataSize;
54
55/* Floating-point constants for for .max, .min, and other properties. */
56template <typename T> real_t Target::FPTypeProperties<T>::max;
57template <typename T> real_t Target::FPTypeProperties<T>::min_normal;
58template <typename T> real_t Target::FPTypeProperties<T>::nan;
59template <typename T> real_t Target::FPTypeProperties<T>::snan;
60template <typename T> real_t Target::FPTypeProperties<T>::infinity;
61template <typename T> real_t Target::FPTypeProperties<T>::epsilon;
62template <typename T> d_int64 Target::FPTypeProperties<T>::dig;
63template <typename T> d_int64 Target::FPTypeProperties<T>::mant_dig;
64template <typename T> d_int64 Target::FPTypeProperties<T>::max_exp;
65template <typename T> d_int64 Target::FPTypeProperties<T>::min_exp;
66template <typename T> d_int64 Target::FPTypeProperties<T>::max_10_exp;
67template <typename T> d_int64 Target::FPTypeProperties<T>::min_10_exp;
68
69
70/* Initialize the floating-point constants for TYPE. */
71
72template <typename T>
73static void
74define_float_constants (tree type)
75{
76 const double log10_2 = 0.30102999566398119521;
77 char buf[128];
78
79 /* Get back-end real mode format. */
80 const machine_mode mode = TYPE_MODE (type);
81 const real_format *fmt = REAL_MODE_FORMAT (mode);
82
83 /* The largest representable value that's not infinity. */
84 get_max_float (fmt, buf, sizeof (buf));
85 real_from_string (&T::max.rv (), buf);
86
87 /* The smallest representable normalized value that's not 0. */
88 snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - 1);
89 real_from_string (&T::min_normal.rv (), buf);
90
91 /* Floating-point NaN. */
92 real_nan (&T::nan.rv (), "", 1, mode);
93
94 /* Signalling floating-point NaN. */
95 real_nan (&T::snan.rv (), "", 0, mode);
96
97 /* Floating-point +Infinity if the target supports infinities. */
98 real_inf (&T::infinity.rv ());
99
100 /* The smallest increment to the value 1. */
101 if (fmt->pnan < fmt->p)
102 snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - fmt->p);
103 else
104 snprintf (buf, sizeof (buf), "0x1p%d", 1 - fmt->p);
105 real_from_string (&T::epsilon.rv (), buf);
106
107 /* The number of decimal digits of precision. */
108 T::dig = (fmt->p - 1) * log10_2;
109
110 /* The number of bits in mantissa. */
111 T::mant_dig = fmt->p;
112
113 /* The maximum int value such that 2** (value-1) is representable. */
114 T::max_exp = fmt->emax;
115
116 /* The minimum int value such that 2** (value-1) is representable as a
117 normalized value. */
118 T::min_exp = fmt->emin;
119
120 /* The maximum int value such that 10**value is representable. */
121 T::max_10_exp = fmt->emax * log10_2;
122
123 /* The minimum int value such that 10**value is representable as a
124 normalized value. */
125 T::min_10_exp = (fmt->emin - 1) * log10_2;
126}
127
128/* Initialize all variables of the Target structure. */
129
130void
131Target::_init (void)
132{
133 /* Map D frontend type and sizes to GCC back-end types. */
134 Target::ptrsize = (POINTER_SIZE / BITS_PER_UNIT);
135 Target::realsize = int_size_in_bytes (long_double_type_node);
136 Target::realpad = (Target::realsize -
137 (TYPE_PRECISION (long_double_type_node) / BITS_PER_UNIT));
138 Target::realalignsize = TYPE_ALIGN_UNIT (long_double_type_node);
139
140 /* Size of run-time TypeInfo object. */
141 Target::classinfosize = 19 * Target::ptrsize;
142
b0a55e66
IB
143 /* Much of the dmd front-end uses ints for sizes and offsets, and cannot
144 handle any larger data type without some pervasive rework. */
145 Target::maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (integer_type_node));
b4c522fa
IB
146
147 /* Define what type to use for size_t, ptrdiff_t. */
148 if (POINTER_SIZE == 64)
149 {
150 global.params.isLP64 = true;
151 Tsize_t = Tuns64;
152 Tptrdiff_t = Tint64;
153 }
154 else
155 {
156 Tsize_t = Tuns32;
157 Tptrdiff_t = Tint32;
158 }
159
160 Type::tsize_t = Type::basic[Tsize_t];
161 Type::tptrdiff_t = Type::basic[Tptrdiff_t];
162 Type::thash_t = Type::tsize_t;
163
164 /* Set-up target C ABI. */
165 Target::c_longsize = int_size_in_bytes (long_integer_type_node);
166
167 /* Set-up target C++ ABI. */
168 Target::reverseCppOverloads = false;
169 Target::cppExceptions = true;
170
171 /* Initialize all compile-time properties for floating-point types.
172 Should ensure that our real_t type is able to represent real_value. */
173 gcc_assert (sizeof (real_t) >= sizeof (real_value));
174
175 define_float_constants <Target::FloatProperties> (float_type_node);
176 define_float_constants <Target::DoubleProperties> (double_type_node);
177 define_float_constants <Target::RealProperties> (long_double_type_node);
178
179 /* Commonly used floating-point constants. */
180 const machine_mode mode = TYPE_MODE (long_double_type_node);
181 real_convert (&CTFloat::zero.rv (), mode, &dconst0);
182 real_convert (&CTFloat::one.rv (), mode, &dconst1);
183 real_convert (&CTFloat::minusone.rv (), mode, &dconstm1);
184 real_convert (&CTFloat::half.rv (), mode, &dconsthalf);
185}
186
187/* Return GCC memory alignment size for type TYPE. */
188
189unsigned
190Target::alignsize (Type *type)
191{
192 gcc_assert (type->isTypeBasic ());
d7815fc4 193 return min_align_of_type (build_ctype (type));
b4c522fa
IB
194}
195
196/* Return GCC field alignment size for type TYPE. */
197
198unsigned
199Target::fieldalign (Type *type)
200{
201 /* Work out the correct alignment for the field decl. */
202 unsigned int align = type->alignsize () * BITS_PER_UNIT;
203
204#ifdef BIGGEST_FIELD_ALIGNMENT
205 align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
206#endif
207
208#ifdef ADJUST_FIELD_ALIGN
209 if (type->isTypeBasic ())
210 align = ADJUST_FIELD_ALIGN (NULL_TREE, build_ctype (type), align);
211#endif
212
213 /* Also controlled by -fpack-struct= */
214 if (maximum_field_alignment)
215 align = MIN (align, maximum_field_alignment);
216
217 return align / BITS_PER_UNIT;
218}
219
220/* Return size of OS critical section.
221 Can't use the sizeof () calls directly since cross compiling is supported
222 and would end up using the host sizes rather than the target sizes. */
223
224unsigned
225Target::critsecsize (void)
226{
227 return targetdm.d_critsec_size ();
228}
229
230/* Returns a Type for the va_list type of the target. */
231
232Type *
233Target::va_listType (void)
234{
235 return Type::tvalist;
236}
237
238/* Checks whether the target supports a vector type with total size SZ
239 (in bytes) and element type TYPE. */
240
241int
242Target::isVectorTypeSupported (int sz, Type *type)
243{
244 /* Size must be greater than zero, and a power of two. */
245 if (sz <= 0 || sz & (sz - 1))
246 return 2;
247
248 /* __vector(void[]) is treated same as __vector(ubyte[]) */
249 if (type == Type::tvoid)
250 type = Type::tuns8;
251
252 /* No support for non-trivial types. */
253 if (!type->isTypeBasic ())
254 return 3;
255
256 /* If there is no hardware support, check if we can safely emulate it. */
257 tree ctype = build_ctype (type);
258 machine_mode mode = TYPE_MODE (ctype);
259
260 if (!targetm.vector_mode_supported_p (mode)
261 && !targetm.scalar_mode_supported_p (as_a <scalar_mode> (mode)))
262 return 3;
263
264 return 0;
265}
266
267/* Checks whether the target supports operation OP for vectors of type TYPE.
268 For binary ops T2 is the type of the right-hand operand.
269 Returns true if the operation is supported or type is not a vector. */
270
271bool
272Target::isVectorOpSupported (Type *type, TOK op, Type *)
273{
274 if (type->ty != Tvector)
275 return true;
276
277 /* Don't support if type is non-scalar, such as __vector(void[]). */
278 if (!type->isscalar ())
279 return false;
280
281 /* Don't support if expression cannot be represented. */
282 switch (op)
283 {
284 case TOKpow:
285 case TOKpowass:
286 /* pow() is lowered as a function call. */
287 return false;
288
289 case TOKmod:
290 case TOKmodass:
291 /* fmod() is lowered as a function call. */
292 if (type->isfloating ())
293 return false;
294 break;
295
296 case TOKandand:
297 case TOKoror:
298 /* Logical operators must have a result type of bool. */
299 return false;
300
301 case TOKue:
302 case TOKlg:
303 case TOKule:
304 case TOKul:
305 case TOKuge:
306 case TOKug:
307 case TOKle:
308 case TOKlt:
309 case TOKge:
310 case TOKgt:
311 case TOKleg:
312 case TOKunord:
313 case TOKequal:
314 case TOKnotequal:
315 case TOKidentity:
316 case TOKnotidentity:
317 /* Comparison operators must have a result type of bool. */
318 return false;
319
320 default:
321 break;
322 }
323
324 return true;
325}
326
327/* Return the symbol mangling of S for C++ linkage. */
328
329const char *
330Target::toCppMangle (Dsymbol *s)
331{
332 return toCppMangleItanium (s);
333}
334
335/* Return the symbol mangling of CD for C++ linkage. */
336
337const char *
338Target::cppTypeInfoMangle (ClassDeclaration *cd)
339{
340 return cppTypeInfoMangleItanium (cd);
341}
342
343/* For a vendor-specific type, return a string containing the C++ mangling.
344 In all other cases, return NULL. */
345
346const char *
347Target::cppTypeMangle (Type *type)
348{
349 if (type->isTypeBasic () || type->ty == Tvector || type->ty == Tstruct)
350 {
351 tree ctype = build_ctype (type);
352 return targetm.mangle_type (ctype);
353 }
354
355 return NULL;
356}
357
358/* Return the type that will really be used for passing the given parameter
359 ARG to an extern(C++) function. */
360
361Type *
362Target::cppParameterType (Parameter *arg)
363{
364 Type *t = arg->type->merge2 ();
365 if (arg->storageClass & (STCout | STCref))
366 t = t->referenceTo ();
367 else if (arg->storageClass & STClazy)
368 {
369 /* Mangle as delegate. */
370 Type *td = TypeFunction::create (NULL, t, 0, LINKd);
371 td = TypeDelegate::create (td);
372 t = t->merge2 ();
373 }
374
375 /* Could be a va_list, which we mangle as a pointer. */
376 if (t->ty == Tsarray && Type::tvalist->ty == Tsarray)
377 {
378 Type *tb = t->toBasetype ()->mutableOf ();
379 if (tb == Type::tvalist)
380 {
381 tb = t->nextOf ()->pointerTo ();
382 t = tb->castMod (t->mod);
383 }
384 }
385
386 return t;
387}
388
c9634470
IB
389/* Checks whether TYPE is a vendor-specific fundamental type. Stores the result
390 in IS_FUNDAMENTAL and returns true if the parameter was set. */
391
392bool
393Target::cppFundamentalType (const Type *, bool &)
394{
395 return false;
396}
397
b4c522fa
IB
398/* Return the default system linkage for the target. */
399
400LINK
401Target::systemLinkage (void)
402{
403 return LINKc;
404}