1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // Copyright (C) 2022 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QTYPES_H |
6 | #define QTYPES_H |
7 | |
8 | #include <QtCore/qprocessordetection.h> |
9 | #include <QtCore/qtconfigmacros.h> |
10 | #include <QtCore/qassert.h> |
11 | |
12 | #ifdef __cplusplus |
13 | # include <cstddef> |
14 | # include <cstdint> |
15 | # if defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>) |
16 | // P1467 implementation - https://wg21.link/p1467 |
17 | # include <stdfloat> |
18 | # endif // defined(__STDCPP_FLOAT16_T__) && __has_include(<stdfloat>) |
19 | #else |
20 | # include <assert.h> |
21 | #endif |
22 | |
23 | #if 0 |
24 | #pragma qt_class(QtTypes) |
25 | #pragma qt_class(QIntegerForSize) |
26 | #pragma qt_sync_stop_processing |
27 | #endif |
28 | |
29 | /* |
30 | Useful type definitions for Qt |
31 | */ |
32 | typedef unsigned char uchar; |
33 | typedef unsigned short ushort; |
34 | typedef unsigned int uint; |
35 | typedef unsigned long ulong; |
36 | |
37 | QT_BEGIN_NAMESPACE |
38 | |
39 | /* |
40 | Size-dependent types (architecture-dependent byte order) |
41 | |
42 | Make sure to update QMetaType when changing these typedefs |
43 | */ |
44 | |
45 | typedef signed char qint8; /* 8 bit signed */ |
46 | typedef unsigned char quint8; /* 8 bit unsigned */ |
47 | typedef short qint16; /* 16 bit signed */ |
48 | typedef unsigned short quint16; /* 16 bit unsigned */ |
49 | typedef int qint32; /* 32 bit signed */ |
50 | typedef unsigned int quint32; /* 32 bit unsigned */ |
51 | // Unlike LL / ULL in C++, for historical reasons, we force the |
52 | // result to be of the requested type. |
53 | #ifdef __cplusplus |
54 | # define Q_INT64_C(c) static_cast<long long>(c ## LL) /* signed 64 bit constant */ |
55 | # define Q_UINT64_C(c) static_cast<unsigned long long>(c ## ULL) /* unsigned 64 bit constant */ |
56 | #else |
57 | # define Q_INT64_C(c) ((long long)(c ## LL)) /* signed 64 bit constant */ |
58 | # define Q_UINT64_C(c) ((unsigned long long)(c ## ULL)) /* unsigned 64 bit constant */ |
59 | #endif |
60 | typedef long long qint64; /* 64 bit signed */ |
61 | typedef unsigned long long quint64; /* 64 bit unsigned */ |
62 | |
63 | typedef qint64 qlonglong; |
64 | typedef quint64 qulonglong; |
65 | |
66 | #if defined(__SIZEOF_INT128__) && !defined(QT_NO_INT128) |
67 | # define QT_SUPPORTS_INT128 __SIZEOF_INT128__ |
68 | #else |
69 | # undef QT_SUPPORTS_INT128 |
70 | #endif |
71 | |
72 | #if defined(QT_SUPPORTS_INT128) |
73 | __extension__ typedef __int128_t qint128; |
74 | __extension__ typedef __uint128_t quint128; |
75 | |
76 | // limits: |
77 | # ifdef __cplusplus /* need to avoid c-style-casts in C++ mode */ |
78 | # define QT_C_STYLE_CAST(type, x) static_cast<type>(x) |
79 | # else /* but C doesn't have constructor-style casts */ |
80 | # define QT_C_STYLE_CAST(type, x) ((type)(x)) |
81 | # endif |
82 | # ifndef Q_UINT128_MAX /* allow qcompilerdetection.h/user override */ |
83 | # define Q_UINT128_MAX QT_C_STYLE_CAST(quint128, -1) |
84 | # endif |
85 | # define Q_INT128_MAX QT_C_STYLE_CAST(qint128, Q_UINT128_MAX / 2) |
86 | # define Q_INT128_MIN (-Q_INT128_MAX - 1) |
87 | |
88 | # ifdef __cplusplus |
89 | namespace QtPrivate::NumberLiterals { |
90 | namespace detail { |
91 | template <quint128 accu, int base> |
92 | constexpr quint128 construct() { return accu; } |
93 | |
94 | template <quint128 accu, int base, char C, char...Cs> |
95 | constexpr quint128 construct() |
96 | { |
97 | if constexpr (C != '\'') { // ignore digit separators |
98 | const int digitValue = '0' <= C && C <= '9' ? C - '0' : |
99 | 'a' <= C && C <= 'z' ? C - 'a' + 10 : |
100 | 'A' <= C && C <= 'Z' ? C - 'A' + 10 : |
101 | /* else */ -1 ; |
102 | static_assert(digitValue >= 0 && digitValue < base, |
103 | "Invalid character" ); |
104 | // accu * base + digitValue <= MAX, but without overflow: |
105 | static_assert(accu <= (Q_UINT128_MAX - digitValue) / base, |
106 | "Overflow occurred" ); |
107 | return construct<accu * base + digitValue, base, Cs...>(); |
108 | } else { |
109 | return construct<accu, base, Cs...>(); |
110 | } |
111 | } |
112 | |
113 | template <char C, char...Cs> |
114 | constexpr quint128 parse0xb() |
115 | { |
116 | constexpr quint128 accu = 0; |
117 | if constexpr (C == 'x' || C == 'X') |
118 | return construct<accu, 16, Cs...>(); // base 16, skip 'x' |
119 | else if constexpr (C == 'b' || C == 'B') |
120 | return construct<accu, 2, Cs...>(); // base 2, skip 'b' |
121 | else |
122 | return construct<accu, 8, C, Cs...>(); // base 8, include C |
123 | } |
124 | |
125 | template <char...Cs> |
126 | constexpr quint128 parse0() |
127 | { |
128 | if constexpr (sizeof...(Cs) == 0) // this was just a literal 0 |
129 | return 0; |
130 | else |
131 | return parse0xb<Cs...>(); |
132 | } |
133 | |
134 | template <char C, char...Cs> |
135 | constexpr quint128 parse() |
136 | { |
137 | if constexpr (C == '0') |
138 | return parse0<Cs...>(); // base 2, 8, or 16 (or just a literal 0), skip '0' |
139 | else |
140 | return construct<0, 10, C, Cs...>(); // initial accu 0, base 10, include C |
141 | } |
142 | } // namespace detail |
143 | template <char...Cs> |
144 | constexpr quint128 operator""_quint128 () noexcept |
145 | { return QtPrivate::NumberLiterals::detail::parse<Cs...>(); } |
146 | template <char...Cs> |
147 | constexpr qint128 operator""_qint128 () noexcept |
148 | { return qint128(QtPrivate::NumberLiterals::detail::parse<Cs...>()); } |
149 | |
150 | #ifndef Q_UINT128_C // allow qcompilerdetection.h/user override |
151 | # define Q_UINT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _quint128; }()) |
152 | #endif |
153 | #ifndef Q_INT128_C // allow qcompilerdetection.h/user override |
154 | # define Q_INT128_C(c) ([]{ using namespace QtPrivate::NumberLiterals; return c ## _qint128; }()) |
155 | #endif |
156 | |
157 | } // namespace QtPrivate::NumberLiterals |
158 | # endif // __cplusplus |
159 | #endif // QT_SUPPORTS_INT128 |
160 | |
161 | #ifndef __cplusplus |
162 | // In C++ mode, we define below using QIntegerForSize template |
163 | static_assert(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions" ); |
164 | typedef ptrdiff_t qptrdiff; |
165 | typedef ptrdiff_t qsizetype; |
166 | typedef ptrdiff_t qintptr; |
167 | typedef size_t quintptr; |
168 | |
169 | #define PRIdQPTRDIFF "td" |
170 | #define PRIiQPTRDIFF "ti" |
171 | |
172 | #define PRIdQSIZETYPE "td" |
173 | #define PRIiQSIZETYPE "ti" |
174 | |
175 | #define PRIdQINTPTR "td" |
176 | #define PRIiQINTPTR "ti" |
177 | |
178 | #define PRIuQUINTPTR "zu" |
179 | #define PRIoQUINTPTR "zo" |
180 | #define PRIxQUINTPTR "zx" |
181 | #define PRIXQUINTPTR "zX" |
182 | #endif |
183 | |
184 | #if defined(QT_COORD_TYPE) |
185 | typedef QT_COORD_TYPE qreal; |
186 | #else |
187 | typedef double qreal; |
188 | #endif |
189 | |
190 | #if defined(__cplusplus) |
191 | /* |
192 | quintptr are qptrdiff is guaranteed to be the same size as a pointer, i.e. |
193 | |
194 | sizeof(void *) == sizeof(quintptr) |
195 | && sizeof(void *) == sizeof(qptrdiff) |
196 | |
197 | While size_t and qsizetype are not guaranteed to be the same size as a pointer, |
198 | they usually are and we do check for that in qtypes.cpp, just to be sure. |
199 | */ |
200 | template <int> struct QIntegerForSize; |
201 | template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; }; |
202 | template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; }; |
203 | template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; }; |
204 | template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; }; |
205 | #if defined(QT_SUPPORTS_INT128) |
206 | template <> struct QIntegerForSize<16> { typedef quint128 Unsigned; typedef qint128 Signed; }; |
207 | #endif |
208 | template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { }; |
209 | typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Signed qregisterint; |
210 | typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Unsigned qregisteruint; |
211 | typedef QIntegerForSizeof<void *>::Unsigned quintptr; |
212 | typedef QIntegerForSizeof<void *>::Signed qptrdiff; |
213 | typedef qptrdiff qintptr; |
214 | using qsizetype = QIntegerForSizeof<std::size_t>::Signed; |
215 | |
216 | // These custom definitions are necessary as we're not defining our |
217 | // datatypes in terms of the language ones, but in terms of integer |
218 | // types that have the sime size. For instance, on a 32-bit platform, |
219 | // qptrdiff is int, while ptrdiff_t may be aliased to long; therefore |
220 | // using %td to print a qptrdiff would be wrong (and raise -Wformat |
221 | // warnings), although both int and long have same bit size on that |
222 | // platform. |
223 | // |
224 | // We know that sizeof(size_t) == sizeof(void *) == sizeof(qptrdiff). |
225 | #if SIZE_MAX == 0xffffffffULL |
226 | #define PRIuQUINTPTR "u" |
227 | #define PRIoQUINTPTR "o" |
228 | #define PRIxQUINTPTR "x" |
229 | #define PRIXQUINTPTR "X" |
230 | |
231 | #define PRIdQPTRDIFF "d" |
232 | #define PRIiQPTRDIFF "i" |
233 | |
234 | #define PRIdQINTPTR "d" |
235 | #define PRIiQINTPTR "i" |
236 | |
237 | #define PRIdQSIZETYPE "d" |
238 | #define PRIiQSIZETYPE "i" |
239 | #elif SIZE_MAX == 0xffffffffffffffffULL |
240 | #define PRIuQUINTPTR "llu" |
241 | #define PRIoQUINTPTR "llo" |
242 | #define PRIxQUINTPTR "llx" |
243 | #define PRIXQUINTPTR "llX" |
244 | |
245 | #define PRIdQPTRDIFF "lld" |
246 | #define PRIiQPTRDIFF "lli" |
247 | |
248 | #define PRIdQINTPTR "lld" |
249 | #define PRIiQINTPTR "lli" |
250 | |
251 | #define PRIdQSIZETYPE "lld" |
252 | #define PRIiQSIZETYPE "lli" |
253 | #else |
254 | #error Unsupported platform (unknown value for SIZE_MAX) |
255 | #endif |
256 | |
257 | // Define a native float16 type |
258 | namespace QtPrivate { |
259 | #if defined(__STDCPP_FLOAT16_T__) |
260 | # define QFLOAT16_IS_NATIVE 1 |
261 | using NativeFloat16Type = std::float16_t; |
262 | #elif defined(Q_CC_CLANG) && defined(__FLT16_MAX__) && 0 |
263 | // disabled due to https://github.com/llvm/llvm-project/issues/56963 |
264 | # define QFLOAT16_IS_NATIVE 1 |
265 | using NativeFloat16Type = decltype(__FLT16_MAX__); |
266 | #elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__) && defined(__ARM_FP16_FORMAT_IEEE) |
267 | # define QFLOAT16_IS_NATIVE 1 |
268 | using NativeFloat16Type = __fp16; |
269 | #elif defined(Q_CC_GNU_ONLY) && defined(__FLT16_MAX__) && defined(__SSE2__) |
270 | # define QFLOAT16_IS_NATIVE 1 |
271 | using NativeFloat16Type = _Float16; |
272 | #else |
273 | # define QFLOAT16_IS_NATIVE 0 |
274 | using NativeFloat16Type = void; |
275 | #endif |
276 | } // QtPrivate |
277 | |
278 | #endif // __cplusplus |
279 | |
280 | QT_END_NAMESPACE |
281 | |
282 | #endif // QTYPES_H |
283 | |