From 68ef4593d67ca82425e2b5392ecc43997f0c06be Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Thu, 17 Apr 2025 13:55:44 +0100 Subject: [PATCH] Make libc easier to use. --- embed/build.sh | 2 +- sqlite3/libc/build.sh | 7 +- sqlite3/libc/libc.wasm | Bin 2075 -> 2199 bytes sqlite3/libc/libc.wat | 235 +++++++++++++++++++-------- sqlite3/{strings.c => libc/string.h} | 58 ++++++- sqlite3/main.c | 1 - util/sql3util/wasm/build.sh | 2 +- util/sql3util/wasm/main.c | 1 - vfs/tests/mptest/wasm/build.sh | 2 +- vfs/tests/mptest/wasm/main.c | 1 - vfs/tests/speedtest1/wasm/build.sh | 2 +- vfs/tests/speedtest1/wasm/main.c | 1 - 12 files changed, 232 insertions(+), 80 deletions(-) rename sqlite3/{strings.c => libc/string.h} (79%) diff --git a/embed/build.sh b/embed/build.sh index 117f8f1..88e12be 100755 --- a/embed/build.sh +++ b/embed/build.sh @@ -12,7 +12,7 @@ trap 'rm -f sqlite3.tmp' EXIT "$WASI_SDK/clang" --target=wasm32-wasi -std=c23 -g0 -O2 \ -Wall -Wextra -Wno-unused-parameter -Wno-unused-function \ -o sqlite3.wasm "$ROOT/sqlite3/main.c" \ - -I"$ROOT/sqlite3" \ + -I"$ROOT/sqlite3/libc" -I"$ROOT/sqlite3" \ -mexec-model=reactor \ -msimd128 -mmutable-globals -mmultivalue \ -mbulk-memory -mreference-types \ diff --git a/sqlite3/libc/build.sh b/sqlite3/libc/build.sh index 3d9aa3d..855a393 100755 --- a/sqlite3/libc/build.sh +++ b/sqlite3/libc/build.sh @@ -6,13 +6,14 @@ cd -P -- "$(dirname -- "$0")" ROOT=../../ BINARYEN="$ROOT/tools/binaryen/bin" WASI_SDK="$ROOT/tools/wasi-sdk/bin" -SRCS="${1:-../strings.c}" +SRCS="${1:-libc.c}" "../tools.sh" -trap 'rm -f libc.tmp' EXIT +trap 'rm -f libc.c libc.tmp' EXIT +echo '#include ' > libc.c "$WASI_SDK/clang" --target=wasm32-wasi -std=c23 -g0 -O2 \ - -o libc.wasm "$SRCS" \ + -o libc.wasm -I. "$SRCS" \ -mexec-model=reactor \ -msimd128 -mmutable-globals -mmultivalue \ -mbulk-memory -mreference-types \ diff --git a/sqlite3/libc/libc.wasm b/sqlite3/libc/libc.wasm index f3761564dbea085bf113264ce25596df95eab1da..995c28efdf41a68a282b7cfd0a1b088f7c183730 100755 GIT binary patch delta 285 zcmYk1F>b<85JY$9J2c;xot|RNTs3Kl6 z64&G*afUQRBuO)9meY)dwJ0MC<{5b}r1e_33@{MditdC_rdiy~sFeNZqBpLcx~=wC z`ge9^gkT6#LpE #include #include #include <__macro_PAGESIZE.h> +#include_next // the system string.h + +#ifdef __cplusplus +extern "C" { +#endif + #ifdef __wasm_bulk_memory__ +// Use the builtins if compiled with bulk memory operations. +// Clang will intrinsify using SIMD for small, constant N. +// For everything else, this helps inlining. + void *memset(void *dest, int c, size_t n) { return __builtin_memset(dest, c, n); } @@ -17,10 +30,19 @@ void *memmove(void *dest, const void *src, size_t n) { return __builtin_memmove(dest, src, n); } -#endif +#endif // __wasm_bulk_memory__ #ifdef __wasm_simd128__ +// SIMD versions of some string.h functions. +// +// These assume aligned v128_t reads can't fail, +// and so can't unaligned reads up to the last +// aligned address less than memory size. +// +// These also assume unaligned access is not painfully slow, +// but that bitmask extraction is slow on AArch64. + int memcmp(const void *v1, const void *v2, size_t n) { const v128_t *w1 = v1; const v128_t *w2 = v2; @@ -166,16 +188,34 @@ char *strchr(const char *s, int c) { return *(char *)r == (char)c ? r : NULL; } -#endif +#pragma push_macro("BITOP") #define BITOP(a, b, op) \ ((a)[(b) / (8 * sizeof(size_t))] op((size_t)1) \ << ((b) % (8 * sizeof(size_t)))) size_t strspn(const char *s, const char *c) { - if (!c[0]) return 0; - const char *const a = s; + + if (!c[0]) return 0; + if (!c[1]) { + const v128_t *const limit = + (v128_t *)(__builtin_wasm_memory_size(0) * PAGESIZE) - 1; + + const v128_t *w = (void *)s; + const v128_t wc = wasm_i8x16_splat(*c); + while (w <= limit) { + if (!wasm_i8x16_all_true(wasm_i8x16_eq(wasm_v128_load(w), wc))) { + break; + } + w++; + } + + s = (void *)w; + while (*s == *c) s++; + return s - a; + } + size_t byteset[32 / sizeof(size_t)] = {0}; for (; *c && BITOP(byteset, *(uint8_t *)c, |=); c++); @@ -194,4 +234,12 @@ size_t strcspn(const char *s, const char *c) { return s - a; } -#undef BITOP +#pragma pop_macro("BITOP") + +#endif // __wasm_simd128__ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _WASM_SIMD128_STRING_H \ No newline at end of file diff --git a/sqlite3/main.c b/sqlite3/main.c index 88da7e7..62eb1aa 100644 --- a/sqlite3/main.c +++ b/sqlite3/main.c @@ -1,4 +1,3 @@ -#include "strings.c" // Amalgamation #include "sqlite3.c" // Extensions diff --git a/util/sql3util/wasm/build.sh b/util/sql3util/wasm/build.sh index 53a00c5..e445a5b 100755 --- a/util/sql3util/wasm/build.sh +++ b/util/sql3util/wasm/build.sh @@ -12,7 +12,7 @@ trap 'rm -f sql3parse_table.tmp' EXIT "$WASI_SDK/clang" --target=wasm32-wasi -std=c23 -g0 -Oz \ -Wall -Wextra -Wno-unused-parameter -Wno-unused-function \ -o sql3parse_table.wasm main.c \ - -I"$ROOT/sqlite3" \ + -I"$ROOT/sqlite3/libc" -I"$ROOT/sqlite3" \ -mexec-model=reactor \ -msimd128 -mmutable-globals -mmultivalue \ -mbulk-memory -mreference-types \ diff --git a/util/sql3util/wasm/main.c b/util/sql3util/wasm/main.c index 3f04173..ede7edb 100644 --- a/util/sql3util/wasm/main.c +++ b/util/sql3util/wasm/main.c @@ -1,6 +1,5 @@ #include -#include "strings.c" #include "sql3parse_table.c" static_assert(offsetof(sql3table, name) == 0, "Unexpected offset"); diff --git a/vfs/tests/mptest/wasm/build.sh b/vfs/tests/mptest/wasm/build.sh index 18c2fd5..1596c60 100755 --- a/vfs/tests/mptest/wasm/build.sh +++ b/vfs/tests/mptest/wasm/build.sh @@ -9,7 +9,7 @@ WASI_SDK="$ROOT/tools/wasi-sdk/bin" "$WASI_SDK/clang" --target=wasm32-wasi -std=c23 -g0 -O2 \ -o mptest.wasm main.c \ - -I"$ROOT/sqlite3" \ + -I"$ROOT/sqlite3/libc" -I"$ROOT/sqlite3" \ -msimd128 -mmutable-globals -mmultivalue \ -mbulk-memory -mreference-types \ -mnontrapping-fptoint -msign-ext \ diff --git a/vfs/tests/mptest/wasm/main.c b/vfs/tests/mptest/wasm/main.c index ba70fc9..57d0ef7 100644 --- a/vfs/tests/mptest/wasm/main.c +++ b/vfs/tests/mptest/wasm/main.c @@ -3,7 +3,6 @@ // Use the default callback, not the Go one we patched in. #define sqliteBusyCallback sqliteDefaultBusyCallback -#include "strings.c" // Amalgamation #include "sqlite3.c" // VFS diff --git a/vfs/tests/speedtest1/wasm/build.sh b/vfs/tests/speedtest1/wasm/build.sh index ffcf157..0a22ee9 100755 --- a/vfs/tests/speedtest1/wasm/build.sh +++ b/vfs/tests/speedtest1/wasm/build.sh @@ -9,7 +9,7 @@ WASI_SDK="$ROOT/tools/wasi-sdk/bin" "$WASI_SDK/clang" --target=wasm32-wasi -std=c23 -g0 -O2 \ -o speedtest1.wasm main.c \ - -I"$ROOT/sqlite3" \ + -I"$ROOT/sqlite3/libc" -I"$ROOT/sqlite3" \ -msimd128 -mmutable-globals -mmultivalue \ -mbulk-memory -mreference-types \ -mnontrapping-fptoint -msign-ext \ diff --git a/vfs/tests/speedtest1/wasm/main.c b/vfs/tests/speedtest1/wasm/main.c index d191e8e..cc08d56 100644 --- a/vfs/tests/speedtest1/wasm/main.c +++ b/vfs/tests/speedtest1/wasm/main.c @@ -1,7 +1,6 @@ // Use the default callback, not the Go one we patched in. #define sqliteBusyCallback sqliteDefaultBusyCallback -#include "strings.c" // Amalgamation #include "sqlite3.c" // VFS