]>
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 | ||
143 | /* Allow data sizes up to half of the address space. */ | |
144 | Target::maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node)); | |
145 | ||
146 | /* Define what type to use for size_t, ptrdiff_t. */ | |
147 | if (POINTER_SIZE == 64) | |
148 | { | |
149 | global.params.isLP64 = true; | |
150 | Tsize_t = Tuns64; | |
151 | Tptrdiff_t = Tint64; | |
152 | } | |
153 | else | |
154 | { | |
155 | Tsize_t = Tuns32; | |
156 | Tptrdiff_t = Tint32; | |
157 | } | |
158 | ||
159 | Type::tsize_t = Type::basic[Tsize_t]; | |
160 | Type::tptrdiff_t = Type::basic[Tptrdiff_t]; | |
161 | Type::thash_t = Type::tsize_t; | |
162 | ||
163 | /* Set-up target C ABI. */ | |
164 | Target::c_longsize = int_size_in_bytes (long_integer_type_node); | |
165 | ||
166 | /* Set-up target C++ ABI. */ | |
167 | Target::reverseCppOverloads = false; | |
168 | Target::cppExceptions = true; | |
169 | ||
170 | /* Initialize all compile-time properties for floating-point types. | |
171 | Should ensure that our real_t type is able to represent real_value. */ | |
172 | gcc_assert (sizeof (real_t) >= sizeof (real_value)); | |
173 | ||
174 | define_float_constants <Target::FloatProperties> (float_type_node); | |
175 | define_float_constants <Target::DoubleProperties> (double_type_node); | |
176 | define_float_constants <Target::RealProperties> (long_double_type_node); | |
177 | ||
178 | /* Commonly used floating-point constants. */ | |
179 | const machine_mode mode = TYPE_MODE (long_double_type_node); | |
180 | real_convert (&CTFloat::zero.rv (), mode, &dconst0); | |
181 | real_convert (&CTFloat::one.rv (), mode, &dconst1); | |
182 | real_convert (&CTFloat::minusone.rv (), mode, &dconstm1); | |
183 | real_convert (&CTFloat::half.rv (), mode, &dconsthalf); | |
184 | } | |
185 | ||
186 | /* Return GCC memory alignment size for type TYPE. */ | |
187 | ||
188 | unsigned | |
189 | Target::alignsize (Type *type) | |
190 | { | |
191 | gcc_assert (type->isTypeBasic ()); | |
d7815fc4 | 192 | return min_align_of_type (build_ctype (type)); |
b4c522fa IB |
193 | } |
194 | ||
195 | /* Return GCC field alignment size for type TYPE. */ | |
196 | ||
197 | unsigned | |
198 | Target::fieldalign (Type *type) | |
199 | { | |
200 | /* Work out the correct alignment for the field decl. */ | |
201 | unsigned int align = type->alignsize () * BITS_PER_UNIT; | |
202 | ||
203 | #ifdef BIGGEST_FIELD_ALIGNMENT | |
204 | align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT); | |
205 | #endif | |
206 | ||
207 | #ifdef ADJUST_FIELD_ALIGN | |
208 | if (type->isTypeBasic ()) | |
209 | align = ADJUST_FIELD_ALIGN (NULL_TREE, build_ctype (type), align); | |
210 | #endif | |
211 | ||
212 | /* Also controlled by -fpack-struct= */ | |
213 | if (maximum_field_alignment) | |
214 | align = MIN (align, maximum_field_alignment); | |
215 | ||
216 | return align / BITS_PER_UNIT; | |
217 | } | |
218 | ||
219 | /* Return size of OS critical section. | |
220 | Can't use the sizeof () calls directly since cross compiling is supported | |
221 | and would end up using the host sizes rather than the target sizes. */ | |
222 | ||
223 | unsigned | |
224 | Target::critsecsize (void) | |
225 | { | |
226 | return targetdm.d_critsec_size (); | |
227 | } | |
228 | ||
229 | /* Returns a Type for the va_list type of the target. */ | |
230 | ||
231 | Type * | |
232 | Target::va_listType (void) | |
233 | { | |
234 | return Type::tvalist; | |
235 | } | |
236 | ||
237 | /* Checks whether the target supports a vector type with total size SZ | |
238 | (in bytes) and element type TYPE. */ | |
239 | ||
240 | int | |
241 | Target::isVectorTypeSupported (int sz, Type *type) | |
242 | { | |
243 | /* Size must be greater than zero, and a power of two. */ | |
244 | if (sz <= 0 || sz & (sz - 1)) | |
245 | return 2; | |
246 | ||
247 | /* __vector(void[]) is treated same as __vector(ubyte[]) */ | |
248 | if (type == Type::tvoid) | |
249 | type = Type::tuns8; | |
250 | ||
251 | /* No support for non-trivial types. */ | |
252 | if (!type->isTypeBasic ()) | |
253 | return 3; | |
254 | ||
255 | /* If there is no hardware support, check if we can safely emulate it. */ | |
256 | tree ctype = build_ctype (type); | |
257 | machine_mode mode = TYPE_MODE (ctype); | |
258 | ||
259 | if (!targetm.vector_mode_supported_p (mode) | |
260 | && !targetm.scalar_mode_supported_p (as_a <scalar_mode> (mode))) | |
261 | return 3; | |
262 | ||
263 | return 0; | |
264 | } | |
265 | ||
266 | /* Checks whether the target supports operation OP for vectors of type TYPE. | |
267 | For binary ops T2 is the type of the right-hand operand. | |
268 | Returns true if the operation is supported or type is not a vector. */ | |
269 | ||
270 | bool | |
271 | Target::isVectorOpSupported (Type *type, TOK op, Type *) | |
272 | { | |
273 | if (type->ty != Tvector) | |
274 | return true; | |
275 | ||
276 | /* Don't support if type is non-scalar, such as __vector(void[]). */ | |
277 | if (!type->isscalar ()) | |
278 | return false; | |
279 | ||
280 | /* Don't support if expression cannot be represented. */ | |
281 | switch (op) | |
282 | { | |
283 | case TOKpow: | |
284 | case TOKpowass: | |
285 | /* pow() is lowered as a function call. */ | |
286 | return false; | |
287 | ||
288 | case TOKmod: | |
289 | case TOKmodass: | |
290 | /* fmod() is lowered as a function call. */ | |
291 | if (type->isfloating ()) | |
292 | return false; | |
293 | break; | |
294 | ||
295 | case TOKandand: | |
296 | case TOKoror: | |
297 | /* Logical operators must have a result type of bool. */ | |
298 | return false; | |
299 | ||
300 | case TOKue: | |
301 | case TOKlg: | |
302 | case TOKule: | |
303 | case TOKul: | |
304 | case TOKuge: | |
305 | case TOKug: | |
306 | case TOKle: | |
307 | case TOKlt: | |
308 | case TOKge: | |
309 | case TOKgt: | |
310 | case TOKleg: | |
311 | case TOKunord: | |
312 | case TOKequal: | |
313 | case TOKnotequal: | |
314 | case TOKidentity: | |
315 | case TOKnotidentity: | |
316 | /* Comparison operators must have a result type of bool. */ | |
317 | return false; | |
318 | ||
319 | default: | |
320 | break; | |
321 | } | |
322 | ||
323 | return true; | |
324 | } | |
325 | ||
326 | /* Return the symbol mangling of S for C++ linkage. */ | |
327 | ||
328 | const char * | |
329 | Target::toCppMangle (Dsymbol *s) | |
330 | { | |
331 | return toCppMangleItanium (s); | |
332 | } | |
333 | ||
334 | /* Return the symbol mangling of CD for C++ linkage. */ | |
335 | ||
336 | const char * | |
337 | Target::cppTypeInfoMangle (ClassDeclaration *cd) | |
338 | { | |
339 | return cppTypeInfoMangleItanium (cd); | |
340 | } | |
341 | ||
342 | /* For a vendor-specific type, return a string containing the C++ mangling. | |
343 | In all other cases, return NULL. */ | |
344 | ||
345 | const char * | |
346 | Target::cppTypeMangle (Type *type) | |
347 | { | |
348 | if (type->isTypeBasic () || type->ty == Tvector || type->ty == Tstruct) | |
349 | { | |
350 | tree ctype = build_ctype (type); | |
351 | return targetm.mangle_type (ctype); | |
352 | } | |
353 | ||
354 | return NULL; | |
355 | } | |
356 | ||
357 | /* Return the type that will really be used for passing the given parameter | |
358 | ARG to an extern(C++) function. */ | |
359 | ||
360 | Type * | |
361 | Target::cppParameterType (Parameter *arg) | |
362 | { | |
363 | Type *t = arg->type->merge2 (); | |
364 | if (arg->storageClass & (STCout | STCref)) | |
365 | t = t->referenceTo (); | |
366 | else if (arg->storageClass & STClazy) | |
367 | { | |
368 | /* Mangle as delegate. */ | |
369 | Type *td = TypeFunction::create (NULL, t, 0, LINKd); | |
370 | td = TypeDelegate::create (td); | |
371 | t = t->merge2 (); | |
372 | } | |
373 | ||
374 | /* Could be a va_list, which we mangle as a pointer. */ | |
375 | if (t->ty == Tsarray && Type::tvalist->ty == Tsarray) | |
376 | { | |
377 | Type *tb = t->toBasetype ()->mutableOf (); | |
378 | if (tb == Type::tvalist) | |
379 | { | |
380 | tb = t->nextOf ()->pointerTo (); | |
381 | t = tb->castMod (t->mod); | |
382 | } | |
383 | } | |
384 | ||
385 | return t; | |
386 | } | |
387 | ||
c9634470 IB |
388 | /* Checks whether TYPE is a vendor-specific fundamental type. Stores the result |
389 | in IS_FUNDAMENTAL and returns true if the parameter was set. */ | |
390 | ||
391 | bool | |
392 | Target::cppFundamentalType (const Type *, bool &) | |
393 | { | |
394 | return false; | |
395 | } | |
396 | ||
b4c522fa IB |
397 | /* Return the default system linkage for the target. */ |
398 | ||
399 | LINK | |
400 | Target::systemLinkage (void) | |
401 | { | |
402 | return LINKc; | |
403 | } |