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 25typedef 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 36 37typedef int64_t di_int; 38typedef uint64_t du_int; 39 40typedef 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 53typedef 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 79typedef int ti_int __attribute__((mode(TI))); 80typedef unsigned tu_int __attribute__((mode(TI))); 81 82typedef 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 95typedef 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 108static __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 115static __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 133typedef union { 134 su_int u; 135 float f; 136} float_bits; 137 138typedef union { 139 udwords u; 140 double f; 141} double_bits; 142 143typedef 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 168typedef long double xf_float; 169typedef 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. 184typedef 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 202typedef 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 209typedef __float128 tf_float; 210#define TF_C(x) x##Q 211#endif 212 213#ifdef CRT_HAS_F128 214typedef 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 227typedef float _Complex Fcomplex; 228typedef double _Complex Dcomplex; 229typedef long double _Complex Lcomplex; 230#if defined(CRT_LDBL_128BIT) 231typedef 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. 236typedef __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. 240typedef _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 248typedef struct { 249 float real, imaginary; 250} Fcomplex; 251 252typedef struct { 253 double real, imaginary; 254} Dcomplex; 255 256typedef 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) 268typedef 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