simdjson 4.2.1
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
15static_assert(CHAR_BIT == 8, "simdjson requires 8-bit bytes");
16
17
18// We are using size_t without namespace std:: throughout the project
19using 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 #if __riscv_v_intrinsic >= 11000
49 #define SIMDJSON_HAS_RVV_INTRINSICS 1
50 #endif
51
52 #define SIMDJSON_HAS_ZVBB_INTRINSICS \
53 0 // there is currently no way to detect this
54
55 #if SIMDJSON_HAS_RVV_INTRINSICS && __riscv_vector && \
56 __riscv_v_min_vlen >= 128 && __riscv_v_elen >= 64
57 // RISC-V V extension
58 #define SIMDJSON_IS_RVV 1
59 #if SIMDJSON_HAS_ZVBB_INTRINSICS && __riscv_zvbb >= 1000000
60 // RISC-V Vector Basic Bit-manipulation
61 #define SIMDJSON_IS_ZVBB 1
62 #endif
63 #endif
64#elif defined(__loongarch_lp64)
65#define SIMDJSON_IS_LOONGARCH64 1
66#elif defined(__PPC64__) || defined(_M_PPC64)
67#define SIMDJSON_IS_PPC64 1
68#if defined(__ALTIVEC__)
69#define SIMDJSON_IS_PPC64_VMX 1
70#endif // defined(__ALTIVEC__)
71#else
72#define SIMDJSON_IS_32BITS 1
73
74#if defined(_M_IX86) || defined(__i386__)
75#define SIMDJSON_IS_X86_32BITS 1
76#elif defined(__arm__) || defined(_M_ARM)
77#define SIMDJSON_IS_ARM_32BITS 1
78#elif defined(__PPC__) || defined(_M_PPC)
79#define SIMDJSON_IS_PPC_32BITS 1
80#endif
81
82#endif // defined(__x86_64__) || defined(_M_AMD64)
83#ifndef SIMDJSON_IS_32BITS
84#define SIMDJSON_IS_32BITS 0
85#endif
86
87#if SIMDJSON_IS_32BITS
88#ifndef SIMDJSON_NO_PORTABILITY_WARNING
89// In the future, we should allow programmers
90// to get warning.
91#endif // SIMDJSON_NO_PORTABILITY_WARNING
92#endif // SIMDJSON_IS_32BITS
93
94#define SIMDJSON_CAT_IMPLEMENTATION_(a,...) a ## __VA_ARGS__
95#define SIMDJSON_CAT(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
96
97#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a,...) #a SIMDJSON_STRINGIFY(__VA_ARGS__)
98#define SIMDJSON_STRINGIFY(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
99
100// this is almost standard?
101#undef SIMDJSON_STRINGIFY_IMPLEMENTATION_
102#undef SIMDJSON_STRINGIFY
103#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a) #a
104#define SIMDJSON_STRINGIFY(a) SIMDJSON_STRINGIFY_IMPLEMENTATION_(a)
105
106// Our fast kernels require 64-bit systems.
107//
108// On 32-bit x86, we lack 64-bit popcnt, lzcnt, blsr instructions.
109// Furthermore, the number of SIMD registers is reduced.
110//
111// On 32-bit ARM, we would have smaller registers.
112//
113// The simdjson users should still have the fallback kernel. It is
114// slower, but it should run everywhere.
115
116//
117// Enable valid runtime implementations, and select SIMDJSON_BUILTIN_IMPLEMENTATION
118//
119
120// We are going to use runtime dispatch.
121#if SIMDJSON_IS_X86_64
122#ifdef __clang__
123// clang does not have GCC push pop
124// warning: clang attribute push can't be used within a namespace in clang up
125// til 8.0 so SIMDJSON_TARGET_REGION and SIMDJSON_UNTARGET_REGION must be *outside* of a
126// namespace.
127#define SIMDJSON_TARGET_REGION(T) \
128 _Pragma(SIMDJSON_STRINGIFY( \
129 clang attribute push(__attribute__((target(T))), apply_to = function)))
130#define SIMDJSON_UNTARGET_REGION _Pragma("clang attribute pop")
131#elif defined(__GNUC__)
132// GCC is easier
133#define SIMDJSON_TARGET_REGION(T) \
134 _Pragma("GCC push_options") _Pragma(SIMDJSON_STRINGIFY(GCC target(T)))
135#define SIMDJSON_UNTARGET_REGION _Pragma("GCC pop_options")
136#endif // clang then gcc
137
138#endif // x86
139
140// Default target region macros don't do anything.
141#ifndef SIMDJSON_TARGET_REGION
142#define SIMDJSON_TARGET_REGION(T)
143#define SIMDJSON_UNTARGET_REGION
144#endif
145
146// Is threading enabled?
147#if defined(_REENTRANT) || defined(_MT)
148#ifndef SIMDJSON_THREADS_ENABLED
149#define SIMDJSON_THREADS_ENABLED
150#endif
151#endif
152
153// workaround for large stack sizes under -O0.
154// https://github.com/simdjson/simdjson/issues/691
155#ifdef __APPLE__
156#ifndef __OPTIMIZE__
157// Apple systems have small stack sizes in secondary threads.
158// Lack of compiler optimization may generate high stack usage.
159// Users may want to disable threads for safety, but only when
160// in debug mode which we detect by the fact that the __OPTIMIZE__
161// macro is not defined.
162#undef SIMDJSON_THREADS_ENABLED
163#endif
164#endif
165
166
167#if defined(__clang__)
168#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
169#elif defined(__GNUC__)
170#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
171#else
172#define SIMDJSON_NO_SANITIZE_UNDEFINED
173#endif
174
175#if defined(__clang__) || defined(__GNUC__)
176#define simdjson_pure [[gnu::pure]]
177#else
178#define simdjson_pure
179#endif
180
181#if defined(__clang__) || defined(__GNUC__)
182#if defined(__has_feature)
183# if __has_feature(memory_sanitizer)
184#define SIMDJSON_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
185# endif // if __has_feature(memory_sanitizer)
186#endif // defined(__has_feature)
187#endif
188// make sure it is defined as 'nothing' if it is unapplicable.
189#ifndef SIMDJSON_NO_SANITIZE_MEMORY
190#define SIMDJSON_NO_SANITIZE_MEMORY
191#endif
192
193#if SIMDJSON_VISUAL_STUDIO
194// This is one case where we do not distinguish between
195// regular visual studio and clang under visual studio.
196// clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
197#define simdjson_strcasecmp _stricmp
198#define simdjson_strncasecmp _strnicmp
199#else
200// The strcasecmp, strncasecmp, and strcasestr functions do not work with multibyte strings (e.g. UTF-8).
201// So they are only useful for ASCII in our context.
202// https://www.gnu.org/software/libunistring/manual/libunistring.html#char-_002a-strings
203#define simdjson_strcasecmp strcasecmp
204#define simdjson_strncasecmp strncasecmp
205#endif
206
207#if defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))
208// If NDEBUG is set, or __OPTIMIZE__ is set, or we are under MSVC in release mode,
209// then do away with asserts and use __assume.
210// We still recommend that our users set NDEBUG in release mode.
211#if SIMDJSON_VISUAL_STUDIO
212#define SIMDJSON_UNREACHABLE() __assume(0)
213#define SIMDJSON_ASSUME(COND) __assume(COND)
214#else
215#define SIMDJSON_UNREACHABLE() __builtin_unreachable();
216#define SIMDJSON_ASSUME(COND) do { if (!(COND)) __builtin_unreachable(); } while (0)
217#endif
218
219#else // defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))
220// This should only ever be enabled in debug mode.
221#define SIMDJSON_UNREACHABLE() assert(0);
222#define SIMDJSON_ASSUME(COND) assert(COND)
223
224#endif
225
226
227
228#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__
229#define SIMDJSON_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
230#elif defined _WIN32
231#define SIMDJSON_IS_BIG_ENDIAN 0
232#else
233#if defined(__APPLE__) || defined(__FreeBSD__)
234#include <machine/endian.h>
235#elif defined(sun) || defined(__sun)
236#include <sys/byteorder.h>
237#elif defined(__MVS__)
238#include <sys/endian.h>
239#else
240#ifdef __has_include
241#if __has_include(<endian.h>)
242#include <endian.h>
243#endif //__has_include(<endian.h>)
244#endif //__has_include
245#endif
246#
247#ifndef __BYTE_ORDER__
248// safe choice
249#define SIMDJSON_IS_BIG_ENDIAN 0
250#endif
251#
252#ifndef __ORDER_LITTLE_ENDIAN__
253// safe choice
254#define SIMDJSON_IS_BIG_ENDIAN 0
255#endif
256#
257#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
258#define SIMDJSON_IS_BIG_ENDIAN 0
259#else
260#define SIMDJSON_IS_BIG_ENDIAN 1
261#endif
262#endif
263
264
265#endif // SIMDJSON_PORTABILITY_H