simdjson
4.5.0
Ridiculously Fast JSON
Loading...
Searching...
No Matches
portability.h
1
#ifndef SIMDJSON_PORTABILITY_H
2
#define SIMDJSON_PORTABILITY_H
3
4
#include <cstddef>
5
#include <cstdint>
6
#include <cstdlib>
7
#include <cfloat>
8
#include <cassert>
9
#include <climits>
10
#ifndef _WIN32
11
// strcasecmp, strncasecmp
12
#include <strings.h>
13
#endif
14
15
static_assert
(CHAR_BIT == 8,
"simdjson requires 8-bit bytes"
);
16
17
18
// We are using size_t without namespace std:: throughout the project
19
using
std::size_t;
20
21
#ifdef _MSC_VER
22
#define SIMDJSON_VISUAL_STUDIO 1
33
#ifdef __clang__
34
// clang under visual studio
35
#define SIMDJSON_CLANG_VISUAL_STUDIO 1
36
#else
37
// just regular visual studio (best guess)
38
#define SIMDJSON_REGULAR_VISUAL_STUDIO 1
39
#endif
// __clang__
40
#endif
// _MSC_VER
41
42
#if (defined(__x86_64__) || defined(_M_AMD64)) && !defined(_M_ARM64EC)
43
#define SIMDJSON_IS_X86_64 1
44
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
45
#define SIMDJSON_IS_ARM64 1
46
#elif defined(__riscv) && __riscv_xlen == 64
47
#define SIMDJSON_IS_RISCV64 1
48
49
#if __riscv_v_intrinsic >= 11000
50
#define SIMDJSON_HAS_RVV_INTRINSICS 1
51
#endif
52
53
#if SIMDJSON_HAS_RVV_INTRINSICS && __riscv_vector && __riscv_v_min_vlen >= 128 && __riscv_v_elen >= 64
54
#define SIMDJSON_IS_RVV 1
// RISC-V V extension
55
#endif
56
57
// current toolchains don't support fixed-size SIMD types that don't match VLEN directly
58
#if __riscv_v_fixed_vlen >= 128 && __riscv_v_fixed_vlen <= 512
59
#define SIMDJSON_IS_RVV_VLS 1
60
#endif
61
62
#elif defined(__loongarch_lp64)
63
#define SIMDJSON_IS_LOONGARCH64 1
64
#if defined(__loongarch_sx) && defined(__loongarch_asx)
65
#define SIMDJSON_IS_LSX 1
66
#define SIMDJSON_IS_LASX 1
// We can always run both
67
#elif defined(__loongarch_sx)
68
#define SIMDJSON_IS_LSX 1
69
70
// Adjust for runtime dispatching support.
71
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__NVCOMPILER)
72
#if __GNUC__ > 15 || (__GNUC__ == 15 && __GNUC_MINOR__ >= 0)
73
// We are ok, we will support runtime dispatch for LASX.
74
#else
75
// We disable runtime dispatch for LASX, which means that we will not be able to use LASX
76
// even if it is supported by the hardware.
77
// Loongson users should update to GCC 15 or better.
78
#define SIMDJSON_IMPLEMENTATION_LASX 0
79
#endif
80
#else
81
// We are not using GCC, so we assume that we can support runtime dispatch for LASX.
82
// https://godbolt.org/z/jcMnrjYhs
83
#define SIMDJSON_IMPLEMENTATION_LASX 0
84
#endif
85
86
87
88
#endif
89
#elif defined(__PPC64__) || defined(_M_PPC64)
90
#define SIMDJSON_IS_PPC64 1
91
#if defined(__ALTIVEC__)
92
#define SIMDJSON_IS_PPC64_VMX 1
93
#endif
// defined(__ALTIVEC__)
94
#else
95
#define SIMDJSON_IS_32BITS 1
96
97
#if defined(_M_IX86) || defined(__i386__)
98
#define SIMDJSON_IS_X86_32BITS 1
99
#elif defined(__arm__) || defined(_M_ARM)
100
#define SIMDJSON_IS_ARM_32BITS 1
101
#elif defined(__PPC__) || defined(_M_PPC)
102
#define SIMDJSON_IS_PPC_32BITS 1
103
#endif
104
105
#endif
// defined(__x86_64__) || defined(_M_AMD64)
106
#ifndef SIMDJSON_IS_32BITS
107
#define SIMDJSON_IS_32BITS 0
108
#endif
109
110
#if SIMDJSON_IS_32BITS
111
#ifndef SIMDJSON_NO_PORTABILITY_WARNING
112
// In the future, we should allow programmers
113
// to get warning.
114
#endif
// SIMDJSON_NO_PORTABILITY_WARNING
115
#endif
// SIMDJSON_IS_32BITS
116
117
#define SIMDJSON_CAT_IMPLEMENTATION_(a,...) a ## __VA_ARGS__
118
#define SIMDJSON_CAT(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
119
120
#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a,...) #a SIMDJSON_STRINGIFY(__VA_ARGS__)
121
#define SIMDJSON_STRINGIFY(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
122
123
// this is almost standard?
124
#undef SIMDJSON_STRINGIFY_IMPLEMENTATION_
125
#undef SIMDJSON_STRINGIFY
126
#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a) #a
127
#define SIMDJSON_STRINGIFY(a) SIMDJSON_STRINGIFY_IMPLEMENTATION_(a)
128
129
// Our fast kernels require 64-bit systems.
130
//
131
// On 32-bit x86, we lack 64-bit popcnt, lzcnt, blsr instructions.
132
// Furthermore, the number of SIMD registers is reduced.
133
//
134
// On 32-bit ARM, we would have smaller registers.
135
//
136
// The simdjson users should still have the fallback kernel. It is
137
// slower, but it should run everywhere.
138
139
//
140
// Enable valid runtime implementations, and select SIMDJSON_BUILTIN_IMPLEMENTATION
141
//
142
143
// We are going to use runtime dispatch.
144
#if defined(SIMDJSON_IS_X86_64) || defined(SIMDJSON_IS_LSX)
145
#ifdef __clang__
146
// clang does not have GCC push pop
147
// warning: clang attribute push can't be used within a namespace in clang up
148
// til 8.0 so SIMDJSON_TARGET_REGION and SIMDJSON_UNTARGET_REGION must be *outside* of a
149
// namespace.
150
#define SIMDJSON_TARGET_REGION(T) \
151
_Pragma(SIMDJSON_STRINGIFY( \
152
clang attribute push(__attribute__((target(T))), apply_to = function)))
153
#define SIMDJSON_UNTARGET_REGION _Pragma("clang attribute pop")
154
#elif defined(__GNUC__)
155
// GCC is easier
156
#define SIMDJSON_TARGET_REGION(T) \
157
_Pragma("GCC push_options") _Pragma(SIMDJSON_STRINGIFY(GCC target(T)))
158
#define SIMDJSON_UNTARGET_REGION _Pragma("GCC pop_options")
159
#endif
// clang then gcc
160
161
#endif
// defined(SIMDJSON_IS_X86_64) || defined(SIMDJSON_IS_LSX)
162
163
// Default target region macros don't do anything.
164
#ifndef SIMDJSON_TARGET_REGION
165
#define SIMDJSON_TARGET_REGION(T)
166
#define SIMDJSON_UNTARGET_REGION
167
#endif
168
169
// Is threading enabled?
170
#if defined(_REENTRANT) || defined(_MT)
171
#ifndef SIMDJSON_THREADS_ENABLED
172
#define SIMDJSON_THREADS_ENABLED
173
#endif
174
#endif
175
176
// workaround for large stack sizes under -O0.
177
// https://github.com/simdjson/simdjson/issues/691
178
#ifdef __APPLE__
179
#ifndef __OPTIMIZE__
180
// Apple systems have small stack sizes in secondary threads.
181
// Lack of compiler optimization may generate high stack usage.
182
// Users may want to disable threads for safety, but only when
183
// in debug mode which we detect by the fact that the __OPTIMIZE__
184
// macro is not defined.
185
#undef SIMDJSON_THREADS_ENABLED
186
#endif
187
#endif
188
189
190
#if defined(__clang__)
191
#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
192
#elif defined(__GNUC__)
193
#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
194
#else
195
#define SIMDJSON_NO_SANITIZE_UNDEFINED
196
#endif
197
198
#if defined(__clang__) || defined(__GNUC__)
199
#define simdjson_pure [[gnu::pure]]
200
#else
201
#define simdjson_pure
202
#endif
203
204
#if defined(__clang__) || defined(__GNUC__)
205
#if defined(__has_feature)
206
# if __has_feature(memory_sanitizer)
207
#define SIMDJSON_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
208
# endif
// if __has_feature(memory_sanitizer)
209
#endif
// defined(__has_feature)
210
#endif
211
// make sure it is defined as 'nothing' if it is unapplicable.
212
#ifndef SIMDJSON_NO_SANITIZE_MEMORY
213
#define SIMDJSON_NO_SANITIZE_MEMORY
214
#endif
215
216
#if SIMDJSON_VISUAL_STUDIO
217
// This is one case where we do not distinguish between
218
// regular visual studio and clang under visual studio.
219
// clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
220
#define simdjson_strcasecmp _stricmp
221
#define simdjson_strncasecmp _strnicmp
222
#else
223
// The strcasecmp, strncasecmp, and strcasestr functions do not work with multibyte strings (e.g. UTF-8).
224
// So they are only useful for ASCII in our context.
225
// https://www.gnu.org/software/libunistring/manual/libunistring.html#char-_002a-strings
226
#define simdjson_strcasecmp strcasecmp
227
#define simdjson_strncasecmp strncasecmp
228
#endif
229
230
#if (defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))) && !SIMDJSON_DEVELOPMENT_CHECKS
231
// If SIMDJSON_DEVELOPMENT_CHECKS is undefined or 0, we consider that we are in release mode.
232
// If NDEBUG is set, or __OPTIMIZE__ is set, or we are under MSVC in release mode,
233
// then do away with asserts and use __assume.
234
// We still recommend that our users set NDEBUG in release mode.
235
#if SIMDJSON_VISUAL_STUDIO
236
#define SIMDJSON_UNREACHABLE() __assume(0)
237
#define SIMDJSON_ASSUME(COND) __assume(COND)
238
#else
239
#define SIMDJSON_UNREACHABLE() __builtin_unreachable();
240
#define SIMDJSON_ASSUME(COND) do { if (!(COND)) __builtin_unreachable(); } while (0)
241
#endif
242
243
#else
// defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG)) && !SIMDJSON_DEVELOPMENT_CHECKS
244
// This should only ever be enabled in debug mode.
245
#define SIMDJSON_UNREACHABLE() assert(0);
246
#define SIMDJSON_ASSUME(COND) assert(COND)
247
248
#endif
249
250
251
252
#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__
253
#define SIMDJSON_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
254
#elif defined _WIN32
255
#define SIMDJSON_IS_BIG_ENDIAN 0
256
#else
257
#if defined(__APPLE__) || defined(__FreeBSD__)
258
#include <machine/endian.h>
259
#elif defined(sun) || defined(__sun)
260
#include <sys/byteorder.h>
261
#elif defined(__MVS__)
262
#include <sys/endian.h>
263
#else
264
#ifdef __has_include
265
#if __has_include(<endian.h>)
266
#include <endian.h>
267
#endif
//__has_include(<endian.h>)
268
#endif
//__has_include
269
#endif
270
#
271
#ifndef __BYTE_ORDER__
272
// safe choice
273
#define SIMDJSON_IS_BIG_ENDIAN 0
274
#endif
275
#
276
#ifndef __ORDER_LITTLE_ENDIAN__
277
// safe choice
278
#define SIMDJSON_IS_BIG_ENDIAN 0
279
#endif
280
#
281
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
282
#define SIMDJSON_IS_BIG_ENDIAN 0
283
#else
284
#define SIMDJSON_IS_BIG_ENDIAN 1
285
#endif
286
#endif
287
288
289
#endif
// SIMDJSON_PORTABILITY_H
include
simdjson
portability.h
Generated by
1.9.8