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#ifndef _WIN32
10// strcasecmp, strncasecmp
11#include <strings.h>
12#endif
13
14#ifdef _MSC_VER
15#define SIMDJSON_VISUAL_STUDIO 1
16/**
17 * We want to differentiate carefully between
18 * clang under visual studio and regular visual
19 * studio.
20 *
21 * Under clang for Windows, we enable:
22 * * target pragmas so that part and only part of the
23 * code gets compiled for advanced instructions.
24 *
25 */
26#ifdef __clang__
27// clang under visual studio
28#define SIMDJSON_CLANG_VISUAL_STUDIO 1
29#else
30// just regular visual studio (best guess)
31#define SIMDJSON_REGULAR_VISUAL_STUDIO 1
32#endif // __clang__
33#endif // _MSC_VER
34
35#if SIMDJSON_REGULAR_VISUAL_STUDIO
36// https://en.wikipedia.org/wiki/C_alternative_tokens
37// This header should have no effect, except maybe
38// under Visual Studio.
39#include <iso646.h>
40#endif
41
42#if defined(__x86_64__) || defined(_M_AMD64)
43#define SIMDJSON_IS_X86_64 1
44#elif defined(__aarch64__) || defined(_M_ARM64)
45#define SIMDJSON_IS_ARM64 1
46#elif defined(__PPC64__) || defined(_M_PPC64)
47#define SIMDJSON_IS_PPC64 1
48#else
49#define SIMDJSON_IS_32BITS 1
50
51// We do not support 32-bit platforms, but it can be
52// handy to identify them.
53#if defined(_M_IX86) || defined(__i386__)
54#define SIMDJSON_IS_X86_32BITS 1
55#elif defined(__arm__) || defined(_M_ARM)
56#define SIMDJSON_IS_ARM_32BITS 1
57#elif defined(__PPC__) || defined(_M_PPC)
58#define SIMDJSON_IS_PPC_32BITS 1
59#endif
60
61#endif // defined(__x86_64__) || defined(_M_AMD64)
62#ifndef SIMDJSON_IS_32BITS
63#define SIMDJSON_IS_32BITS 0
64#endif
65
66#if SIMDJSON_IS_32BITS
67#ifndef SIMDJSON_NO_PORTABILITY_WARNING
68#pragma message("The simdjson library is designed \
69for 64-bit processors and it seems that you are not \
70compiling for a known 64-bit platform. All fast kernels \
71will be disabled and performance may be poor. Please \
72use a 64-bit target such as x64, 64-bit ARM or 64-bit PPC.")
73#endif // SIMDJSON_NO_PORTABILITY_WARNING
74#endif // SIMDJSON_IS_32BITS
75
76// this is almost standard?
77#undef SIMDJSON_STRINGIFY_IMPLEMENTATION_
78#undef SIMDJSON_STRINGIFY
79#define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a) #a
80#define SIMDJSON_STRINGIFY(a) SIMDJSON_STRINGIFY_IMPLEMENTATION_(a)
81
82// Our fast kernels require 64-bit systems.
83//
84// On 32-bit x86, we lack 64-bit popcnt, lzcnt, blsr instructions.
85// Furthermore, the number of SIMD registers is reduced.
86//
87// On 32-bit ARM, we would have smaller registers.
88//
89// The simdjson users should still have the fallback kernel. It is
90// slower, but it should run everywhere.
91
92//
93// Enable valid runtime implementations, and select SIMDJSON_BUILTIN_IMPLEMENTATION
94//
95
96// We are going to use runtime dispatch.
97#if SIMDJSON_IS_X86_64
98#ifdef __clang__
99// clang does not have GCC push pop
100// warning: clang attribute push can't be used within a namespace in clang up
101// til 8.0 so SIMDJSON_TARGET_REGION and SIMDJSON_UNTARGET_REGION must be *outside* of a
102// namespace.
103#define SIMDJSON_TARGET_REGION(T) \
104 _Pragma(SIMDJSON_STRINGIFY( \
105 clang attribute push(__attribute__((target(T))), apply_to = function)))
106#define SIMDJSON_UNTARGET_REGION _Pragma("clang attribute pop")
107#elif defined(__GNUC__)
108// GCC is easier
109#define SIMDJSON_TARGET_REGION(T) \
110 _Pragma("GCC push_options") _Pragma(SIMDJSON_STRINGIFY(GCC target(T)))
111#define SIMDJSON_UNTARGET_REGION _Pragma("GCC pop_options")
112#endif // clang then gcc
113
114#endif // x86
115
116// Default target region macros don't do anything.
117#ifndef SIMDJSON_TARGET_REGION
118#define SIMDJSON_TARGET_REGION(T)
119#define SIMDJSON_UNTARGET_REGION
120#endif
121
122// Is threading enabled?
123#if defined(_REENTRANT) || defined(_MT)
124#ifndef SIMDJSON_THREADS_ENABLED
125#define SIMDJSON_THREADS_ENABLED
126#endif
127#endif
128
129// workaround for large stack sizes under -O0.
130// https://github.com/simdjson/simdjson/issues/691
131#ifdef __APPLE__
132#ifndef __OPTIMIZE__
133// Apple systems have small stack sizes in secondary threads.
134// Lack of compiler optimization may generate high stack usage.
135// Users may want to disable threads for safety, but only when
136// in debug mode which we detect by the fact that the __OPTIMIZE__
137// macro is not defined.
138#undef SIMDJSON_THREADS_ENABLED
139#endif
140#endif
141
142
143#if defined(__clang__)
144#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
145#elif defined(__GNUC__)
146#define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
147#else
148#define SIMDJSON_NO_SANITIZE_UNDEFINED
149#endif
150
151#if SIMDJSON_VISUAL_STUDIO
152// This is one case where we do not distinguish between
153// regular visual studio and clang under visual studio.
154// clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
155#define simdjson_strcasecmp _stricmp
156#define simdjson_strncasecmp _strnicmp
157#else
158// The strcasecmp, strncasecmp, and strcasestr functions do not work with multibyte strings (e.g. UTF-8).
159// So they are only useful for ASCII in our context.
160// https://www.gnu.org/software/libunistring/manual/libunistring.html#char-_002a-strings
161#define simdjson_strcasecmp strcasecmp
162#define simdjson_strncasecmp strncasecmp
163#endif
164
165#ifdef NDEBUG
166
167#if SIMDJSON_VISUAL_STUDIO
168#define SIMDJSON_UNREACHABLE() __assume(0)
169#define SIMDJSON_ASSUME(COND) __assume(COND)
170#else
171#define SIMDJSON_UNREACHABLE() __builtin_unreachable();
172#define SIMDJSON_ASSUME(COND) do { if (!(COND)) __builtin_unreachable(); } while (0)
173#endif
174
175#else // NDEBUG
176
177#define SIMDJSON_UNREACHABLE() assert(0);
178#define SIMDJSON_ASSUME(COND) assert(COND)
179
180#endif
181
182#endif // SIMDJSON_PORTABILITY_H
183