blob: 18bf0a7f3bf993979c0ff5337ae78debb8d020f4 [file] [log] [blame]
Daniel Boulby318e7a52022-10-21 20:20:52 +01001//===-- 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//===----------------------------------------------------------------------===//
dp-arm75b60572017-05-04 12:12:06 +010015
16#ifndef INT_TYPES_H
17#define INT_TYPES_H
18
19#include "int_endianness.h"
20
Daniel Boulby318e7a52022-10-21 20:20:52 +010021// si_int is defined in Linux sysroot's asm-generic/siginfo.h
dp-arm75b60572017-05-04 12:12:06 +010022#ifdef si_int
23#undef si_int
24#endif
Daniel Boulby318e7a52022-10-21 20:20:52 +010025typedef int32_t si_int;
26typedef 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
dp-arm75b60572017-05-04 12:12:06 +010036
Daniel Boulby318e7a52022-10-21 20:20:52 +010037typedef int64_t di_int;
38typedef uint64_t du_int;
dp-arm75b60572017-05-04 12:12:06 +010039
Daniel Boulby318e7a52022-10-21 20:20:52 +010040typedef union {
41 di_int all;
42 struct {
dp-arm75b60572017-05-04 12:12:06 +010043#if _YUGA_LITTLE_ENDIAN
Daniel Boulby318e7a52022-10-21 20:20:52 +010044 su_int low;
45 si_int high;
dp-arm75b60572017-05-04 12:12:06 +010046#else
Daniel Boulby318e7a52022-10-21 20:20:52 +010047 si_int high;
48 su_int low;
49#endif // _YUGA_LITTLE_ENDIAN
50 } s;
dp-arm75b60572017-05-04 12:12:06 +010051} dwords;
52
Daniel Boulby318e7a52022-10-21 20:20:52 +010053typedef union {
54 du_int all;
55 struct {
dp-arm75b60572017-05-04 12:12:06 +010056#if _YUGA_LITTLE_ENDIAN
Daniel Boulby318e7a52022-10-21 20:20:52 +010057 su_int low;
58 su_int high;
dp-arm75b60572017-05-04 12:12:06 +010059#else
Daniel Boulby318e7a52022-10-21 20:20:52 +010060 su_int high;
61 su_int low;
62#endif // _YUGA_LITTLE_ENDIAN
63 } s;
dp-arm75b60572017-05-04 12:12:06 +010064} udwords;
65
Daniel Boulby318e7a52022-10-21 20:20:52 +010066#if defined(__LP64__) || defined(__wasm__) || defined(__mips64) || \
Maksims Svecovsc8829162023-05-04 16:57:43 +010067 defined(__SIZEOF_INT128__) || defined(_WIN64)
dp-arm75b60572017-05-04 12:12:06 +010068#define CRT_HAS_128BIT
69#endif
70
Daniel Boulby318e7a52022-10-21 20:20:52 +010071// 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
dp-arm75b60572017-05-04 12:12:06 +010078#ifdef CRT_HAS_128BIT
Daniel Boulby318e7a52022-10-21 20:20:52 +010079typedef int ti_int __attribute__((mode(TI)));
80typedef unsigned tu_int __attribute__((mode(TI)));
dp-arm75b60572017-05-04 12:12:06 +010081
Daniel Boulby318e7a52022-10-21 20:20:52 +010082typedef union {
83 ti_int all;
84 struct {
dp-arm75b60572017-05-04 12:12:06 +010085#if _YUGA_LITTLE_ENDIAN
Daniel Boulby318e7a52022-10-21 20:20:52 +010086 du_int low;
87 di_int high;
dp-arm75b60572017-05-04 12:12:06 +010088#else
Daniel Boulby318e7a52022-10-21 20:20:52 +010089 di_int high;
90 du_int low;
91#endif // _YUGA_LITTLE_ENDIAN
92 } s;
dp-arm75b60572017-05-04 12:12:06 +010093} twords;
94
Daniel Boulby318e7a52022-10-21 20:20:52 +010095typedef union {
96 tu_int all;
97 struct {
dp-arm75b60572017-05-04 12:12:06 +010098#if _YUGA_LITTLE_ENDIAN
Daniel Boulby318e7a52022-10-21 20:20:52 +010099 du_int low;
100 du_int high;
dp-arm75b60572017-05-04 12:12:06 +0100101#else
Daniel Boulby318e7a52022-10-21 20:20:52 +0100102 du_int high;
103 du_int low;
104#endif // _YUGA_LITTLE_ENDIAN
105 } s;
dp-arm75b60572017-05-04 12:12:06 +0100106} utwords;
107
108static __inline ti_int make_ti(di_int h, di_int l) {
Daniel Boulby318e7a52022-10-21 20:20:52 +0100109 twords r;
110 r.s.high = h;
111 r.s.low = l;
112 return r.all;
dp-arm75b60572017-05-04 12:12:06 +0100113}
114
115static __inline tu_int make_tu(du_int h, du_int l) {
Daniel Boulby318e7a52022-10-21 20:20:52 +0100116 utwords r;
117 r.s.high = h;
118 r.s.low = l;
119 return r.all;
dp-arm75b60572017-05-04 12:12:06 +0100120}
121
Daniel Boulby318e7a52022-10-21 20:20:52 +0100122#endif // CRT_HAS_128BIT
dp-arm75b60572017-05-04 12:12:06 +0100123
Daniel Boulby318e7a52022-10-21 20:20:52 +0100124// 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
133typedef union {
134 su_int u;
135 float f;
dp-arm75b60572017-05-04 12:12:06 +0100136} float_bits;
137
Daniel Boulby318e7a52022-10-21 20:20:52 +0100138typedef union {
139 udwords u;
140 double f;
dp-arm75b60572017-05-04 12:12:06 +0100141} double_bits;
Daniel Boulby318e7a52022-10-21 20:20:52 +0100142#endif
dp-arm75b60572017-05-04 12:12:06 +0100143
Daniel Boulby318e7a52022-10-21 20:20:52 +0100144typedef struct {
dp-arm75b60572017-05-04 12:12:06 +0100145#if _YUGA_LITTLE_ENDIAN
Daniel Boulby318e7a52022-10-21 20:20:52 +0100146 udwords low;
147 udwords high;
dp-arm75b60572017-05-04 12:12:06 +0100148#else
Daniel Boulby318e7a52022-10-21 20:20:52 +0100149 udwords high;
150 udwords low;
151#endif // _YUGA_LITTLE_ENDIAN
dp-arm75b60572017-05-04 12:12:06 +0100152} uqwords;
153
Daniel Boulby318e7a52022-10-21 20:20:52 +0100154// Check if the target supports 80 bit extended precision long doubles.
155// Notably, on x86 Windows, MSVC only provides a 64-bit long double, but GCC
156// still makes it 80 bits. Clang will match whatever compiler it is trying to
157// be compatible with. On 32-bit x86 Android, long double is 64 bits, while on
158// x86_64 Android, long double is 128 bits.
159#if (defined(__i386__) || defined(__x86_64__)) && \
160 !(defined(_MSC_VER) || defined(__ANDROID__))
161#define HAS_80_BIT_LONG_DOUBLE 1
162#elif defined(__m68k__) || defined(__ia64__)
163#define HAS_80_BIT_LONG_DOUBLE 1
164#else
165#define HAS_80_BIT_LONG_DOUBLE 0
166#endif
167
Manish Pandey9320bd52023-11-06 16:45:14 +0000168#if HAS_80_BIT_LONG_DOUBLE
169typedef long double xf_float;
Daniel Boulby318e7a52022-10-21 20:20:52 +0100170typedef union {
171 uqwords u;
Manish Pandey9320bd52023-11-06 16:45:14 +0000172 xf_float f;
173} xf_bits;
174#endif
175
176#ifdef __powerpc64__
177// From https://gcc.gnu.org/wiki/Ieee128PowerPC:
178// PowerPC64 uses the following suffixes:
179// IFmode: IBM extended double
180// KFmode: IEEE 128-bit floating point
181// TFmode: Matches the default for long double. With -mabi=ieeelongdouble,
182// it is IEEE 128-bit, with -mabi=ibmlongdouble IBM extended double
183// Since compiler-rt only implements the tf set of libcalls, we use long double
184// for the tf_float typedef.
185typedef long double tf_float;
186#define CRT_LDBL_128BIT
187#define CRT_HAS_F128
188#if __LDBL_MANT_DIG__ == 113 && !defined(__LONG_DOUBLE_IBM128__)
189#define CRT_HAS_IEEE_TF
190#define CRT_LDBL_IEEE_F128
191#endif
192#define TF_C(x) x##L
193#elif __LDBL_MANT_DIG__ == 113
194// Use long double instead of __float128 if it matches the IEEE 128-bit format.
195#define CRT_LDBL_128BIT
196#define CRT_HAS_F128
197#define CRT_HAS_IEEE_TF
198#define CRT_LDBL_IEEE_F128
199typedef long double tf_float;
200#define TF_C(x) x##L
201#elif defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
202#define CRT_HAS___FLOAT128_KEYWORD
203#define CRT_HAS_F128
204// NB: we assume the __float128 type uses IEEE representation.
205#define CRT_HAS_IEEE_TF
206typedef __float128 tf_float;
207#define TF_C(x) x##Q
208#endif
209
210#ifdef CRT_HAS_F128
211typedef union {
212 uqwords u;
213 tf_float f;
214} tf_bits;
215#endif
dp-arm75b60572017-05-04 12:12:06 +0100216
Manish Pandey9320bd52023-11-06 16:45:14 +0000217// __(u)int128_t is currently needed to compile the *tf builtins as we would
218// otherwise need to manually expand the bit manipulation on two 64-bit value.
219#if defined(CRT_HAS_128BIT) && defined(CRT_HAS_F128)
220#define CRT_HAS_TF_MODE
221#endif
222
223#if CRT_HAS_FLOATING_POINT
dp-arm75b60572017-05-04 12:12:06 +0100224#if __STDC_VERSION__ >= 199901L
225typedef float _Complex Fcomplex;
226typedef double _Complex Dcomplex;
227typedef long double _Complex Lcomplex;
Manish Pandey9320bd52023-11-06 16:45:14 +0000228#if defined(CRT_LDBL_128BIT)
229typedef Lcomplex Qcomplex;
230#define CRT_HAS_NATIVE_COMPLEX_F128
231#elif defined(CRT_HAS___FLOAT128_KEYWORD)
232#if defined(__clang_major__) && __clang_major__ > 10
233// Clang prior to 11 did not support __float128 _Complex.
234typedef __float128 _Complex Qcomplex;
235#define CRT_HAS_NATIVE_COMPLEX_F128
236#elif defined(__GNUC__) && __GNUC__ >= 7
237// GCC does not allow __float128 _Complex, but accepts _Float128 _Complex.
238typedef _Float128 _Complex Qcomplex;
239#define CRT_HAS_NATIVE_COMPLEX_F128
240#endif
241#endif
dp-arm75b60572017-05-04 12:12:06 +0100242
243#define COMPLEX_REAL(x) __real__(x)
244#define COMPLEX_IMAGINARY(x) __imag__(x)
245#else
Daniel Boulby318e7a52022-10-21 20:20:52 +0100246typedef struct {
247 float real, imaginary;
248} Fcomplex;
dp-arm75b60572017-05-04 12:12:06 +0100249
Daniel Boulby318e7a52022-10-21 20:20:52 +0100250typedef struct {
251 double real, imaginary;
252} Dcomplex;
dp-arm75b60572017-05-04 12:12:06 +0100253
Daniel Boulby318e7a52022-10-21 20:20:52 +0100254typedef struct {
255 long double real, imaginary;
256} Lcomplex;
dp-arm75b60572017-05-04 12:12:06 +0100257
258#define COMPLEX_REAL(x) (x).real
259#define COMPLEX_IMAGINARY(x) (x).imaginary
260#endif
Manish Pandey9320bd52023-11-06 16:45:14 +0000261
262#ifdef CRT_HAS_NATIVE_COMPLEX_F128
263#define COMPLEXTF_REAL(x) __real__(x)
264#define COMPLEXTF_IMAGINARY(x) __imag__(x)
265#elif defined(CRT_HAS_F128)
266typedef struct {
267 tf_float real, imaginary;
268} Qcomplex;
269#define COMPLEXTF_REAL(x) (x).real
270#define COMPLEXTF_IMAGINARY(x) (x).imaginary
271#endif
272
Daniel Boulby318e7a52022-10-21 20:20:52 +0100273#endif
274#endif // INT_TYPES_H