xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/int_types.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1  //===-- int_lib.h - configuration header for compiler-rt  -----------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file is not part of the interface of this library.
10  //
11  // This file defines various standard types, most importantly a number of unions
12  // used to access parts of larger types.
13  //
14  //===----------------------------------------------------------------------===//
15  
16  #ifndef INT_TYPES_H
17  #define INT_TYPES_H
18  
19  #include "int_endianness.h"
20  
21  // si_int is defined in Linux sysroot's asm-generic/siginfo.h
22  #ifdef si_int
23  #undef si_int
24  #endif
25  typedef int32_t si_int;
26  typedef uint32_t su_int;
27  #if UINT_MAX == 0xFFFFFFFF
28  #define clzsi __builtin_clz
29  #define ctzsi __builtin_ctz
30  #elif ULONG_MAX == 0xFFFFFFFF
31  #define clzsi __builtin_clzl
32  #define ctzsi __builtin_ctzl
33  #else
34  #error could not determine appropriate clzsi macro for this system
35  #endif
36  
37  typedef int64_t di_int;
38  typedef uint64_t du_int;
39  
40  typedef union {
41    di_int all;
42    struct {
43  #if _YUGA_LITTLE_ENDIAN
44      su_int low;
45      si_int high;
46  #else
47      si_int high;
48      su_int low;
49  #endif // _YUGA_LITTLE_ENDIAN
50    } s;
51  } dwords;
52  
53  typedef union {
54    du_int all;
55    struct {
56  #if _YUGA_LITTLE_ENDIAN
57      su_int low;
58      su_int high;
59  #else
60      su_int high;
61      su_int low;
62  #endif // _YUGA_LITTLE_ENDIAN
63    } s;
64  } udwords;
65  
66  #if defined(__LP64__) || defined(__wasm__) || defined(__mips64) ||             \
67      defined(__SIZEOF_INT128__) || defined(_WIN64)
68  #define CRT_HAS_128BIT
69  #endif
70  
71  // MSVC doesn't have a working 128bit integer type. Users should really compile
72  // compiler-rt with clang, but if they happen to be doing a standalone build for
73  // asan or something else, disable the 128 bit parts so things sort of work.
74  #if defined(_MSC_VER) && !defined(__clang__)
75  #undef CRT_HAS_128BIT
76  #endif
77  
78  #ifdef CRT_HAS_128BIT
79  typedef int ti_int __attribute__((mode(TI)));
80  typedef unsigned tu_int __attribute__((mode(TI)));
81  
82  typedef union {
83    ti_int all;
84    struct {
85  #if _YUGA_LITTLE_ENDIAN
86      du_int low;
87      di_int high;
88  #else
89      di_int high;
90      du_int low;
91  #endif // _YUGA_LITTLE_ENDIAN
92    } s;
93  } twords;
94  
95  typedef union {
96    tu_int all;
97    struct {
98  #if _YUGA_LITTLE_ENDIAN
99      du_int low;
100      du_int high;
101  #else
102      du_int high;
103      du_int low;
104  #endif // _YUGA_LITTLE_ENDIAN
105    } s;
106  } utwords;
107  
make_ti(di_int h,di_int l)108  static __inline ti_int make_ti(di_int h, di_int l) {
109    twords r;
110    r.s.high = (du_int)h;
111    r.s.low = (du_int)l;
112    return r.all;
113  }
114  
make_tu(du_int h,du_int l)115  static __inline tu_int make_tu(du_int h, du_int l) {
116    utwords r;
117    r.s.high = h;
118    r.s.low = l;
119    return r.all;
120  }
121  
122  #endif // CRT_HAS_128BIT
123  
124  // FreeBSD's boot environment does not support using floating-point and poisons
125  // the float and double keywords.
126  #if defined(__FreeBSD__) && defined(_STANDALONE)
127  #define CRT_HAS_FLOATING_POINT 0
128  #else
129  #define CRT_HAS_FLOATING_POINT 1
130  #endif
131  
132  #if CRT_HAS_FLOATING_POINT
133  typedef union {
134    su_int u;
135    float f;
136  } float_bits;
137  
138  typedef union {
139    udwords u;
140    double f;
141  } double_bits;
142  
143  typedef struct {
144  #if _YUGA_LITTLE_ENDIAN
145    udwords low;
146    udwords high;
147  #else
148    udwords high;
149    udwords low;
150  #endif // _YUGA_LITTLE_ENDIAN
151  } uqwords;
152  
153  // Check if the target supports 80 bit extended precision long doubles.
154  // Notably, on x86 Windows, MSVC only provides a 64-bit long double, but GCC
155  // still makes it 80 bits. Clang will match whatever compiler it is trying to
156  // be compatible with. On 32-bit x86 Android, long double is 64 bits, while on
157  // x86_64 Android, long double is 128 bits.
158  #if (defined(__i386__) || defined(__x86_64__)) &&                              \
159      !(defined(_MSC_VER) || defined(__ANDROID__))
160  #define HAS_80_BIT_LONG_DOUBLE 1
161  #elif defined(__m68k__) || defined(__ia64__)
162  #define HAS_80_BIT_LONG_DOUBLE 1
163  #else
164  #define HAS_80_BIT_LONG_DOUBLE 0
165  #endif
166  
167  #if HAS_80_BIT_LONG_DOUBLE
168  typedef long double xf_float;
169  typedef union {
170    uqwords u;
171    xf_float f;
172  } xf_bits;
173  #endif
174  
175  #ifdef __powerpc64__
176  // From https://gcc.gnu.org/wiki/Ieee128PowerPC:
177  // PowerPC64 uses the following suffixes:
178  // IFmode: IBM extended double
179  // KFmode: IEEE 128-bit floating point
180  // TFmode: Matches the default for long double. With -mabi=ieeelongdouble,
181  //         it is IEEE 128-bit, with -mabi=ibmlongdouble IBM extended double
182  // Since compiler-rt only implements the tf set of libcalls, we use long double
183  // for the tf_float typedef.
184  typedef long double tf_float;
185  #define CRT_LDBL_128BIT
186  #define CRT_HAS_F128
187  #if __LDBL_MANT_DIG__ == 113 && !defined(__LONG_DOUBLE_IBM128__)
188  #define CRT_HAS_IEEE_TF
189  #define CRT_LDBL_IEEE_F128
190  #endif
191  #define TF_C(x) x##L
192  #elif __LDBL_MANT_DIG__ == 113 ||                                              \
193      (__FLT_RADIX__ == 16 && __LDBL_MANT_DIG__ == 28)
194  // Use long double instead of __float128 if it matches the IEEE 128-bit format
195  // or the IBM hexadecimal format.
196  #define CRT_LDBL_128BIT
197  #define CRT_HAS_F128
198  #if __LDBL_MANT_DIG__ == 113
199  #define CRT_HAS_IEEE_TF
200  #define CRT_LDBL_IEEE_F128
201  #endif
202  typedef long double tf_float;
203  #define TF_C(x) x##L
204  #elif defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
205  #define CRT_HAS___FLOAT128_KEYWORD
206  #define CRT_HAS_F128
207  // NB: we assume the __float128 type uses IEEE representation.
208  #define CRT_HAS_IEEE_TF
209  typedef __float128 tf_float;
210  #define TF_C(x) x##Q
211  #endif
212  
213  #ifdef CRT_HAS_F128
214  typedef union {
215    uqwords u;
216    tf_float f;
217  } tf_bits;
218  #endif
219  
220  // __(u)int128_t is currently needed to compile the *tf builtins as we would
221  // otherwise need to manually expand the bit manipulation on two 64-bit value.
222  #if defined(CRT_HAS_128BIT) && defined(CRT_HAS_F128)
223  #define CRT_HAS_TF_MODE
224  #endif
225  
226  #if __STDC_VERSION__ >= 199901L
227  typedef float _Complex Fcomplex;
228  typedef double _Complex Dcomplex;
229  typedef long double _Complex Lcomplex;
230  #if defined(CRT_LDBL_128BIT)
231  typedef Lcomplex Qcomplex;
232  #define CRT_HAS_NATIVE_COMPLEX_F128
233  #elif defined(CRT_HAS___FLOAT128_KEYWORD)
234  #if defined(__clang_major__) && __clang_major__ > 10
235  // Clang prior to 11 did not support __float128 _Complex.
236  typedef __float128 _Complex Qcomplex;
237  #define CRT_HAS_NATIVE_COMPLEX_F128
238  #elif defined(__GNUC__) && __GNUC__ >= 7
239  // GCC does not allow __float128 _Complex, but accepts _Float128 _Complex.
240  typedef _Float128 _Complex Qcomplex;
241  #define CRT_HAS_NATIVE_COMPLEX_F128
242  #endif
243  #endif
244  
245  #define COMPLEX_REAL(x) __real__(x)
246  #define COMPLEX_IMAGINARY(x) __imag__(x)
247  #else
248  typedef struct {
249    float real, imaginary;
250  } Fcomplex;
251  
252  typedef struct {
253    double real, imaginary;
254  } Dcomplex;
255  
256  typedef struct {
257    long double real, imaginary;
258  } Lcomplex;
259  
260  #define COMPLEX_REAL(x) (x).real
261  #define COMPLEX_IMAGINARY(x) (x).imaginary
262  #endif
263  
264  #ifdef CRT_HAS_NATIVE_COMPLEX_F128
265  #define COMPLEXTF_REAL(x) __real__(x)
266  #define COMPLEXTF_IMAGINARY(x) __imag__(x)
267  #elif defined(CRT_HAS_F128)
268  typedef struct {
269    tf_float real, imaginary;
270  } Qcomplex;
271  #define COMPLEXTF_REAL(x) (x).real
272  #define COMPLEXTF_IMAGINARY(x) (x).imaginary
273  #endif
274  
275  #endif // CRT_HAS_FLOATING_POINT
276  #endif // INT_TYPES_H
277