diff --git a/src/prebuilt/wasm2c_simd_source_declarations.cc b/src/prebuilt/wasm2c_simd_source_declarations.cc index c51139f58..942e3e48d 100644 --- a/src/prebuilt/wasm2c_simd_source_declarations.cc +++ b/src/prebuilt/wasm2c_simd_source_declarations.cc @@ -1,8 +1,12 @@ -const char* s_simd_source_declarations = R"w2c_template(#if defined(__GNUC__) && defined(__x86_64__) +const char* s_simd_source_declarations = R"w2c_template(#if WASM_RT_MEMCHECK_GUARD_PAGES +)w2c_template" +R"w2c_template(#ifdef __GNUC__ +)w2c_template" +R"w2c_template(#if defined(__x86_64__) )w2c_template" R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"x"(var)); )w2c_template" -R"w2c_template(#elif defined(__GNUC__) && defined(__aarch64__) +R"w2c_template(#elif defined(__aarch64__) )w2c_template" R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"w"(var)); )w2c_template" @@ -10,13 +14,21 @@ R"w2c_template(#elif defined(__s390x__) )w2c_template" R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"d"(var)); )w2c_template" -R"w2c_template(#else +R"w2c_template(#endif +)w2c_template" +R"w2c_template(#endif +)w2c_template" +R"w2c_template(#endif +)w2c_template" +R"w2c_template( +#ifndef SIMD_FORCE_READ )w2c_template" R"w2c_template(#define SIMD_FORCE_READ(var) )w2c_template" R"w2c_template(#endif )w2c_template" -R"w2c_template(// TODO: equivalent constraint for ARM and other architectures +R"w2c_template( +// TODO: equivalent constraint for ARM and other architectures )w2c_template" R"w2c_template( // The below SIMD operations copy to a local variable first as the diff --git a/src/prebuilt/wasm2c_source_declarations.cc b/src/prebuilt/wasm2c_source_declarations.cc index 965ace7e2..26c8e967e 100644 --- a/src/prebuilt/wasm2c_source_declarations.cc +++ b/src/prebuilt/wasm2c_source_declarations.cc @@ -285,8 +285,36 @@ R"w2c_template(#if WASM_RT_MEMCHECK_GUARD_PAGES )w2c_template" R"w2c_template(#define MEMCHECK_DEFAULT32(mem, a, t) WASM_RT_CHECK_BASE(mem); )w2c_template" +R"w2c_template( +// When using guard pages, reads have to be immediately consumed so that OOB +)w2c_template" +R"w2c_template(// trap checks are applied in the right place, and not optimized away. +)w2c_template" +R"w2c_template(#ifdef __GNUC__ +)w2c_template" +R"w2c_template(#define FORCE_READ_INT(var) __asm__("" ::"r"(var)); +)w2c_template" +R"w2c_template(// Clang on Mips requires "f" constraints on floats +)w2c_template" +R"w2c_template(// See https://github.com/llvm/llvm-project/issues/64241 +)w2c_template" +R"w2c_template(#if defined(__clang__) && \ +)w2c_template" +R"w2c_template( (defined(mips) || defined(__mips__) || defined(__mips)) +)w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT(var) __asm__("" ::"f"(var)); +)w2c_template" R"w2c_template(#else )w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); +)w2c_template" +R"w2c_template(#endif +)w2c_template" +R"w2c_template(#endif +)w2c_template" +R"w2c_template( +#else +)w2c_template" R"w2c_template(#define MEMCHECK_DEFAULT32(mem, a, t) \ )w2c_template" R"w2c_template( WASM_RT_CHECK_BASE(mem); \ @@ -307,29 +335,14 @@ R"w2c_template( WASM_RT_CHECK_BASE(mem); \ R"w2c_template( RANGE_CHECK(mem, a, sizeof(t)); )w2c_template" R"w2c_template( -#ifdef __GNUC__ -)w2c_template" -R"w2c_template(#define FORCE_READ_INT(var) __asm__("" ::"r"(var)); -)w2c_template" -R"w2c_template(// Clang on Mips requires "f" constraints on floats -)w2c_template" -R"w2c_template(// See https://github.com/llvm/llvm-project/issues/64241 -)w2c_template" -R"w2c_template(#if defined(__clang__) && \ -)w2c_template" -R"w2c_template( (defined(mips) || defined(__mips__) || defined(__mips)) -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT(var) __asm__("" ::"f"(var)); +#ifndef FORCE_READ_INT )w2c_template" -R"w2c_template(#else -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); +R"w2c_template(#define FORCE_READ_INT(var) )w2c_template" R"w2c_template(#endif )w2c_template" -R"w2c_template(#else -)w2c_template" -R"w2c_template(#define FORCE_READ_INT(var) +R"w2c_template( +#ifndef FORCE_READ_FLOAT )w2c_template" R"w2c_template(#define FORCE_READ_FLOAT(var) )w2c_template" diff --git a/src/template/wasm2c.declarations.c b/src/template/wasm2c.declarations.c index fce64b0d8..76d629db6 100644 --- a/src/template/wasm2c.declarations.c +++ b/src/template/wasm2c.declarations.c @@ -151,18 +151,9 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { // or it may do a slightly faster RANGE_CHECK. #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, a, t) WASM_RT_CHECK_BASE(mem); -#else -#define MEMCHECK_DEFAULT32(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ - TRAP(OOB); -#endif - -// MEMCHECK_GENERAL can be used for any memory -#define MEMCHECK_GENERAL(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - RANGE_CHECK(mem, a, sizeof(t)); +// When using guard pages, reads have to be immediately consumed so that OOB +// trap checks are applied in the right place, and not optimized away. #ifdef __GNUC__ #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats @@ -173,8 +164,25 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #else #define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); #endif +#endif + #else +#define MEMCHECK_DEFAULT32(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ + TRAP(OOB); +#endif + +// MEMCHECK_GENERAL can be used for any memory +#define MEMCHECK_GENERAL(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + RANGE_CHECK(mem, a, sizeof(t)); + +#ifndef FORCE_READ_INT #define FORCE_READ_INT(var) +#endif + +#ifndef FORCE_READ_FLOAT #define FORCE_READ_FLOAT(var) #endif diff --git a/src/template/wasm2c_simd.declarations.c b/src/template/wasm2c_simd.declarations.c index 01416c27b..3a5c3f544 100644 --- a/src/template/wasm2c_simd.declarations.c +++ b/src/template/wasm2c_simd.declarations.c @@ -1,12 +1,19 @@ -#if defined(__GNUC__) && defined(__x86_64__) +#if WASM_RT_MEMCHECK_GUARD_PAGES +#ifdef __GNUC__ +#if defined(__x86_64__) #define SIMD_FORCE_READ(var) __asm__("" ::"x"(var)); -#elif defined(__GNUC__) && defined(__aarch64__) +#elif defined(__aarch64__) #define SIMD_FORCE_READ(var) __asm__("" ::"w"(var)); #elif defined(__s390x__) #define SIMD_FORCE_READ(var) __asm__("" ::"d"(var)); -#else +#endif +#endif +#endif + +#ifndef SIMD_FORCE_READ #define SIMD_FORCE_READ(var) #endif + // TODO: equivalent constraint for ARM and other architectures // The below SIMD operations copy to a local variable first as the diff --git a/test/wasm2c/add.txt b/test/wasm2c/add.txt index 6a9b4f234..8b731032d 100644 --- a/test/wasm2c/add.txt +++ b/test/wasm2c/add.txt @@ -218,18 +218,9 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { // or it may do a slightly faster RANGE_CHECK. #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, a, t) WASM_RT_CHECK_BASE(mem); -#else -#define MEMCHECK_DEFAULT32(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ - TRAP(OOB); -#endif - -// MEMCHECK_GENERAL can be used for any memory -#define MEMCHECK_GENERAL(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - RANGE_CHECK(mem, a, sizeof(t)); +// When using guard pages, reads have to be immediately consumed so that OOB +// trap checks are applied in the right place, and not optimized away. #ifdef __GNUC__ #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats @@ -240,8 +231,25 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #else #define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); #endif +#endif + #else +#define MEMCHECK_DEFAULT32(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ + TRAP(OOB); +#endif + +// MEMCHECK_GENERAL can be used for any memory +#define MEMCHECK_GENERAL(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + RANGE_CHECK(mem, a, sizeof(t)); + +#ifndef FORCE_READ_INT #define FORCE_READ_INT(var) +#endif + +#ifndef FORCE_READ_FLOAT #define FORCE_READ_FLOAT(var) #endif diff --git a/test/wasm2c/check-imports.txt b/test/wasm2c/check-imports.txt index 0e48f43eb..9e731e0fb 100644 --- a/test/wasm2c/check-imports.txt +++ b/test/wasm2c/check-imports.txt @@ -243,18 +243,9 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { // or it may do a slightly faster RANGE_CHECK. #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, a, t) WASM_RT_CHECK_BASE(mem); -#else -#define MEMCHECK_DEFAULT32(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ - TRAP(OOB); -#endif - -// MEMCHECK_GENERAL can be used for any memory -#define MEMCHECK_GENERAL(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - RANGE_CHECK(mem, a, sizeof(t)); +// When using guard pages, reads have to be immediately consumed so that OOB +// trap checks are applied in the right place, and not optimized away. #ifdef __GNUC__ #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats @@ -265,8 +256,25 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #else #define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); #endif +#endif + #else +#define MEMCHECK_DEFAULT32(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ + TRAP(OOB); +#endif + +// MEMCHECK_GENERAL can be used for any memory +#define MEMCHECK_GENERAL(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + RANGE_CHECK(mem, a, sizeof(t)); + +#ifndef FORCE_READ_INT #define FORCE_READ_INT(var) +#endif + +#ifndef FORCE_READ_FLOAT #define FORCE_READ_FLOAT(var) #endif diff --git a/test/wasm2c/export-names.txt b/test/wasm2c/export-names.txt index 54ab285c2..8c1bfd286 100644 --- a/test/wasm2c/export-names.txt +++ b/test/wasm2c/export-names.txt @@ -243,18 +243,9 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { // or it may do a slightly faster RANGE_CHECK. #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, a, t) WASM_RT_CHECK_BASE(mem); -#else -#define MEMCHECK_DEFAULT32(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ - TRAP(OOB); -#endif - -// MEMCHECK_GENERAL can be used for any memory -#define MEMCHECK_GENERAL(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - RANGE_CHECK(mem, a, sizeof(t)); +// When using guard pages, reads have to be immediately consumed so that OOB +// trap checks are applied in the right place, and not optimized away. #ifdef __GNUC__ #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats @@ -265,8 +256,25 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #else #define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); #endif +#endif + #else +#define MEMCHECK_DEFAULT32(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ + TRAP(OOB); +#endif + +// MEMCHECK_GENERAL can be used for any memory +#define MEMCHECK_GENERAL(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + RANGE_CHECK(mem, a, sizeof(t)); + +#ifndef FORCE_READ_INT #define FORCE_READ_INT(var) +#endif + +#ifndef FORCE_READ_FLOAT #define FORCE_READ_FLOAT(var) #endif diff --git a/test/wasm2c/hello.txt b/test/wasm2c/hello.txt index 6a6274f30..56799781b 100644 --- a/test/wasm2c/hello.txt +++ b/test/wasm2c/hello.txt @@ -250,18 +250,9 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { // or it may do a slightly faster RANGE_CHECK. #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, a, t) WASM_RT_CHECK_BASE(mem); -#else -#define MEMCHECK_DEFAULT32(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ - TRAP(OOB); -#endif - -// MEMCHECK_GENERAL can be used for any memory -#define MEMCHECK_GENERAL(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - RANGE_CHECK(mem, a, sizeof(t)); +// When using guard pages, reads have to be immediately consumed so that OOB +// trap checks are applied in the right place, and not optimized away. #ifdef __GNUC__ #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats @@ -272,8 +263,25 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #else #define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); #endif +#endif + #else +#define MEMCHECK_DEFAULT32(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ + TRAP(OOB); +#endif + +// MEMCHECK_GENERAL can be used for any memory +#define MEMCHECK_GENERAL(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + RANGE_CHECK(mem, a, sizeof(t)); + +#ifndef FORCE_READ_INT #define FORCE_READ_INT(var) +#endif + +#ifndef FORCE_READ_FLOAT #define FORCE_READ_FLOAT(var) #endif diff --git a/test/wasm2c/minimal.txt b/test/wasm2c/minimal.txt index 1afe9fb32..6af4a2279 100644 --- a/test/wasm2c/minimal.txt +++ b/test/wasm2c/minimal.txt @@ -212,18 +212,9 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { // or it may do a slightly faster RANGE_CHECK. #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, a, t) WASM_RT_CHECK_BASE(mem); -#else -#define MEMCHECK_DEFAULT32(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ - TRAP(OOB); -#endif - -// MEMCHECK_GENERAL can be used for any memory -#define MEMCHECK_GENERAL(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - RANGE_CHECK(mem, a, sizeof(t)); +// When using guard pages, reads have to be immediately consumed so that OOB +// trap checks are applied in the right place, and not optimized away. #ifdef __GNUC__ #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats @@ -234,8 +225,25 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #else #define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); #endif +#endif + #else +#define MEMCHECK_DEFAULT32(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ + TRAP(OOB); +#endif + +// MEMCHECK_GENERAL can be used for any memory +#define MEMCHECK_GENERAL(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + RANGE_CHECK(mem, a, sizeof(t)); + +#ifndef FORCE_READ_INT #define FORCE_READ_INT(var) +#endif + +#ifndef FORCE_READ_FLOAT #define FORCE_READ_FLOAT(var) #endif diff --git a/test/wasm2c/tail-calls.txt b/test/wasm2c/tail-calls.txt index ea6dd154c..807c4acf6 100644 --- a/test/wasm2c/tail-calls.txt +++ b/test/wasm2c/tail-calls.txt @@ -242,18 +242,9 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { // or it may do a slightly faster RANGE_CHECK. #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, a, t) WASM_RT_CHECK_BASE(mem); -#else -#define MEMCHECK_DEFAULT32(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ - TRAP(OOB); -#endif - -// MEMCHECK_GENERAL can be used for any memory -#define MEMCHECK_GENERAL(mem, a, t) \ - WASM_RT_CHECK_BASE(mem); \ - RANGE_CHECK(mem, a, sizeof(t)); +// When using guard pages, reads have to be immediately consumed so that OOB +// trap checks are applied in the right place, and not optimized away. #ifdef __GNUC__ #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats @@ -264,8 +255,25 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #else #define FORCE_READ_FLOAT(var) __asm__("" ::"r"(var)); #endif +#endif + #else +#define MEMCHECK_DEFAULT32(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ + TRAP(OOB); +#endif + +// MEMCHECK_GENERAL can be used for any memory +#define MEMCHECK_GENERAL(mem, a, t) \ + WASM_RT_CHECK_BASE(mem); \ + RANGE_CHECK(mem, a, sizeof(t)); + +#ifndef FORCE_READ_INT #define FORCE_READ_INT(var) +#endif + +#ifndef FORCE_READ_FLOAT #define FORCE_READ_FLOAT(var) #endif