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 108 static __inline ti_int make_ti(di_int h, di_int l) { 109 twords r; 110 r.s.high = h; 111 r.s.low = l; 112 return r.all; 113 } 114 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 #endif 143 144 typedef struct { 145 #if _YUGA_LITTLE_ENDIAN 146 udwords low; 147 udwords high; 148 #else 149 udwords high; 150 udwords low; 151 #endif // _YUGA_LITTLE_ENDIAN 152 } uqwords; 153 154 // 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 168 #if HAS_80_BIT_LONG_DOUBLE 169 typedef long double xf_float; 170 typedef union { 171 uqwords u; 172 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. 185 typedef 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 199 typedef 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 206 typedef __float128 tf_float; 207 #define TF_C(x) x##Q 208 #endif 209 210 #ifdef CRT_HAS_F128 211 typedef union { 212 uqwords u; 213 tf_float f; 214 } tf_bits; 215 #endif 216 217 // __(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 224 #if __STDC_VERSION__ >= 199901L 225 typedef float _Complex Fcomplex; 226 typedef double _Complex Dcomplex; 227 typedef long double _Complex Lcomplex; 228 #if defined(CRT_LDBL_128BIT) 229 typedef 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. 234 typedef __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. 238 typedef _Float128 _Complex Qcomplex; 239 #define CRT_HAS_NATIVE_COMPLEX_F128 240 #endif 241 #endif 242 243 #define COMPLEX_REAL(x) __real__(x) 244 #define COMPLEX_IMAGINARY(x) __imag__(x) 245 #else 246 typedef struct { 247 float real, imaginary; 248 } Fcomplex; 249 250 typedef struct { 251 double real, imaginary; 252 } Dcomplex; 253 254 typedef struct { 255 long double real, imaginary; 256 } Lcomplex; 257 258 #define COMPLEX_REAL(x) (x).real 259 #define COMPLEX_IMAGINARY(x) (x).imaginary 260 #endif 261 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) 266 typedef 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 273 #endif 274 #endif // INT_TYPES_H 275