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