Mercurial > hg > CbC > CbC_gcc
comparison gcc/d/d-target.cc @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
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 /* 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. */ | |
85 get_max_float (fmt, buf, sizeof (buf), false); | |
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 | |
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)); | |
147 | |
148 /* Define what type to use for size_t, ptrdiff_t. */ | |
149 if (Target::ptrsize == 8) | |
150 { | |
151 global.params.isLP64 = true; | |
152 Tsize_t = Tuns64; | |
153 Tptrdiff_t = Tint64; | |
154 } | |
155 else if (Target::ptrsize == 4) | |
156 { | |
157 Tsize_t = Tuns32; | |
158 Tptrdiff_t = Tint32; | |
159 } | |
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."); | |
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 ()); | |
201 return min_align_of_type (build_ctype (type)); | |
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 | |
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 | |
406 /* Return the default system linkage for the target. */ | |
407 | |
408 LINK | |
409 Target::systemLinkage (void) | |
410 { | |
411 return LINKc; | |
412 } |