qr_reader-native 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE-mruby.txt +22 -0
- data/LICENSE-spinel.txt +19 -0
- data/LICENSE.txt +21 -0
- data/README.md +61 -0
- data/ext/qr_reader_native/SPINEL_VERSION +1 -0
- data/ext/qr_reader_native/extconf.rb +8 -0
- data/ext/qr_reader_native/mruby/error.h +13 -0
- data/ext/qr_reader_native/mruby/internal.h +145 -0
- data/ext/qr_reader_native/mruby/string.h +22 -0
- data/ext/qr_reader_native/mruby.h +93 -0
- data/ext/qr_reader_native/mruby_shim.h +118 -0
- data/ext/qr_reader_native/qr_reader_native.c +13513 -0
- data/ext/qr_reader_native/qr_reader_native.h +29 -0
- data/ext/qr_reader_native/qr_reader_native_ext.c +598 -0
- data/ext/qr_reader_native/re_cased.h +71 -0
- data/ext/qr_reader_native/re_compile.c +5784 -0
- data/ext/qr_reader_native/re_ctype.h +3540 -0
- data/ext/qr_reader_native/re_exec.c +2190 -0
- data/ext/qr_reader_native/re_internal.h +671 -0
- data/ext/qr_reader_native/re_prop.h +4629 -0
- data/ext/qr_reader_native/re_spinel.c +363 -0
- data/ext/qr_reader_native/re_spinel.h +22 -0
- data/ext/qr_reader_native/re_spinel_utf8.inc +97 -0
- data/ext/qr_reader_native/re_utf8.c +156 -0
- data/ext/qr_reader_native/sp_alloc.c +1447 -0
- data/ext/qr_reader_native/sp_alloc.h +1196 -0
- data/ext/qr_reader_native/sp_argf.h +33 -0
- data/ext/qr_reader_native/sp_array.c +1052 -0
- data/ext/qr_reader_native/sp_array.h +456 -0
- data/ext/qr_reader_native/sp_bigint.c +5826 -0
- data/ext/qr_reader_native/sp_bigint.h +117 -0
- data/ext/qr_reader_native/sp_cold.c +5259 -0
- data/ext/qr_reader_native/sp_compat.h +402 -0
- data/ext/qr_reader_native/sp_core.c +818 -0
- data/ext/qr_reader_native/sp_core.h +56 -0
- data/ext/qr_reader_native/sp_crypto.c +877 -0
- data/ext/qr_reader_native/sp_crypto.h +169 -0
- data/ext/qr_reader_native/sp_dtoa.c +1533 -0
- data/ext/qr_reader_native/sp_dtoa.h +29 -0
- data/ext/qr_reader_native/sp_encoding_names.h +172 -0
- data/ext/qr_reader_native/sp_enum.h +86 -0
- data/ext/qr_reader_native/sp_exc.c +1185 -0
- data/ext/qr_reader_native/sp_exc.h +186 -0
- data/ext/qr_reader_native/sp_exc_ctx.h +56 -0
- data/ext/qr_reader_native/sp_fiber.c +889 -0
- data/ext/qr_reader_native/sp_fiber.h +162 -0
- data/ext/qr_reader_native/sp_fiber_ctx.h +84 -0
- data/ext/qr_reader_native/sp_format.c +695 -0
- data/ext/qr_reader_native/sp_format.h +83 -0
- data/ext/qr_reader_native/sp_gc.c +1793 -0
- data/ext/qr_reader_native/sp_gc.h +762 -0
- data/ext/qr_reader_native/sp_hash.c +131 -0
- data/ext/qr_reader_native/sp_hash.h +131 -0
- data/ext/qr_reader_native/sp_inspect.c +215 -0
- data/ext/qr_reader_native/sp_inspect.h +128 -0
- data/ext/qr_reader_native/sp_io.c +1676 -0
- data/ext/qr_reader_native/sp_io.h +272 -0
- data/ext/qr_reader_native/sp_iobuffer.c +1014 -0
- data/ext/qr_reader_native/sp_iobuffer.h +167 -0
- data/ext/qr_reader_native/sp_marshal.c +487 -0
- data/ext/qr_reader_native/sp_marshal.h +60 -0
- data/ext/qr_reader_native/sp_net.c +1029 -0
- data/ext/qr_reader_native/sp_net.h +205 -0
- data/ext/qr_reader_native/sp_pack.c +1254 -0
- data/ext/qr_reader_native/sp_poly_cold.c +1220 -0
- data/ext/qr_reader_native/sp_proc.c +410 -0
- data/ext/qr_reader_native/sp_proc.h +327 -0
- data/ext/qr_reader_native/sp_process.c +547 -0
- data/ext/qr_reader_native/sp_process_status.c +211 -0
- data/ext/qr_reader_native/sp_process_status.h +66 -0
- data/ext/qr_reader_native/sp_random.c +287 -0
- data/ext/qr_reader_native/sp_random.h +52 -0
- data/ext/qr_reader_native/sp_range.h +144 -0
- data/ext/qr_reader_native/sp_re.c +1379 -0
- data/ext/qr_reader_native/sp_re.h +186 -0
- data/ext/qr_reader_native/sp_re_names.h +59 -0
- data/ext/qr_reader_native/sp_sched.c +4044 -0
- data/ext/qr_reader_native/sp_sched.h +295 -0
- data/ext/qr_reader_native/sp_slab.c +1507 -0
- data/ext/qr_reader_native/sp_str.c +1462 -0
- data/ext/qr_reader_native/sp_str.h +306 -0
- data/ext/qr_reader_native/sp_str_crypt.c +23 -0
- data/ext/qr_reader_native/sp_string.c +92 -0
- data/ext/qr_reader_native/sp_string.h +253 -0
- data/ext/qr_reader_native/sp_system.c +78 -0
- data/ext/qr_reader_native/sp_system.h +18 -0
- data/ext/qr_reader_native/sp_time.c +860 -0
- data/ext/qr_reader_native/sp_time.h +100 -0
- data/ext/qr_reader_native/sp_types.h +292 -0
- data/ext/qr_reader_native/spinel_rt.h +19017 -0
- data/ext/qr_reader_native/unicase.c +399 -0
- data/ext/qr_reader_native/unicase.h +901 -0
- data/lib/qr_reader/native.rb +6 -0
- metadata +153 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
/* sp_compat.h -- the GNU C extensions the runtime and the generated C use,
|
|
2
|
+
* behind macros that fall back to standard C where a compiler lacks them.
|
|
3
|
+
*
|
|
4
|
+
* A compiler with the extension keeps the code it compiled before: every
|
|
5
|
+
* macro expands to the same builtin or attribute. One without it (an old or
|
|
6
|
+
* non-GNU toolchain for a small target) gets the fallback: a hint becomes
|
|
7
|
+
* nothing, a builtin becomes the standard (C23 <stdckdint.h>) or hand-written
|
|
8
|
+
* equivalent.
|
|
9
|
+
*
|
|
10
|
+
* Detection asks __has_builtin / __has_attribute / __has_include first; the
|
|
11
|
+
* GCC version is the last resort, for the GCCs that predate the __has_ forms.
|
|
12
|
+
*
|
|
13
|
+
* Defining SP_PORTABLE takes every fallback even where the extension exists,
|
|
14
|
+
* so a GCC or clang build exercises the code a plain C compiler would get.
|
|
15
|
+
* What no macro can express stays an extension under SP_PORTABLE too (the
|
|
16
|
+
* statement expressions and cleanup scopes the generated C is built from, and
|
|
17
|
+
* the rest listed at the end of this file).
|
|
18
|
+
*
|
|
19
|
+
* Included first by sp_types.h, the base header every runtime source and the
|
|
20
|
+
* generated translation unit see; it depends on nothing but <stdint.h>.
|
|
21
|
+
*/
|
|
22
|
+
#ifndef SP_COMPAT_H
|
|
23
|
+
#define SP_COMPAT_H
|
|
24
|
+
|
|
25
|
+
#include <stdint.h>
|
|
26
|
+
#include <stddef.h>
|
|
27
|
+
|
|
28
|
+
/* ---- detection ---- */
|
|
29
|
+
|
|
30
|
+
#if defined(__GNUC__) && !defined(__clang__)
|
|
31
|
+
# define SP_GNUC_PREREQ(maj, min) (__GNUC__ > (maj) || (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min)))
|
|
32
|
+
#else
|
|
33
|
+
# define SP_GNUC_PREREQ(maj, min) 0
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
#if defined(SP_PORTABLE)
|
|
37
|
+
# define SP_HAS_BUILTIN(x) 0
|
|
38
|
+
# define SP_HAS_ATTRIBUTE(x) 0
|
|
39
|
+
# define SP_GNU_OK 0
|
|
40
|
+
#else
|
|
41
|
+
# if defined(__has_builtin)
|
|
42
|
+
# define SP_HAS_BUILTIN(x) __has_builtin(x)
|
|
43
|
+
# else
|
|
44
|
+
# define SP_HAS_BUILTIN(x) 0
|
|
45
|
+
# endif
|
|
46
|
+
# if defined(__has_attribute)
|
|
47
|
+
# define SP_HAS_ATTRIBUTE(x) __has_attribute(x)
|
|
48
|
+
# else
|
|
49
|
+
# define SP_HAS_ATTRIBUTE(x) 0
|
|
50
|
+
# endif
|
|
51
|
+
/* the version fallback: a GCC before __has_builtin (10) / __has_attribute (5) */
|
|
52
|
+
# if defined(__GNUC__) || defined(__clang__)
|
|
53
|
+
# define SP_GNU_OK 1
|
|
54
|
+
# else
|
|
55
|
+
# define SP_GNU_OK 0
|
|
56
|
+
# endif
|
|
57
|
+
#endif
|
|
58
|
+
|
|
59
|
+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
|
60
|
+
# define SP_C11 1
|
|
61
|
+
#else
|
|
62
|
+
# define SP_C11 0
|
|
63
|
+
#endif
|
|
64
|
+
|
|
65
|
+
/* ---- hints: nothing when absent ---- */
|
|
66
|
+
|
|
67
|
+
#if SP_HAS_BUILTIN(__builtin_expect) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 0))
|
|
68
|
+
# define SP_LIKELY(x) __builtin_expect(!!(x), 1)
|
|
69
|
+
# define SP_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
|
70
|
+
/* the value itself, unnormalized: what a site wrote as __builtin_expect(x, v) */
|
|
71
|
+
# define SP_EXPECT(x, v) __builtin_expect((x), (v))
|
|
72
|
+
#else
|
|
73
|
+
# define SP_LIKELY(x) (x)
|
|
74
|
+
# define SP_UNLIKELY(x) (x)
|
|
75
|
+
# define SP_EXPECT(x, v) (x)
|
|
76
|
+
#endif
|
|
77
|
+
|
|
78
|
+
#if SP_HAS_ATTRIBUTE(cold) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(4, 3))
|
|
79
|
+
# define SP_COLD __attribute__((cold))
|
|
80
|
+
#else
|
|
81
|
+
# define SP_COLD
|
|
82
|
+
#endif
|
|
83
|
+
|
|
84
|
+
#if SP_HAS_ATTRIBUTE(noinline) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 1))
|
|
85
|
+
# define SP_NOINLINE __attribute__((noinline))
|
|
86
|
+
#else
|
|
87
|
+
# define SP_NOINLINE
|
|
88
|
+
#endif
|
|
89
|
+
|
|
90
|
+
/* `inline` stays: only the forcing is a hint. The generated C spells it
|
|
91
|
+
`inline SP_ALWAYS_INLINE`, so src/csplit.c still sees the `inline` word. */
|
|
92
|
+
#if SP_HAS_ATTRIBUTE(always_inline) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 1))
|
|
93
|
+
# define SP_ALWAYS_INLINE __attribute__((always_inline))
|
|
94
|
+
#else
|
|
95
|
+
# define SP_ALWAYS_INLINE
|
|
96
|
+
#endif
|
|
97
|
+
#define SP_INLINE inline SP_ALWAYS_INLINE
|
|
98
|
+
|
|
99
|
+
#if SP_HAS_ATTRIBUTE(unused) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 0))
|
|
100
|
+
# define SP_UNUSED __attribute__((unused))
|
|
101
|
+
#else
|
|
102
|
+
# define SP_UNUSED
|
|
103
|
+
#endif
|
|
104
|
+
|
|
105
|
+
#if SP_HAS_ATTRIBUTE(format) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 0))
|
|
106
|
+
# define SP_PRINTF_FORMAT(fmt, first) __attribute__((format(printf, fmt, first)))
|
|
107
|
+
#else
|
|
108
|
+
# define SP_PRINTF_FORMAT(fmt, first)
|
|
109
|
+
#endif
|
|
110
|
+
|
|
111
|
+
/* A tail call the compiler must make. Ruby does not promise one, so the plain
|
|
112
|
+
call a compiler without it makes means the same. Written before `return`. */
|
|
113
|
+
#if SP_HAS_ATTRIBUTE(musttail)
|
|
114
|
+
# define SP_MUSTTAIL __attribute__((musttail))
|
|
115
|
+
#else
|
|
116
|
+
# define SP_MUSTTAIL
|
|
117
|
+
#endif
|
|
118
|
+
|
|
119
|
+
/* noreturn is a hint to the optimizer and the warnings; C11 has its own */
|
|
120
|
+
#if SP_HAS_ATTRIBUTE(noreturn) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(2, 5))
|
|
121
|
+
# define SP_NORETURN __attribute__((noreturn))
|
|
122
|
+
#elif SP_C11
|
|
123
|
+
# define SP_NORETURN _Noreturn
|
|
124
|
+
#else
|
|
125
|
+
# define SP_NORETURN
|
|
126
|
+
#endif
|
|
127
|
+
|
|
128
|
+
#if SP_HAS_BUILTIN(__builtin_unreachable) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(4, 5))
|
|
129
|
+
# define SP_UNREACHABLE() __builtin_unreachable()
|
|
130
|
+
#else
|
|
131
|
+
# include <stdlib.h>
|
|
132
|
+
# define SP_UNREACHABLE() abort()
|
|
133
|
+
#endif
|
|
134
|
+
|
|
135
|
+
#if SP_HAS_BUILTIN(__builtin_prefetch) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 1))
|
|
136
|
+
# define SP_PREFETCH(p) __builtin_prefetch(p)
|
|
137
|
+
#else
|
|
138
|
+
# define SP_PREFETCH(p) ((void)(p))
|
|
139
|
+
#endif
|
|
140
|
+
|
|
141
|
+
/* Is `x` a constant the compiler can see? No means the general path, which
|
|
142
|
+
is always correct. */
|
|
143
|
+
#if SP_HAS_BUILTIN(__builtin_constant_p) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 1))
|
|
144
|
+
# define SP_CONSTANT_P(x) __builtin_constant_p(x)
|
|
145
|
+
#else
|
|
146
|
+
# define SP_CONSTANT_P(x) 0
|
|
147
|
+
#endif
|
|
148
|
+
|
|
149
|
+
/* The pause a spin-wait loop takes between polls. */
|
|
150
|
+
#if !defined(SP_PORTABLE) && (defined(__x86_64__) || defined(__i386__)) && \
|
|
151
|
+
(SP_HAS_BUILTIN(__builtin_ia32_pause) || SP_GNU_OK)
|
|
152
|
+
# define SP_CPU_RELAX() __builtin_ia32_pause()
|
|
153
|
+
#elif !defined(SP_PORTABLE) && (defined(__aarch64__) || defined(__arm__)) && SP_GNU_OK
|
|
154
|
+
# define SP_CPU_RELAX() __asm__ __volatile__("yield" ::: "memory")
|
|
155
|
+
#else
|
|
156
|
+
# define SP_CPU_RELAX() ((void)0)
|
|
157
|
+
#endif
|
|
158
|
+
|
|
159
|
+
/* ---- attributes with a meaning: no silent fallback ---- */
|
|
160
|
+
|
|
161
|
+
/* Run before main. There is no standard spelling; a compiler without it
|
|
162
|
+
leaves the hook unrun, so it is kept even under SP_PORTABLE (the
|
|
163
|
+
generated program would otherwise start with its hooks missing). */
|
|
164
|
+
#if SP_HAS_ATTRIBUTE(constructor) || defined(__GNUC__) || defined(__clang__)
|
|
165
|
+
# define SP_CONSTRUCTOR __attribute__((constructor))
|
|
166
|
+
# define SP_DESTRUCTOR __attribute__((destructor))
|
|
167
|
+
#else
|
|
168
|
+
# error "spinel: the runtime needs __attribute__((constructor)) (see sp_compat.h)"
|
|
169
|
+
#endif
|
|
170
|
+
|
|
171
|
+
/* An optional symbol that is NULL when nothing defines it. Without it the
|
|
172
|
+
feature that probes the symbol is compiled out (SP_HAVE_WEAK is 0). */
|
|
173
|
+
#if SP_HAS_ATTRIBUTE(weak) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 0))
|
|
174
|
+
# define SP_WEAK __attribute__((weak))
|
|
175
|
+
# define SP_HAVE_WEAK 1
|
|
176
|
+
#else
|
|
177
|
+
# define SP_WEAK
|
|
178
|
+
# define SP_HAVE_WEAK 0
|
|
179
|
+
#endif
|
|
180
|
+
|
|
181
|
+
/* Run `fn(&var)` when `var` goes out of scope, by any exit. The GC root and
|
|
182
|
+
regexp frame guards pop themselves this way; nothing standard does it, so
|
|
183
|
+
it is kept under SP_PORTABLE and a compiler without it cannot build the
|
|
184
|
+
generated C (the generator would have to emit every pop itself). */
|
|
185
|
+
#if SP_HAS_ATTRIBUTE(cleanup) || defined(__GNUC__) || defined(__clang__)
|
|
186
|
+
# define SP_CLEANUP(fn) __attribute__((cleanup(fn)))
|
|
187
|
+
#else
|
|
188
|
+
# error "spinel: the runtime needs __attribute__((cleanup)) (see sp_compat.h)"
|
|
189
|
+
#endif
|
|
190
|
+
|
|
191
|
+
/* ---- thread-local storage ---- */
|
|
192
|
+
|
|
193
|
+
#if !defined(SP_PORTABLE) && (defined(__GNUC__) || defined(__clang__))
|
|
194
|
+
# define SP_THREAD_LOCAL __thread
|
|
195
|
+
#elif SP_C11 && !defined(__STDC_NO_THREADS__)
|
|
196
|
+
# define SP_THREAD_LOCAL _Thread_local
|
|
197
|
+
#else
|
|
198
|
+
# define SP_THREAD_LOCAL /* no TLS: only the single-threaded build works */
|
|
199
|
+
# define SP_NO_THREAD_LOCAL 1
|
|
200
|
+
#endif
|
|
201
|
+
|
|
202
|
+
/* ---- overflow-checked arithmetic ----
|
|
203
|
+
The builtin first, then C23's <stdckdint.h>, then a range check by hand.
|
|
204
|
+
Named by operand width (intptr_t, which sp_int is, and uint64_t): the
|
|
205
|
+
builtins are type-generic, the hand-written checks cannot be. Each
|
|
206
|
+
answers nonzero on overflow and stores the wrapped result. */
|
|
207
|
+
|
|
208
|
+
#if (SP_HAS_BUILTIN(__builtin_add_overflow) && SP_HAS_BUILTIN(__builtin_sub_overflow) && \
|
|
209
|
+
SP_HAS_BUILTIN(__builtin_mul_overflow)) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(5, 0))
|
|
210
|
+
# define SP_CKD_BUILTIN 1
|
|
211
|
+
#elif !defined(SP_PORTABLE) && defined(__has_include)
|
|
212
|
+
# if __has_include(<stdckdint.h>)
|
|
213
|
+
# include <stdckdint.h>
|
|
214
|
+
# define SP_CKD_STDC 1
|
|
215
|
+
# endif
|
|
216
|
+
#endif
|
|
217
|
+
|
|
218
|
+
#if defined(SP_CKD_BUILTIN)
|
|
219
|
+
/* the builtin in place, as the call sites wrote it before */
|
|
220
|
+
# define sp_ckd_add_iptr(a, b, r) __builtin_add_overflow(a, b, r)
|
|
221
|
+
# define sp_ckd_sub_iptr(a, b, r) __builtin_sub_overflow(a, b, r)
|
|
222
|
+
# define sp_ckd_mul_iptr(a, b, r) __builtin_mul_overflow(a, b, r)
|
|
223
|
+
# define sp_ckd_add_u64(a, b, r) __builtin_add_overflow(a, b, r)
|
|
224
|
+
# define sp_ckd_mul_u64(a, b, r) __builtin_mul_overflow(a, b, r)
|
|
225
|
+
#elif defined(SP_CKD_STDC)
|
|
226
|
+
# define sp_ckd_add_iptr(a, b, r) ckd_add(r, (intptr_t)(a), (intptr_t)(b))
|
|
227
|
+
# define sp_ckd_sub_iptr(a, b, r) ckd_sub(r, (intptr_t)(a), (intptr_t)(b))
|
|
228
|
+
# define sp_ckd_mul_iptr(a, b, r) ckd_mul(r, (intptr_t)(a), (intptr_t)(b))
|
|
229
|
+
# define sp_ckd_add_u64(a, b, r) ckd_add(r, (uint64_t)(a), (uint64_t)(b))
|
|
230
|
+
# define sp_ckd_mul_u64(a, b, r) ckd_mul(r, (uint64_t)(a), (uint64_t)(b))
|
|
231
|
+
#else
|
|
232
|
+
/* unsigned arithmetic wraps, and the sign bits of the operands against the
|
|
233
|
+
result say whether the signed sum did */
|
|
234
|
+
static inline int sp_ckd_add_iptr(intptr_t a, intptr_t b, intptr_t *r) {
|
|
235
|
+
uintptr_t x = (uintptr_t)a, y = (uintptr_t)b, z = x + y;
|
|
236
|
+
*r = (intptr_t)z;
|
|
237
|
+
return (((x ^ z) & (y ^ z)) >> (sizeof(intptr_t) * 8 - 1)) != 0;
|
|
238
|
+
}
|
|
239
|
+
static inline int sp_ckd_sub_iptr(intptr_t a, intptr_t b, intptr_t *r) {
|
|
240
|
+
uintptr_t x = (uintptr_t)a, y = (uintptr_t)b, z = x - y;
|
|
241
|
+
*r = (intptr_t)z;
|
|
242
|
+
return (((x ^ z) & (~y ^ z)) >> (sizeof(intptr_t) * 8 - 1)) != 0;
|
|
243
|
+
}
|
|
244
|
+
/* the bounds are checked before multiplying: no wider type is portable */
|
|
245
|
+
static inline int sp_ckd_mul_iptr(intptr_t a, intptr_t b, intptr_t *r) {
|
|
246
|
+
int ovf;
|
|
247
|
+
if (a > 0) ovf = b > 0 ? a > INTPTR_MAX / b : b < INTPTR_MIN / a;
|
|
248
|
+
else if (a < 0) ovf = b > 0 ? a < INTPTR_MIN / b : (b < 0 && (a == INTPTR_MIN || b == INTPTR_MIN || -a > INTPTR_MAX / -b));
|
|
249
|
+
else ovf = 0;
|
|
250
|
+
*r = (intptr_t)((uintptr_t)a * (uintptr_t)b);
|
|
251
|
+
return ovf;
|
|
252
|
+
}
|
|
253
|
+
static inline int sp_ckd_add_u64(uint64_t a, uint64_t b, uint64_t *r) {
|
|
254
|
+
*r = a + b;
|
|
255
|
+
return *r < a;
|
|
256
|
+
}
|
|
257
|
+
static inline int sp_ckd_mul_u64(uint64_t a, uint64_t b, uint64_t *r) {
|
|
258
|
+
*r = a * b;
|
|
259
|
+
return a != 0 && *r / a != b;
|
|
260
|
+
}
|
|
261
|
+
#endif
|
|
262
|
+
|
|
263
|
+
/* ---- bit counting (64-bit operands; clz/ctz of 0 is undefined, as the
|
|
264
|
+
builtins leave it) ---- */
|
|
265
|
+
|
|
266
|
+
#if SP_HAS_BUILTIN(__builtin_clzll) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 4))
|
|
267
|
+
# define SP_CLZ64(x) __builtin_clzll((unsigned long long)(x))
|
|
268
|
+
#else
|
|
269
|
+
static inline int sp_clz64_fallback(uint64_t x) {
|
|
270
|
+
int n = 0;
|
|
271
|
+
if (!(x >> 32)) { n += 32; x <<= 32; }
|
|
272
|
+
if (!(x >> 48)) { n += 16; x <<= 16; }
|
|
273
|
+
if (!(x >> 56)) { n += 8; x <<= 8; }
|
|
274
|
+
if (!(x >> 60)) { n += 4; x <<= 4; }
|
|
275
|
+
if (!(x >> 62)) { n += 2; x <<= 2; }
|
|
276
|
+
if (!(x >> 63)) { n += 1; }
|
|
277
|
+
return n;
|
|
278
|
+
}
|
|
279
|
+
# define SP_CLZ64(x) sp_clz64_fallback((uint64_t)(x))
|
|
280
|
+
#endif
|
|
281
|
+
|
|
282
|
+
#if SP_HAS_BUILTIN(__builtin_ctzll) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 4))
|
|
283
|
+
# define SP_CTZ64(x) __builtin_ctzll((unsigned long long)(x))
|
|
284
|
+
#else
|
|
285
|
+
static inline int sp_ctz64_fallback(uint64_t x) {
|
|
286
|
+
int n = 0;
|
|
287
|
+
if (!(x & 0xffffffffu)) { n += 32; x >>= 32; }
|
|
288
|
+
if (!(x & 0xffffu)) { n += 16; x >>= 16; }
|
|
289
|
+
if (!(x & 0xffu)) { n += 8; x >>= 8; }
|
|
290
|
+
if (!(x & 0xfu)) { n += 4; x >>= 4; }
|
|
291
|
+
if (!(x & 0x3u)) { n += 2; x >>= 2; }
|
|
292
|
+
if (!(x & 0x1u)) { n += 1; }
|
|
293
|
+
return n;
|
|
294
|
+
}
|
|
295
|
+
# define SP_CTZ64(x) sp_ctz64_fallback((uint64_t)(x))
|
|
296
|
+
#endif
|
|
297
|
+
|
|
298
|
+
#if SP_HAS_BUILTIN(__builtin_popcountll) || (!defined(SP_PORTABLE) && SP_GNUC_PREREQ(3, 4))
|
|
299
|
+
# define SP_POPCOUNT64(x) __builtin_popcountll((unsigned long long)(x))
|
|
300
|
+
#else
|
|
301
|
+
static inline int sp_popcount64_fallback(uint64_t x) {
|
|
302
|
+
x = x - ((x >> 1) & 0x5555555555555555ULL);
|
|
303
|
+
x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL);
|
|
304
|
+
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
|
|
305
|
+
return (int)((x * 0x0101010101010101ULL) >> 56);
|
|
306
|
+
}
|
|
307
|
+
# define SP_POPCOUNT64(x) sp_popcount64_fallback((uint64_t)(x))
|
|
308
|
+
#endif
|
|
309
|
+
|
|
310
|
+
/* ---- 128-bit integers ---- */
|
|
311
|
+
|
|
312
|
+
#if !defined(SP_PORTABLE) && defined(__SIZEOF_INT128__)
|
|
313
|
+
# define SP_HAVE_INT128 1
|
|
314
|
+
__extension__ typedef __int128 sp_int128;
|
|
315
|
+
__extension__ typedef unsigned __int128 sp_uint128;
|
|
316
|
+
#else
|
|
317
|
+
# define SP_HAVE_INT128 0
|
|
318
|
+
#endif
|
|
319
|
+
|
|
320
|
+
/* ---- atomics ----
|
|
321
|
+
The __atomic builtins take a plain object, which C11's <stdatomic.h> does
|
|
322
|
+
not (it wants an _Atomic one), so the fallback is the plain operation:
|
|
323
|
+
right for the single-threaded runtime, which is all a compiler without
|
|
324
|
+
them can build. The memory-order arguments are dropped with the builtin,
|
|
325
|
+
so the __ATOMIC_* names need not exist there. */
|
|
326
|
+
|
|
327
|
+
/* The threaded runtime needs them for its correctness, not its speed, so
|
|
328
|
+
SP_PORTABLE keeps them there: its fallback is the single-threaded one. */
|
|
329
|
+
#if defined(SP_PORTABLE) && !defined(SP_THREADS)
|
|
330
|
+
# define SP_ATOMICS_BUILTIN 0
|
|
331
|
+
#elif SP_HAS_BUILTIN(__atomic_load_n) || SP_GNUC_PREREQ(4, 7) || defined(__clang__) || \
|
|
332
|
+
(defined(SP_THREADS) && defined(__GNUC__))
|
|
333
|
+
# define SP_ATOMICS_BUILTIN 1
|
|
334
|
+
#else
|
|
335
|
+
# define SP_ATOMICS_BUILTIN 0
|
|
336
|
+
#endif
|
|
337
|
+
|
|
338
|
+
#if SP_ATOMICS_BUILTIN
|
|
339
|
+
# define SP_HAVE_ATOMICS 1
|
|
340
|
+
# define SP_ATOMIC_LOAD(p, mo) __atomic_load_n(p, mo)
|
|
341
|
+
# define SP_ATOMIC_STORE(p, v, mo) __atomic_store_n(p, v, mo)
|
|
342
|
+
# define SP_ATOMIC_EXCHANGE(p, v, mo) __atomic_exchange_n(p, v, mo)
|
|
343
|
+
# define SP_ATOMIC_FETCH_ADD(p, v, mo) __atomic_fetch_add(p, v, mo)
|
|
344
|
+
# define SP_ATOMIC_FETCH_SUB(p, v, mo) __atomic_fetch_sub(p, v, mo)
|
|
345
|
+
# define SP_ATOMIC_FETCH_OR(p, v, mo) __atomic_fetch_or(p, v, mo)
|
|
346
|
+
# define SP_ATOMIC_FETCH_AND(p, v, mo) __atomic_fetch_and(p, v, mo)
|
|
347
|
+
# define SP_ATOMIC_ADD_FETCH(p, v, mo) __atomic_add_fetch(p, v, mo)
|
|
348
|
+
# define SP_ATOMIC_SUB_FETCH(p, v, mo) __atomic_sub_fetch(p, v, mo)
|
|
349
|
+
# define SP_ATOMIC_CAS(p, exp, des, weak, smo, fmo) __atomic_compare_exchange_n(p, exp, des, weak, smo, fmo)
|
|
350
|
+
# define SP_ATOMIC_FENCE(mo) __atomic_thread_fence(mo)
|
|
351
|
+
#else
|
|
352
|
+
# define SP_HAVE_ATOMICS 0
|
|
353
|
+
# if defined(SP_THREADS)
|
|
354
|
+
# error "spinel: the threaded runtime (SP_THREADS) needs the __atomic builtins"
|
|
355
|
+
# endif
|
|
356
|
+
# define SP_ATOMIC_LOAD(p, mo) (*(p))
|
|
357
|
+
# define SP_ATOMIC_STORE(p, v, mo) ((void)(*(p) = (v)))
|
|
358
|
+
/* the old value, without a temporary of the object's type: swap through
|
|
359
|
+
the arithmetic that restores it (integers and pointers alike) */
|
|
360
|
+
# define SP_ATOMIC_EXCHANGE(p, v, mo) sp_atomic_xchg_fallback((void *)(p), sizeof *(p), (uint64_t)(uintptr_t)(v))
|
|
361
|
+
# define SP_ATOMIC_FETCH_ADD(p, v, mo) ((*(p) += (v)) - (v))
|
|
362
|
+
# define SP_ATOMIC_FETCH_SUB(p, v, mo) ((*(p) -= (v)) + (v))
|
|
363
|
+
# define SP_ATOMIC_FETCH_OR(p, v, mo) sp_atomic_or_fallback((uint64_t *)(p), (uint64_t)(v))
|
|
364
|
+
# define SP_ATOMIC_FETCH_AND(p, v, mo) sp_atomic_and_fallback((uint64_t *)(p), (uint64_t)(v))
|
|
365
|
+
# define SP_ATOMIC_ADD_FETCH(p, v, mo) (*(p) += (v))
|
|
366
|
+
# define SP_ATOMIC_SUB_FETCH(p, v, mo) (*(p) -= (v))
|
|
367
|
+
# define SP_ATOMIC_CAS(p, exp, des, weak, smo, fmo) \
|
|
368
|
+
(*(p) == *(exp) ? (*(p) = (des), 1) : (*(exp) = *(p), 0))
|
|
369
|
+
# define SP_ATOMIC_FENCE(mo) ((void)0)
|
|
370
|
+
#endif
|
|
371
|
+
|
|
372
|
+
#if !SP_HAVE_ATOMICS
|
|
373
|
+
#include <string.h>
|
|
374
|
+
/* exchange on an object of 1, 2, 4 or 8 bytes, answering the old value in
|
|
375
|
+
the low bytes of a uint64_t that the caller's cast narrows back */
|
|
376
|
+
static inline uint64_t sp_atomic_xchg_fallback(void *p, size_t n, uint64_t v) {
|
|
377
|
+
uint64_t old = 0;
|
|
378
|
+
switch (n) {
|
|
379
|
+
case 1: { uint8_t o = *(uint8_t *)p; *(uint8_t *)p = (uint8_t)v; old = o; break; }
|
|
380
|
+
case 2: { uint16_t o = *(uint16_t *)p; *(uint16_t *)p = (uint16_t)v; old = o; break; }
|
|
381
|
+
case 4: { uint32_t o = *(uint32_t *)p; *(uint32_t *)p = (uint32_t)v; old = o; break; }
|
|
382
|
+
default: { uint64_t o; memcpy(&o, p, 8); memcpy(p, &v, 8); old = o; break; }
|
|
383
|
+
}
|
|
384
|
+
return old;
|
|
385
|
+
}
|
|
386
|
+
static inline uint64_t sp_atomic_or_fallback(uint64_t *p, uint64_t v) { uint64_t o = *p; *p = o | v; return o; }
|
|
387
|
+
static inline uint64_t sp_atomic_and_fallback(uint64_t *p, uint64_t v) { uint64_t o = *p; *p = o & v; return o; }
|
|
388
|
+
#endif
|
|
389
|
+
|
|
390
|
+
/* ---- what stays an extension under SP_PORTABLE ----
|
|
391
|
+
No macro can stand in for these; a plain C compiler needs the generator
|
|
392
|
+
(or the runtime) to write them differently:
|
|
393
|
+
- statement expressions `({ ... })`, the shape of most generated C;
|
|
394
|
+
- __attribute__((cleanup)) on the GC root and regexp frame guards
|
|
395
|
+
(SP_GC_SAVE / SP_GC_ROOT*, sp_re_frame), which pop at every scope exit;
|
|
396
|
+
- __COUNTER__ in the guard names, and __typeof__ in a few spliced temps;
|
|
397
|
+
- SP_FLOAT_NIL_CONST, a NaN with a payload as a constant expression;
|
|
398
|
+
- __attribute__((constructor)) hooks (SP_CONSTRUCTOR above);
|
|
399
|
+
- an asm label (`__asm__("sym")`) on --ffi declarations;
|
|
400
|
+
- the fiber context switch, written in asm per architecture. */
|
|
401
|
+
|
|
402
|
+
#endif /* SP_COMPAT_H */
|