simdutf 7.3.5
Unicode at GB/s.
Loading...
Searching...
No Matches
portability.h
1#ifndef SIMDUTF_PORTABILITY_H
2#define SIMDUTF_PORTABILITY_H
3
4#include "simdutf/compiler_check.h"
5
6#include <cfloat>
7#include <cstddef>
8#include <cstdint>
9#include <cstdlib>
10#ifndef _WIN32
11 // strcasecmp, strncasecmp
12 #include <strings.h>
13#endif
14
15#if defined(__apple_build_version__)
16 #if __apple_build_version__ < 14000000
17 #define SIMDUTF_SPAN_DISABLED \
18 1 // apple-clang/13 doesn't support std::convertible_to
19 #endif
20#endif
21
22#if SIMDUTF_CPLUSPLUS20
23 #include <version>
24 #if __cpp_concepts >= 201907L && __cpp_lib_span >= 202002L && \
25 !defined(SIMDUTF_SPAN_DISABLED)
26 #define SIMDUTF_SPAN 1
27 #endif // __cpp_concepts >= 201907L && __cpp_lib_span >= 202002L
28 #if __cpp_lib_atomic_ref >= 201806L
29 #define SIMDUTF_ATOMIC_REF 1
30 #endif // __cpp_lib_atomic_ref
31 #if __has_cpp_attribute(maybe_unused) >= 201603L
32 #define SIMDUTF_MAYBE_UNUSED_AVAILABLE 1
33 #endif // __has_cpp_attribute(maybe_unused) >= 201603L
34#endif
35
41#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
42 #define SIMDUTF_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
43#elif defined(_WIN32)
44 #define SIMDUTF_IS_BIG_ENDIAN 0
45#else
46 #if defined(__APPLE__) || \
47 defined(__FreeBSD__) // defined __BYTE_ORDER__ && defined
48 // __ORDER_BIG_ENDIAN__
49 #include <machine/endian.h>
50 #elif defined(sun) || \
51 defined(__sun) // defined(__APPLE__) || defined(__FreeBSD__)
52 #include <sys/byteorder.h>
53 #else // defined(__APPLE__) || defined(__FreeBSD__)
54
55 #ifdef __has_include
56 #if __has_include(<endian.h>)
57 #include <endian.h>
58 #endif //__has_include(<endian.h>)
59 #endif //__has_include
60
61 #endif // defined(__APPLE__) || defined(__FreeBSD__)
62
63 #ifndef !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__)
64 #define SIMDUTF_IS_BIG_ENDIAN 0
65 #endif
66
67 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
68 #define SIMDUTF_IS_BIG_ENDIAN 0
69 #else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
70 #define SIMDUTF_IS_BIG_ENDIAN 1
71 #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
72
73#endif // defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__
74
79#ifdef _MSC_VER
80 #define SIMDUTF_VISUAL_STUDIO 1
91 #ifdef __clang__
92 // clang under visual studio
93 #define SIMDUTF_CLANG_VISUAL_STUDIO 1
94 #else
95 // just regular visual studio (best guess)
96 #define SIMDUTF_REGULAR_VISUAL_STUDIO 1
97 #endif // __clang__
98#endif // _MSC_VER
99
100#ifdef SIMDUTF_REGULAR_VISUAL_STUDIO
101 // https://en.wikipedia.org/wiki/C_alternative_tokens
102 // This header should have no effect, except maybe
103 // under Visual Studio.
104 #include <iso646.h>
105#endif
106
107#if (defined(__x86_64__) || defined(_M_AMD64)) && !defined(_M_ARM64EC)
108 #define SIMDUTF_IS_X86_64 1
109#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
110 #define SIMDUTF_IS_ARM64 1
111#elif defined(__PPC64__) || defined(_M_PPC64)
112 #if defined(__VEC__) && defined(__ALTIVEC__)
113 #define SIMDUTF_IS_PPC64 1
114 #endif
115#elif defined(__s390__)
116// s390 IBM system. Big endian.
117#elif (defined(__riscv) || defined(__riscv__)) && __riscv_xlen == 64
118 // RISC-V 64-bit
119 #define SIMDUTF_IS_RISCV64 1
120
121 // #if __riscv_v_intrinsic >= 1000000
122 // #define SIMDUTF_HAS_RVV_INTRINSICS 1
123 // #define SIMDUTF_HAS_RVV_TARGET_REGION 1
124 // #elif ...
125 // Check for special compiler versions that implement pre v1.0 intrinsics
126 #if __riscv_v_intrinsic >= 11000
127 #define SIMDUTF_HAS_RVV_INTRINSICS 1
128 #endif
129
130 #define SIMDUTF_HAS_ZVBB_INTRINSICS \
131 0 // there is currently no way to detect this
132
133 #if SIMDUTF_HAS_RVV_INTRINSICS && __riscv_vector && \
134 __riscv_v_min_vlen >= 128 && __riscv_v_elen >= 64
135 // RISC-V V extension
136 #define SIMDUTF_IS_RVV 1
137 #if SIMDUTF_HAS_ZVBB_INTRINSICS && __riscv_zvbb >= 1000000
138 // RISC-V Vector Basic Bit-manipulation
139 #define SIMDUTF_IS_ZVBB 1
140 #endif
141 #endif
142
143#elif defined(__loongarch_lp64)
144 #if defined(__loongarch_sx) && defined(__loongarch_asx)
145 #define SIMDUTF_IS_LSX 1
146 #define SIMDUTF_IS_LASX 1
147 #elif defined(__loongarch_sx)
148 #define SIMDUTF_IS_LSX 1
149 #endif
150#else
151 // The simdutf library is designed
152 // for 64-bit processors and it seems that you are not
153 // compiling for a known 64-bit platform. Please
154 // use a 64-bit target such as x64 or 64-bit ARM for best performance.
155 #define SIMDUTF_IS_32BITS 1
156
157 // We do not support 32-bit platforms, but it can be
158 // handy to identify them.
159 #if defined(_M_IX86) || defined(__i386__)
160 #define SIMDUTF_IS_X86_32BITS 1
161 #elif defined(__arm__) || defined(_M_ARM)
162 #define SIMDUTF_IS_ARM_32BITS 1
163 #elif defined(__PPC__) || defined(_M_PPC)
164 #define SIMDUTF_IS_PPC_32BITS 1
165 #endif
166
167#endif // defined(__x86_64__) || defined(_M_AMD64)
168
169#ifdef SIMDUTF_IS_32BITS
170 #ifndef SIMDUTF_NO_PORTABILITY_WARNING
171 // In the future, we may want to warn users of 32-bit systems that
172 // the simdutf does not support accelerated kernels for such systems.
173 #endif // SIMDUTF_NO_PORTABILITY_WARNING
174#endif // SIMDUTF_IS_32BITS
175
176// this is almost standard?
177#define SIMDUTF_STRINGIFY_IMPLEMENTATION_(a) #a
178#define SIMDUTF_STRINGIFY(a) SIMDUTF_STRINGIFY_IMPLEMENTATION_(a)
179
180// Our fast kernels require 64-bit systems.
181//
182// On 32-bit x86, we lack 64-bit popcnt, lzcnt, blsr instructions.
183// Furthermore, the number of SIMD registers is reduced.
184//
185// On 32-bit ARM, we would have smaller registers.
186//
187// The simdutf users should still have the fallback kernel. It is
188// slower, but it should run everywhere.
189
190//
191// Enable valid runtime implementations, and select
192// SIMDUTF_BUILTIN_IMPLEMENTATION
193//
194
195// We are going to use runtime dispatch.
196#ifdef SIMDUTF_IS_X86_64
197 #ifdef __clang__
198 // clang does not have GCC push pop
199 // warning: clang attribute push can't be used within a namespace in clang
200 // up til 8.0 so SIMDUTF_TARGET_REGION and SIMDUTF_UNTARGET_REGION must be
201 // *outside* of a namespace.
202 #define SIMDUTF_TARGET_REGION(T) \
203 _Pragma(SIMDUTF_STRINGIFY(clang attribute push( \
204 __attribute__((target(T))), apply_to = function)))
205 #define SIMDUTF_UNTARGET_REGION _Pragma("clang attribute pop")
206 #elif defined(__GNUC__)
207 // GCC is easier
208 #define SIMDUTF_TARGET_REGION(T) \
209 _Pragma("GCC push_options") _Pragma(SIMDUTF_STRINGIFY(GCC target(T)))
210 #define SIMDUTF_UNTARGET_REGION _Pragma("GCC pop_options")
211 #endif // clang then gcc
212
213#endif // x86
214
215// Default target region macros don't do anything.
216#ifndef SIMDUTF_TARGET_REGION
217 #define SIMDUTF_TARGET_REGION(T)
218 #define SIMDUTF_UNTARGET_REGION
219#endif
220
221// Is threading enabled?
222#if defined(_REENTRANT) || defined(_MT)
223 #ifndef SIMDUTF_THREADS_ENABLED
224 #define SIMDUTF_THREADS_ENABLED
225 #endif
226#endif
227
228// workaround for large stack sizes under -O0.
229// https://github.com/simdutf/simdutf/issues/691
230#ifdef __APPLE__
231 #ifndef __OPTIMIZE__
232 // Apple systems have small stack sizes in secondary threads.
233 // Lack of compiler optimization may generate high stack usage.
234 // Users may want to disable threads for safety, but only when
235 // in debug mode which we detect by the fact that the __OPTIMIZE__
236 // macro is not defined.
237 #undef SIMDUTF_THREADS_ENABLED
238 #endif
239#endif
240
241#ifdef SIMDUTF_VISUAL_STUDIO
242 // This is one case where we do not distinguish between
243 // regular visual studio and clang under visual studio.
244 // clang under Windows has _stricmp (like visual studio) but not strcasecmp
245 // (as clang normally has)
246 #define simdutf_strcasecmp _stricmp
247 #define simdutf_strncasecmp _strnicmp
248#else
249 // The strcasecmp, strncasecmp, and strcasestr functions do not work with
250 // multibyte strings (e.g. UTF-8). So they are only useful for ASCII in our
251 // context.
252 // https://www.gnu.org/software/libunistring/manual/libunistring.html#char-_002a-strings
253 #define simdutf_strcasecmp strcasecmp
254 #define simdutf_strncasecmp strncasecmp
255#endif
256
257#if defined(__GNUC__) && !defined(__clang__)
258 #if __GNUC__ >= 11
259 #define SIMDUTF_GCC11ORMORE 1
260 #endif // __GNUC__ >= 11
261#endif // defined(__GNUC__) && !defined(__clang__)
262
263#endif // SIMDUTF_PORTABILITY_H