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