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