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(__riscv) || 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#endif
143
144typedef 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 CRT_HAS_FLOATING_POINT
169typedef union {
170 uqwords u;
171 long double f;
172} long_double_bits;
173
174#if __STDC_VERSION__ >= 199901L
175typedef float _Complex Fcomplex;
176typedef double _Complex Dcomplex;
177typedef long double _Complex Lcomplex;
178
179#define COMPLEX_REAL(x) __real__(x)
180#define COMPLEX_IMAGINARY(x) __imag__(x)
181#else
182typedef struct {
183 float real, imaginary;
184} Fcomplex;
185
186typedef struct {
187 double real, imaginary;
188} Dcomplex;
189
190typedef struct {
191 long double real, imaginary;
192} Lcomplex;
193
194#define COMPLEX_REAL(x) (x).real
195#define COMPLEX_IMAGINARY(x) (x).imaginary
196#endif
197#endif
198#endif // INT_TYPES_H
199

source code of compiler-rt/lib/builtins/int_types.h