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
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
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