wasm2c: missing guard force_read error with escape hatch
diff --git a/src/prebuilt/wasm2c_simd_source_declarations.cc b/src/prebuilt/wasm2c_simd_source_declarations.cc index 53e4b5e..b1cd5f7 100644 --- a/src/prebuilt/wasm2c_simd_source_declarations.cc +++ b/src/prebuilt/wasm2c_simd_source_declarations.cc
@@ -1,6 +1,10 @@ -const char* s_simd_source_declarations = R"w2c_template(#if WASM_RT_MEMCHECK_GUARD_PAGES +const char* s_simd_source_declarations = R"w2c_template(#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ )w2c_template" -R"w2c_template(#ifdef __GNUC__ +R"w2c_template( WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION +)w2c_template" +R"w2c_template(#define SIMD_FORCE_READ(var) +)w2c_template" +R"w2c_template(#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES )w2c_template" R"w2c_template(#if defined(__x86_64__) )w2c_template" @@ -10,27 +14,31 @@ )w2c_template" R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"w"(var)); )w2c_template" +R"w2c_template(#elif defined(__riscv) +)w2c_template" +R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"vr"(var)); +)w2c_template" R"w2c_template(#elif defined(__s390x__) )w2c_template" R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"d"(var)); )w2c_template" -R"w2c_template(#endif +R"w2c_template(#else +)w2c_template" +R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"f"(var)); )w2c_template" R"w2c_template(#endif )w2c_template" -R"w2c_template(#endif +R"w2c_template(#else )w2c_template" -R"w2c_template( -#ifndef SIMD_FORCE_READ +R"w2c_template(#error \ )w2c_template" -R"w2c_template(#define SIMD_FORCE_READ(var) +R"w2c_template( "Guard page mode for Wasm not supported on this platform because SIMD_FORCE_READ could not be instantiated." \ +)w2c_template" +R"w2c_template( "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" )w2c_template" R"w2c_template(#endif )w2c_template" 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 )w2c_template" R"w2c_template(// MEM_ADDR_MEMOP maybe segment pointers if WASM_RT_USE_SEGUE_FOR_THIS_MODULE is
diff --git a/src/prebuilt/wasm2c_source_declarations.cc b/src/prebuilt/wasm2c_source_declarations.cc index 67f33db..1da5d1d 100644 --- a/src/prebuilt/wasm2c_source_declarations.cc +++ b/src/prebuilt/wasm2c_source_declarations.cc
@@ -311,76 +311,8 @@ )w2c_template" R"w2c_template( 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( -#if defined(__i386__) || defined(__x86_64__) -)w2c_template" -R"w2c_template(#if defined(__SSE__) -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "x" -)w2c_template" -R"w2c_template(#else // No SSE, old x87 -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" -)w2c_template" -R"w2c_template(#endif -)w2c_template" -R"w2c_template(#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ -)w2c_template" -R"w2c_template( ((__ARM_FP & 0x4) != 0) -)w2c_template" -R"w2c_template(#ifdef __aarch64__ -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "w" -)w2c_template" R"w2c_template(#else )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "t" -)w2c_template" -R"w2c_template(#endif -)w2c_template" -R"w2c_template(#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) -)w2c_template" -R"w2c_template(// Clang before v18 uses hard floats which has a different constraint -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" -)w2c_template" -R"w2c_template(#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ -)w2c_template" -R"w2c_template( !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" -)w2c_template" -R"w2c_template(#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" -)w2c_template" -R"w2c_template(#elif defined(__s390__) || defined(__s390x__) -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" -)w2c_template" -R"w2c_template(#else -)w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "r" -)w2c_template" -R"w2c_template(#endif -)w2c_template" -R"w2c_template( -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); -)w2c_template" -R"w2c_template(#endif -)w2c_template" -R"w2c_template( -#else -)w2c_template" R"w2c_template(#if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE )w2c_template" R"w2c_template(#define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ @@ -415,16 +347,69 @@ R"w2c_template( RANGE_CHECK(mem, a, sizeof(t)); )w2c_template" R"w2c_template( -#ifndef FORCE_READ_INT +// 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. This is +)w2c_template" +R"w2c_template(// done using FORCE_READ_INT/FORCE_READ_FLOAT +)w2c_template" +R"w2c_template(#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ +)w2c_template" +R"w2c_template( WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION )w2c_template" R"w2c_template(#define FORCE_READ_INT(var) )w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT(var) +)w2c_template" +R"w2c_template(#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES +)w2c_template" +R"w2c_template(#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) +)w2c_template" +R"w2c_template( +#if defined(__x86_64__) || defined(_M_X64) +)w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "x" +)w2c_template" +R"w2c_template(#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) +)w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "w" +)w2c_template" +R"w2c_template(#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) +)w2c_template" +R"w2c_template(// Clang before v18 uses hard floats which has a different constraint +)w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +)w2c_template" +R"w2c_template(#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ +)w2c_template" +R"w2c_template( !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +)w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +)w2c_template" +R"w2c_template(#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +)w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +)w2c_template" +R"w2c_template(#elif defined(__s390__) || defined(__s390x__) +)w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +)w2c_template" +R"w2c_template(#else +)w2c_template" +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "r" +)w2c_template" R"w2c_template(#endif )w2c_template" R"w2c_template( -#ifndef FORCE_READ_FLOAT +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT(var) +R"w2c_template(#else +)w2c_template" +R"w2c_template(#error \ +)w2c_template" +R"w2c_template( "Guard page mode for Wasm not supported on this platform because FORCE_READ_INT/FORCE_READ_FLOAT could not be instantiated." \ +)w2c_template" +R"w2c_template( "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" )w2c_template" R"w2c_template(#endif )w2c_template"
diff --git a/src/template/wasm2c.declarations.c b/src/template/wasm2c.declarations.c index 6e5b92f..19a8e85 100644 --- a/src/template/wasm2c.declarations.c +++ b/src/template/wasm2c.declarations.c
@@ -165,42 +165,6 @@ #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ WASM_RT_CHECK_BASE(mem); - -// 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)); - -#if defined(__i386__) || defined(__x86_64__) -#if defined(__SSE__) -#define FORCE_READ_FLOAT_CONSTRAINT "x" -#else // No SSE, old x87 -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#endif -#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ - ((__ARM_FP & 0x4) != 0) -#ifdef __aarch64__ -#define FORCE_READ_FLOAT_CONSTRAINT "w" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "t" -#endif -#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) -// Clang before v18 uses hard floats which has a different constraint -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ - !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__s390__) || defined(__s390x__) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "r" -#endif - -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); -#endif - #else #if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ @@ -220,12 +184,39 @@ WASM_RT_CHECK_BASE(mem); \ RANGE_CHECK(mem, a, sizeof(t)); -#ifndef FORCE_READ_INT +// 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. This is +// done using FORCE_READ_INT/FORCE_READ_FLOAT +#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ + WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION #define FORCE_READ_INT(var) +#define FORCE_READ_FLOAT(var) +#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES +#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) + +#if defined(__x86_64__) || defined(_M_X64) +#define FORCE_READ_FLOAT_CONSTRAINT "x" +#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) +#define FORCE_READ_FLOAT_CONSTRAINT "w" +#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) +// Clang before v18 uses hard floats which has a different constraint +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ + !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__s390__) || defined(__s390x__) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#else +#define FORCE_READ_FLOAT_CONSTRAINT "r" #endif -#ifndef FORCE_READ_FLOAT -#define FORCE_READ_FLOAT(var) +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) +#else +#error \ + "Guard page mode for Wasm not supported on this platform because FORCE_READ_INT/FORCE_READ_FLOAT could not be instantiated." \ + "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" #endif static inline void load_data(u8* dest, const u8* src, size_t n) {
diff --git a/src/template/wasm2c_simd.declarations.c b/src/template/wasm2c_simd.declarations.c index 84bd54a..0de5500 100644 --- a/src/template/wasm2c_simd.declarations.c +++ b/src/template/wasm2c_simd.declarations.c
@@ -1,20 +1,23 @@ -#if WASM_RT_MEMCHECK_GUARD_PAGES -#ifdef __GNUC__ +#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ + WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION +#define SIMD_FORCE_READ(var) +#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES #if defined(__x86_64__) #define SIMD_FORCE_READ(var) __asm__("" ::"x"(var)); #elif defined(__aarch64__) #define SIMD_FORCE_READ(var) __asm__("" ::"w"(var)); +#elif defined(__riscv) +#define SIMD_FORCE_READ(var) __asm__("" ::"vr"(var)); #elif defined(__s390x__) #define SIMD_FORCE_READ(var) __asm__("" ::"d"(var)); +#else +#define SIMD_FORCE_READ(var) __asm__("" ::"f"(var)); #endif +#else +#error \ + "Guard page mode for Wasm not supported on this platform because SIMD_FORCE_READ could not be instantiated." \ + "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" #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 // MEM_ADDR_MEMOP maybe segment pointers if WASM_RT_USE_SEGUE_FOR_THIS_MODULE is
diff --git a/test/wasm2c/add.txt b/test/wasm2c/add.txt index ff36819..f55b5a3 100644 --- a/test/wasm2c/add.txt +++ b/test/wasm2c/add.txt
@@ -232,42 +232,6 @@ #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ WASM_RT_CHECK_BASE(mem); - -// 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)); - -#if defined(__i386__) || defined(__x86_64__) -#if defined(__SSE__) -#define FORCE_READ_FLOAT_CONSTRAINT "x" -#else // No SSE, old x87 -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#endif -#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ - ((__ARM_FP & 0x4) != 0) -#ifdef __aarch64__ -#define FORCE_READ_FLOAT_CONSTRAINT "w" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "t" -#endif -#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) -// Clang before v18 uses hard floats which has a different constraint -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ - !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__s390__) || defined(__s390x__) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "r" -#endif - -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); -#endif - #else #if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ @@ -287,12 +251,39 @@ WASM_RT_CHECK_BASE(mem); \ RANGE_CHECK(mem, a, sizeof(t)); -#ifndef FORCE_READ_INT +// 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. This is +// done using FORCE_READ_INT/FORCE_READ_FLOAT +#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ + WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION #define FORCE_READ_INT(var) +#define FORCE_READ_FLOAT(var) +#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES +#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) + +#if defined(__x86_64__) || defined(_M_X64) +#define FORCE_READ_FLOAT_CONSTRAINT "x" +#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) +#define FORCE_READ_FLOAT_CONSTRAINT "w" +#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) +// Clang before v18 uses hard floats which has a different constraint +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ + !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__s390__) || defined(__s390x__) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#else +#define FORCE_READ_FLOAT_CONSTRAINT "r" #endif -#ifndef FORCE_READ_FLOAT -#define FORCE_READ_FLOAT(var) +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) +#else +#error \ + "Guard page mode for Wasm not supported on this platform because FORCE_READ_INT/FORCE_READ_FLOAT could not be instantiated." \ + "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" #endif static inline void load_data(u8* dest, const u8* src, size_t n) {
diff --git a/test/wasm2c/check-imports.txt b/test/wasm2c/check-imports.txt index b1c5b95..eadb806 100644 --- a/test/wasm2c/check-imports.txt +++ b/test/wasm2c/check-imports.txt
@@ -257,42 +257,6 @@ #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ WASM_RT_CHECK_BASE(mem); - -// 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)); - -#if defined(__i386__) || defined(__x86_64__) -#if defined(__SSE__) -#define FORCE_READ_FLOAT_CONSTRAINT "x" -#else // No SSE, old x87 -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#endif -#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ - ((__ARM_FP & 0x4) != 0) -#ifdef __aarch64__ -#define FORCE_READ_FLOAT_CONSTRAINT "w" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "t" -#endif -#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) -// Clang before v18 uses hard floats which has a different constraint -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ - !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__s390__) || defined(__s390x__) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "r" -#endif - -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); -#endif - #else #if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ @@ -312,12 +276,39 @@ WASM_RT_CHECK_BASE(mem); \ RANGE_CHECK(mem, a, sizeof(t)); -#ifndef FORCE_READ_INT +// 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. This is +// done using FORCE_READ_INT/FORCE_READ_FLOAT +#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ + WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION #define FORCE_READ_INT(var) +#define FORCE_READ_FLOAT(var) +#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES +#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) + +#if defined(__x86_64__) || defined(_M_X64) +#define FORCE_READ_FLOAT_CONSTRAINT "x" +#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) +#define FORCE_READ_FLOAT_CONSTRAINT "w" +#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) +// Clang before v18 uses hard floats which has a different constraint +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ + !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__s390__) || defined(__s390x__) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#else +#define FORCE_READ_FLOAT_CONSTRAINT "r" #endif -#ifndef FORCE_READ_FLOAT -#define FORCE_READ_FLOAT(var) +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) +#else +#error \ + "Guard page mode for Wasm not supported on this platform because FORCE_READ_INT/FORCE_READ_FLOAT could not be instantiated." \ + "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" #endif static inline void load_data(u8* dest, const u8* src, size_t n) {
diff --git a/test/wasm2c/export-names.txt b/test/wasm2c/export-names.txt index dfce091..1b4a624 100644 --- a/test/wasm2c/export-names.txt +++ b/test/wasm2c/export-names.txt
@@ -257,42 +257,6 @@ #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ WASM_RT_CHECK_BASE(mem); - -// 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)); - -#if defined(__i386__) || defined(__x86_64__) -#if defined(__SSE__) -#define FORCE_READ_FLOAT_CONSTRAINT "x" -#else // No SSE, old x87 -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#endif -#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ - ((__ARM_FP & 0x4) != 0) -#ifdef __aarch64__ -#define FORCE_READ_FLOAT_CONSTRAINT "w" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "t" -#endif -#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) -// Clang before v18 uses hard floats which has a different constraint -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ - !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__s390__) || defined(__s390x__) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "r" -#endif - -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); -#endif - #else #if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ @@ -312,12 +276,39 @@ WASM_RT_CHECK_BASE(mem); \ RANGE_CHECK(mem, a, sizeof(t)); -#ifndef FORCE_READ_INT +// 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. This is +// done using FORCE_READ_INT/FORCE_READ_FLOAT +#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ + WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION #define FORCE_READ_INT(var) +#define FORCE_READ_FLOAT(var) +#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES +#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) + +#if defined(__x86_64__) || defined(_M_X64) +#define FORCE_READ_FLOAT_CONSTRAINT "x" +#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) +#define FORCE_READ_FLOAT_CONSTRAINT "w" +#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) +// Clang before v18 uses hard floats which has a different constraint +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ + !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__s390__) || defined(__s390x__) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#else +#define FORCE_READ_FLOAT_CONSTRAINT "r" #endif -#ifndef FORCE_READ_FLOAT -#define FORCE_READ_FLOAT(var) +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) +#else +#error \ + "Guard page mode for Wasm not supported on this platform because FORCE_READ_INT/FORCE_READ_FLOAT could not be instantiated." \ + "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" #endif static inline void load_data(u8* dest, const u8* src, size_t n) {
diff --git a/test/wasm2c/hello.txt b/test/wasm2c/hello.txt index ce5b697..d9c4302 100644 --- a/test/wasm2c/hello.txt +++ b/test/wasm2c/hello.txt
@@ -264,42 +264,6 @@ #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ WASM_RT_CHECK_BASE(mem); - -// 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)); - -#if defined(__i386__) || defined(__x86_64__) -#if defined(__SSE__) -#define FORCE_READ_FLOAT_CONSTRAINT "x" -#else // No SSE, old x87 -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#endif -#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ - ((__ARM_FP & 0x4) != 0) -#ifdef __aarch64__ -#define FORCE_READ_FLOAT_CONSTRAINT "w" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "t" -#endif -#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) -// Clang before v18 uses hard floats which has a different constraint -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ - !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__s390__) || defined(__s390x__) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "r" -#endif - -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); -#endif - #else #if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ @@ -319,12 +283,39 @@ WASM_RT_CHECK_BASE(mem); \ RANGE_CHECK(mem, a, sizeof(t)); -#ifndef FORCE_READ_INT +// 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. This is +// done using FORCE_READ_INT/FORCE_READ_FLOAT +#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ + WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION #define FORCE_READ_INT(var) +#define FORCE_READ_FLOAT(var) +#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES +#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) + +#if defined(__x86_64__) || defined(_M_X64) +#define FORCE_READ_FLOAT_CONSTRAINT "x" +#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) +#define FORCE_READ_FLOAT_CONSTRAINT "w" +#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) +// Clang before v18 uses hard floats which has a different constraint +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ + !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__s390__) || defined(__s390x__) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#else +#define FORCE_READ_FLOAT_CONSTRAINT "r" #endif -#ifndef FORCE_READ_FLOAT -#define FORCE_READ_FLOAT(var) +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) +#else +#error \ + "Guard page mode for Wasm not supported on this platform because FORCE_READ_INT/FORCE_READ_FLOAT could not be instantiated." \ + "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" #endif static inline void load_data(u8* dest, const u8* src, size_t n) {
diff --git a/test/wasm2c/minimal.txt b/test/wasm2c/minimal.txt index 437832b..373e86d 100644 --- a/test/wasm2c/minimal.txt +++ b/test/wasm2c/minimal.txt
@@ -226,42 +226,6 @@ #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ WASM_RT_CHECK_BASE(mem); - -// 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)); - -#if defined(__i386__) || defined(__x86_64__) -#if defined(__SSE__) -#define FORCE_READ_FLOAT_CONSTRAINT "x" -#else // No SSE, old x87 -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#endif -#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ - ((__ARM_FP & 0x4) != 0) -#ifdef __aarch64__ -#define FORCE_READ_FLOAT_CONSTRAINT "w" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "t" -#endif -#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) -// Clang before v18 uses hard floats which has a different constraint -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ - !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__s390__) || defined(__s390x__) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "r" -#endif - -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); -#endif - #else #if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ @@ -281,12 +245,39 @@ WASM_RT_CHECK_BASE(mem); \ RANGE_CHECK(mem, a, sizeof(t)); -#ifndef FORCE_READ_INT +// 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. This is +// done using FORCE_READ_INT/FORCE_READ_FLOAT +#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ + WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION #define FORCE_READ_INT(var) +#define FORCE_READ_FLOAT(var) +#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES +#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) + +#if defined(__x86_64__) || defined(_M_X64) +#define FORCE_READ_FLOAT_CONSTRAINT "x" +#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) +#define FORCE_READ_FLOAT_CONSTRAINT "w" +#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) +// Clang before v18 uses hard floats which has a different constraint +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ + !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__s390__) || defined(__s390x__) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#else +#define FORCE_READ_FLOAT_CONSTRAINT "r" #endif -#ifndef FORCE_READ_FLOAT -#define FORCE_READ_FLOAT(var) +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) +#else +#error \ + "Guard page mode for Wasm not supported on this platform because FORCE_READ_INT/FORCE_READ_FLOAT could not be instantiated." \ + "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" #endif static inline void load_data(u8* dest, const u8* src, size_t n) {
diff --git a/test/wasm2c/tail-calls.txt b/test/wasm2c/tail-calls.txt index b7e1f36..715e77c 100644 --- a/test/wasm2c/tail-calls.txt +++ b/test/wasm2c/tail-calls.txt
@@ -256,42 +256,6 @@ #if WASM_RT_MEMCHECK_GUARD_PAGES #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ WASM_RT_CHECK_BASE(mem); - -// 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)); - -#if defined(__i386__) || defined(__x86_64__) -#if defined(__SSE__) -#define FORCE_READ_FLOAT_CONSTRAINT "x" -#else // No SSE, old x87 -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#endif -#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ - ((__ARM_FP & 0x4) != 0) -#ifdef __aarch64__ -#define FORCE_READ_FLOAT_CONSTRAINT "w" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "t" -#endif -#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) -// Clang before v18 uses hard floats which has a different constraint -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ - !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#elif defined(__s390__) || defined(__s390x__) -#define FORCE_READ_FLOAT_CONSTRAINT "f" -#else -#define FORCE_READ_FLOAT_CONSTRAINT "r" -#endif - -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); -#endif - #else #if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE #define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ @@ -311,12 +275,39 @@ WASM_RT_CHECK_BASE(mem); \ RANGE_CHECK(mem, a, sizeof(t)); -#ifndef FORCE_READ_INT +// 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. This is +// done using FORCE_READ_INT/FORCE_READ_FLOAT +#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ + WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION #define FORCE_READ_INT(var) +#define FORCE_READ_FLOAT(var) +#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES +#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) + +#if defined(__x86_64__) || defined(_M_X64) +#define FORCE_READ_FLOAT_CONSTRAINT "x" +#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) +#define FORCE_READ_FLOAT_CONSTRAINT "w" +#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) +// Clang before v18 uses hard floats which has a different constraint +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ + !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#elif defined(__s390__) || defined(__s390x__) +#define FORCE_READ_FLOAT_CONSTRAINT "f" +#else +#define FORCE_READ_FLOAT_CONSTRAINT "r" #endif -#ifndef FORCE_READ_FLOAT -#define FORCE_READ_FLOAT(var) +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) +#else +#error \ + "Guard page mode for Wasm not supported on this platform because FORCE_READ_INT/FORCE_READ_FLOAT could not be instantiated." \ + "Either enable specify -DWASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION=1 during compilation or use -DWASM_RT_MEMCHECK_BOUNDS_CHECK=1 to use bounds check mode" #endif static inline void load_data(u8* dest, const u8* src, size_t n) {
diff --git a/wasm2c/wasm-rt.h b/wasm2c/wasm-rt.h index c6859f7..537c322 100644 --- a/wasm2c/wasm-rt.h +++ b/wasm2c/wasm-rt.h
@@ -133,6 +133,17 @@ #endif /** + * This macro, if defined, allows the embedder to permit elimination of unused + * memory loads. Note, this a non conformant configuration, i.e., this does not + * respect Wasm's specification, as Wasm requires all loads (even the eliminated + * loads to trap), whereas this configuration could eliminate an out-of-bound + * load, and thus allow the Wasm module to not trap. Use with caution. + */ +#ifndef WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION +#define WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION 0 +#endif + +/** * Set the range checking strategy for Wasm memories. * * GUARD_PAGES: memory accesses rely on unmapped pages/guard pages to trap @@ -142,11 +153,15 @@ * * This defaults to GUARD_PAGES as this is the fastest option, iff the * requirements of GUARD_PAGES --- 64-bit platforms, MMAP allocation strategy, - * no 64-bit memories --- are met. This falls back to BOUNDS otherwise. + * no 64-bit memories, and platforms with a supported FORCE_READ_STRATEGY + * described below --- are met. This falls back to BOUNDS otherwise. + * + * FORCE_READ_STRATEGY --- either the compiler should be a gcc/clang-like + * compiler or the embedder must permit a non-conforming setting (allow dead + * read elimination from linear memory) */ - -/** Check if Guard checks are supported */ -#if UINTPTR_MAX > 0xffffffff && WASM_RT_USE_MMAP +#if UINTPTR_MAX > 0xffffffff && WASM_RT_USE_MMAP && \ + (WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION || defined(__GNUC__)) #define WASM_RT_GUARD_PAGES_SUPPORTED 1 #else #define WASM_RT_GUARD_PAGES_SUPPORTED 0