diff --git a/src/prebuilt/wasm2c_simd_source_declarations.cc b/src/prebuilt/wasm2c_simd_source_declarations.cc index 53e4b5e3f..b1cd5f79c 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,25 +14,29 @@ R"w2c_template(#elif defined(__aarch64__) )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(#endif +R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"f"(var)); )w2c_template" R"w2c_template(#endif )w2c_template" -R"w2c_template( -#ifndef SIMD_FORCE_READ +R"w2c_template(#else )w2c_template" -R"w2c_template(#define SIMD_FORCE_READ(var) +R"w2c_template(#error \ )w2c_template" -R"w2c_template(#endif +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( -// TODO: equivalent constraint for ARM and other architectures +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( // 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 67f33db85..1da5d1d10 100644 --- a/src/prebuilt/wasm2c_source_declarations.cc +++ b/src/prebuilt/wasm2c_source_declarations.cc @@ -311,120 +311,105 @@ R"w2c_template(#define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ )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__) +R"w2c_template(#else )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "x" +R"w2c_template(#if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE )w2c_template" -R"w2c_template(#else // No SSE, old x87 +R"w2c_template(#define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +R"w2c_template( WASM_RT_CHECK_BASE(mem); \ )w2c_template" -R"w2c_template(#endif +R"w2c_template( if (UNLIKELY(a + (uint64_t)sizeof(t) > local_memory_size)) \ )w2c_template" -R"w2c_template(#elif (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) && \ +R"w2c_template( TRAP(OOB); )w2c_template" -R"w2c_template( ((__ARM_FP & 0x4) != 0) +R"w2c_template(#else )w2c_template" -R"w2c_template(#ifdef __aarch64__ +R"w2c_template(#define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "w" +R"w2c_template( WASM_RT_CHECK_BASE(mem); \ )w2c_template" -R"w2c_template(#else +R"w2c_template( if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "t" +R"w2c_template( TRAP(OOB); )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 +R"w2c_template(#endif )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +R"w2c_template( +// MEMCHECK_GENERAL can be used for any memory )w2c_template" -R"w2c_template(#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) || \ +R"w2c_template(#define MEMCHECK_GENERAL(mem, a, t) \ )w2c_template" -R"w2c_template( !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) +R"w2c_template( WASM_RT_CHECK_BASE(mem); \ )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +R"w2c_template( RANGE_CHECK(mem, a, sizeof(t)); )w2c_template" -R"w2c_template(#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) +R"w2c_template( +// When using guard pages, reads have to be immediately consumed so that OOB )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +R"w2c_template(// trap checks are applied in the right place, and not optimized away. This is )w2c_template" -R"w2c_template(#elif defined(__s390__) || defined(__s390x__) +R"w2c_template(// done using FORCE_READ_INT/FORCE_READ_FLOAT )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" +R"w2c_template(#if WASM_RT_MEMCHECK_BOUNDS_CHECK || \ )w2c_template" -R"w2c_template(#else +R"w2c_template( WASM_RT_NONCONFORMING_ALLOW_OOB_READ_ELIMINATION )w2c_template" -R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "r" +R"w2c_template(#define FORCE_READ_INT(var) )w2c_template" -R"w2c_template(#endif +R"w2c_template(#define FORCE_READ_FLOAT(var) )w2c_template" -R"w2c_template( -#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)); +R"w2c_template(#elif defined(__GNUC__) && WASM_RT_MEMCHECK_GUARD_PAGES )w2c_template" -R"w2c_template(#endif +R"w2c_template(#define FORCE_READ_INT(var) __asm__("" ::"r"(var)) )w2c_template" R"w2c_template( -#else +#if defined(__x86_64__) || defined(_M_X64) )w2c_template" -R"w2c_template(#if WASM_RT_USE_LOCAL_MEMORY_BASE_SIZE_FOR_THIS_MODULE +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "x" )w2c_template" -R"w2c_template(#define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ +R"w2c_template(#elif defined(__aarch64__) && defined(__ARM_FP) && ((__ARM_FP & 0x4) != 0) )w2c_template" -R"w2c_template( WASM_RT_CHECK_BASE(mem); \ +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "w" )w2c_template" -R"w2c_template( if (UNLIKELY(a + (uint64_t)sizeof(t) > local_memory_size)) \ +R"w2c_template(#elif defined(__mips__) && defined(__clang__) && !defined(__mips_soft_float) )w2c_template" -R"w2c_template( TRAP(OOB); +R"w2c_template(// Clang before v18 uses hard floats which has a different constraint )w2c_template" -R"w2c_template(#else +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" )w2c_template" -R"w2c_template(#define MEMCHECK_DEFAULT32(mem, local_memory_size, a, t) \ +R"w2c_template(#elif (defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)) && \ )w2c_template" -R"w2c_template( WASM_RT_CHECK_BASE(mem); \ +R"w2c_template( !(defined(_SOFT_FLOAT) || defined(__NO_FPRS__)) )w2c_template" -R"w2c_template( if (UNLIKELY(a + (uint64_t)sizeof(t) > mem->size)) \ +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" )w2c_template" -R"w2c_template( TRAP(OOB); +R"w2c_template(#elif defined(__riscv) && defined(__riscv_flen) && (__riscv_flen >= 32) )w2c_template" -R"w2c_template(#endif +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" )w2c_template" -R"w2c_template(#endif +R"w2c_template(#elif defined(__s390__) || defined(__s390x__) )w2c_template" -R"w2c_template( -// MEMCHECK_GENERAL can be used for any memory +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "f" )w2c_template" -R"w2c_template(#define MEMCHECK_GENERAL(mem, a, t) \ +R"w2c_template(#else )w2c_template" -R"w2c_template( WASM_RT_CHECK_BASE(mem); \ +R"w2c_template(#define FORCE_READ_FLOAT_CONSTRAINT "r" )w2c_template" -R"w2c_template( RANGE_CHECK(mem, a, sizeof(t)); +R"w2c_template(#endif )w2c_template" R"w2c_template( -#ifndef FORCE_READ_INT +#define FORCE_READ_FLOAT(var) __asm__("" ::FORCE_READ_FLOAT_CONSTRAINT(var)) )w2c_template" -R"w2c_template(#define FORCE_READ_INT(var) +R"w2c_template(#else )w2c_template" -R"w2c_template(#endif +R"w2c_template(#error \ )w2c_template" -R"w2c_template( -#ifndef FORCE_READ_FLOAT +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(#define FORCE_READ_FLOAT(var) +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 6e5b92fb2..19a8e8567 100644 --- a/src/template/wasm2c.declarations.c +++ b/src/template/wasm2c.declarations.c @@ -165,42 +165,6 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #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 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { 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 84bd54aa4..0de5500e2 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 ff36819b5..f55b5a3f1 100644 --- a/test/wasm2c/add.txt +++ b/test/wasm2c/add.txt @@ -232,42 +232,6 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #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 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { 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 b1c5b9558..eadb8066a 100644 --- a/test/wasm2c/check-imports.txt +++ b/test/wasm2c/check-imports.txt @@ -257,42 +257,6 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #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 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { 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 dfce091ab..1b4a62469 100644 --- a/test/wasm2c/export-names.txt +++ b/test/wasm2c/export-names.txt @@ -257,42 +257,6 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #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 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { 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 ce5b697cf..d9c430265 100644 --- a/test/wasm2c/hello.txt +++ b/test/wasm2c/hello.txt @@ -264,42 +264,6 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #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 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { 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 437832bf5..373e86de4 100644 --- a/test/wasm2c/minimal.txt +++ b/test/wasm2c/minimal.txt @@ -226,42 +226,6 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #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 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { 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 b7e1f3664..715e77ca6 100644 --- a/test/wasm2c/tail-calls.txt +++ b/test/wasm2c/tail-calls.txt @@ -256,42 +256,6 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { #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 @@ static inline uint64_t checked_add_u64(uint64_t a, uint64_t b) { 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 c6859f738..537c32234 100644 --- a/wasm2c/wasm-rt.h +++ b/wasm2c/wasm-rt.h @@ -132,6 +132,17 @@ extern "C" { #endif #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. * @@ -142,11 +153,15 @@ extern "C" { * * 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