]>
Commit | Line | Data |
---|---|---|
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 | |
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 "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. */ | |
45 | int Target::ptrsize; | |
46 | int Target::c_longsize; | |
47 | int Target::realsize; | |
48 | int Target::realpad; | |
49 | int Target::realalignsize; | |
50 | bool Target::reverseCppOverloads; | |
51 | bool Target::cppExceptions; | |
52 | int Target::classinfosize; | |
53 | unsigned long long Target::maxStaticDataSize; | |
54 | ||
55 | /* Floating-point constants for for .max, .min, and other properties. */ | |
56 | template <typename T> real_t Target::FPTypeProperties<T>::max; | |
57 | template <typename T> real_t Target::FPTypeProperties<T>::min_normal; | |
58 | template <typename T> real_t Target::FPTypeProperties<T>::nan; | |
59 | template <typename T> real_t Target::FPTypeProperties<T>::snan; | |
60 | template <typename T> real_t Target::FPTypeProperties<T>::infinity; | |
61 | template <typename T> real_t Target::FPTypeProperties<T>::epsilon; | |
62 | template <typename T> d_int64 Target::FPTypeProperties<T>::dig; | |
63 | template <typename T> d_int64 Target::FPTypeProperties<T>::mant_dig; | |
64 | template <typename T> d_int64 Target::FPTypeProperties<T>::max_exp; | |
65 | template <typename T> d_int64 Target::FPTypeProperties<T>::min_exp; | |
66 | template <typename T> d_int64 Target::FPTypeProperties<T>::max_10_exp; | |
67 | template <typename T> d_int64 Target::FPTypeProperties<T>::min_10_exp; | |
68 | ||
69 | ||
70 | /* Initialize the floating-point constants for TYPE. */ | |
71 | ||
72 | template <typename T> | |
73 | static void | |
74 | define_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 | ||
130 | void | |
131 | Target::_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 | ||
189 | unsigned | |
190 | Target::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 | ||
198 | unsigned | |
199 | Target::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 | ||
224 | unsigned | |
225 | Target::critsecsize (void) | |
226 | { | |
227 | return targetdm.d_critsec_size (); | |
228 | } | |
229 | ||
230 | /* Returns a Type for the va_list type of the target. */ | |
231 | ||
232 | Type * | |
233 | Target::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 | ||
241 | int | |
242 | Target::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 | ||
271 | bool | |
272 | Target::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 | ||
329 | const char * | |
330 | Target::toCppMangle (Dsymbol *s) | |
331 | { | |
332 | return toCppMangleItanium (s); | |
333 | } | |
334 | ||
335 | /* Return the symbol mangling of CD for C++ linkage. */ | |
336 | ||
337 | const char * | |
338 | Target::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 | ||
346 | const char * | |
347 | Target::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 | ||
361 | Type * | |
362 | Target::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 | ||
392 | bool | |
393 | Target::cppFundamentalType (const Type *, bool &) | |
394 | { | |
395 | return false; | |
396 | } | |
397 | ||
b4c522fa IB |
398 | /* Return the default system linkage for the target. */ |
399 | ||
400 | LINK | |
401 | Target::systemLinkage (void) | |
402 | { | |
403 | return LINKc; | |
404 | } |