xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/d-target.cc (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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 .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
define_float_constants(tree type)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
_init(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
alignsize(Type * type)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
fieldalign(Type * type)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
critsecsize(void)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 *
va_listType(void)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
isVectorTypeSupported(int sz,Type * type)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
isVectorOpSupported(Type * type,TOK op,Type *)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 *
toCppMangle(Dsymbol * s)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 *
cppTypeInfoMangle(ClassDeclaration * cd)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 *
cppTypeMangle(Type * type)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 *
cppParameterType(Parameter * arg)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
cppFundamentalType(const Type *,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
systemLinkage(void)409 Target::systemLinkage (void)
410 {
411   return LINKc;
412 }
413 
414 /* Generate a TypeTuple of the equivalent types used to determine if a
415    function argument of the given type can be passed in registers.
416    The results of this are highly platform dependent, and intended
417    primarly for use in implementing va_arg() with RTTI.  */
418 
419 TypeTuple *
toArgTypes(Type *)420 Target::toArgTypes (Type *)
421 {
422   /* Not implemented, however this is not currently used anywhere.  */
423   return NULL;
424 }
425