From 4151fe0500933d270a5434e395b208bdd241db0b Mon Sep 17 00:00:00 2001 From: Shravan Narayan Date: Fri, 15 Dec 2023 16:54:48 -0600 Subject: [PATCH] wasm2c: Add macro and tests to disable Wasm's force_read --- .github/workflows/build.yml | 6 +++--- .../wasm2c_simd_source_declarations.cc | 4 +++- src/prebuilt/wasm2c_source_declarations.cc | 2 +- src/template/wasm2c.declarations.c | 2 +- src/template/wasm2c_simd.declarations.c | 3 ++- test/run-tests.py | 21 ++++++++++--------- test/wasm2c/add.txt | 2 +- test/wasm2c/check-imports.txt | 2 +- test/wasm2c/export-names.txt | 2 +- test/wasm2c/hello.txt | 2 +- test/wasm2c/minimal.txt | 2 +- test/wasm2c/tail-calls.txt | 2 +- wasm2c/wasm-rt.h | 10 +++++++++ 13 files changed, 37 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0852b2a32..4eb90e4dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -172,7 +172,7 @@ jobs: runs-on: ubuntu-latest env: USE_NINJA: "1" - WASM2C_CFLAGS: "-DWASM_RT_USE_MMAP=1 -DWASM_RT_SKIP_SIGNAL_RECOVERY=1 -DWASM_RT_NONCONFORMING_UNCHECKED_STACK_EXHAUSTION=1 -DWASM2C_TEST_EMBEDDER_SIGNAL_HANDLING" + WASM2C_CFLAGS: "-DWASM_RT_USE_MMAP=1 -DWASM_RT_SKIP_SIGNAL_RECOVERY=1 -DWASM_RT_NONCONFORMING_UNCHECKED_STACK_EXHAUSTION=1 -DWASM2C_NONCONFORMING_LOAD_ELISION=1 -DWASM2C_TEST_EMBEDDER_SIGNAL_HANDLING" steps: - uses: actions/setup-python@v1 with: @@ -182,5 +182,5 @@ jobs: submodules: true - run: sudo apt-get install ninja-build - run: make clang-debug - - name: tests (wasm2c tests excluding memory64) - run: ./test/run-tests.py *wasm2c* --exclude-dir memory64 + - name: tests (wasm2c tests excluding memory64 and unobserved read elimination) + run: ./test/run-tests.py *wasm2c* --exclude memory64 --exclude address-overflow.txt --exclude address.txt --exclude address0.txt --exclude address1.txt --exclude traps.txt --exclude traps0.txt --exclude simd_address.txt diff --git a/src/prebuilt/wasm2c_simd_source_declarations.cc b/src/prebuilt/wasm2c_simd_source_declarations.cc index 07425377a..97a7a7ecb 100644 --- a/src/prebuilt/wasm2c_simd_source_declarations.cc +++ b/src/prebuilt/wasm2c_simd_source_declarations.cc @@ -1,4 +1,6 @@ -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 defined(__GNUC__) && defined(__x86_64__) && \ +)w2c_template" +R"w2c_template( !WASM2C_NONCONFORMING_LOAD_ELISION )w2c_template" R"w2c_template(#define SIMD_FORCE_READ(var) __asm__("" ::"x"(var)); )w2c_template" diff --git a/src/prebuilt/wasm2c_source_declarations.cc b/src/prebuilt/wasm2c_source_declarations.cc index ac0629e42..018106b4c 100644 --- a/src/prebuilt/wasm2c_source_declarations.cc +++ b/src/prebuilt/wasm2c_source_declarations.cc @@ -135,7 +135,7 @@ R"w2c_template(#define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) R"w2c_template(#endif )w2c_template" R"w2c_template( -#ifdef __GNUC__ +#if defined(__GNUC__) && !WASM2C_NONCONFORMING_LOAD_ELISION )w2c_template" R"w2c_template(#define FORCE_READ_INT(var) __asm__("" ::"r"(var)); )w2c_template" diff --git a/src/template/wasm2c.declarations.c b/src/template/wasm2c.declarations.c index 6399affe2..ce64c7f2e 100644 --- a/src/template/wasm2c.declarations.c +++ b/src/template/wasm2c.declarations.c @@ -73,7 +73,7 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a, #define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !WASM2C_NONCONFORMING_LOAD_ELISION #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats // See https://github.com/llvm/llvm-project/issues/64241 diff --git a/src/template/wasm2c_simd.declarations.c b/src/template/wasm2c_simd.declarations.c index cf397856b..d94d9a9d5 100644 --- a/src/template/wasm2c_simd.declarations.c +++ b/src/template/wasm2c_simd.declarations.c @@ -1,4 +1,5 @@ -#if defined(__GNUC__) && defined(__x86_64__) +#if defined(__GNUC__) && defined(__x86_64__) && \ + !WASM2C_NONCONFORMING_LOAD_ELISION #define SIMD_FORCE_READ(var) __asm__("" ::"x"(var)); #else #define SIMD_FORCE_READ(var) diff --git a/test/run-tests.py b/test/run-tests.py index 2eb7ebbf4..4d147517b 100755 --- a/test/run-tests.py +++ b/test/run-tests.py @@ -684,17 +684,18 @@ def _Clear(self): sys.stderr.write('\r%s\r' % (' ' * self.last_length)) -def FindTestFiles(ext, filter_pattern_re, exclude_dirs): +def FindTestFiles(ext, filter_pattern_re, excludes): tests = [] for root, dirs, files in os.walk(TEST_DIR): - for ex in exclude_dirs: + for ex in excludes: if ex in dirs: # Filtering out dirs here causes os.walk not to descend into them dirs.remove(ex) for f in files: - path = os.path.join(root, f) - if os.path.splitext(f)[1] == ext: - tests.append(os.path.relpath(path, REPO_ROOT_DIR)) + if f not in excludes: + path = os.path.join(root, f) + if os.path.splitext(f)[1] == ext: + tests.append(os.path.relpath(path, REPO_ROOT_DIR)) tests.sort() return [test for test in tests if re.match(filter_pattern_re, test)] @@ -928,10 +929,10 @@ def main(args): action='store_true') parser.add_argument('patterns', metavar='pattern', nargs='*', help='test patterns.') - parser.add_argument('--exclude-dir', action='append', default=[], - help='directory to exclude.') + parser.add_argument('--exclude', action='append', default=[], + help='file or directory names to exclude.') options = parser.parse_args(args) - exclude_dirs = options.exclude_dir + excludes = options.exclude if options.jobs != 1: if options.fail_fast: @@ -947,9 +948,9 @@ def main(args): # By default, exclude wasi tests because WASI support is not include # by int the build by default. # TODO(sbc): Find some way to detect the WASI support. - exclude_dirs += ['wasi'] + excludes += ['wasi'] - test_names = FindTestFiles('.txt', pattern_re, exclude_dirs) + test_names = FindTestFiles('.txt', pattern_re, excludes) if options.list: for test_name in test_names: diff --git a/test/wasm2c/add.txt b/test/wasm2c/add.txt index d250c4c0c..5f5d78dfe 100644 --- a/test/wasm2c/add.txt +++ b/test/wasm2c/add.txt @@ -140,7 +140,7 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a, #define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !WASM2C_NONCONFORMING_LOAD_ELISION #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats // See https://github.com/llvm/llvm-project/issues/64241 diff --git a/test/wasm2c/check-imports.txt b/test/wasm2c/check-imports.txt index 3da1741e5..cbd4e56ac 100644 --- a/test/wasm2c/check-imports.txt +++ b/test/wasm2c/check-imports.txt @@ -163,7 +163,7 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a, #define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !WASM2C_NONCONFORMING_LOAD_ELISION #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats // See https://github.com/llvm/llvm-project/issues/64241 diff --git a/test/wasm2c/export-names.txt b/test/wasm2c/export-names.txt index ed9772b98..35ba5ecf3 100644 --- a/test/wasm2c/export-names.txt +++ b/test/wasm2c/export-names.txt @@ -163,7 +163,7 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a, #define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !WASM2C_NONCONFORMING_LOAD_ELISION #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats // See https://github.com/llvm/llvm-project/issues/64241 diff --git a/test/wasm2c/hello.txt b/test/wasm2c/hello.txt index d56c7216b..9fec8c3cc 100644 --- a/test/wasm2c/hello.txt +++ b/test/wasm2c/hello.txt @@ -171,7 +171,7 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a, #define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !WASM2C_NONCONFORMING_LOAD_ELISION #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats // See https://github.com/llvm/llvm-project/issues/64241 diff --git a/test/wasm2c/minimal.txt b/test/wasm2c/minimal.txt index 9199efb8f..7e3b01b81 100644 --- a/test/wasm2c/minimal.txt +++ b/test/wasm2c/minimal.txt @@ -134,7 +134,7 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a, #define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !WASM2C_NONCONFORMING_LOAD_ELISION #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats // See https://github.com/llvm/llvm-project/issues/64241 diff --git a/test/wasm2c/tail-calls.txt b/test/wasm2c/tail-calls.txt index fe9815e35..fdb1f03b5 100644 --- a/test/wasm2c/tail-calls.txt +++ b/test/wasm2c/tail-calls.txt @@ -164,7 +164,7 @@ static inline bool func_types_eq(const wasm_rt_func_type_t a, #define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !WASM2C_NONCONFORMING_LOAD_ELISION #define FORCE_READ_INT(var) __asm__("" ::"r"(var)); // Clang on Mips requires "f" constraints on floats // See https://github.com/llvm/llvm-project/issues/64241 diff --git a/wasm2c/wasm-rt.h b/wasm2c/wasm-rt.h index bd0cd61df..db18b238f 100644 --- a/wasm2c/wasm-rt.h +++ b/wasm2c/wasm-rt.h @@ -174,6 +174,16 @@ extern "C" { #define WASM_RT_NONCONFORMING_UNCHECKED_STACK_EXHAUSTION 0 #endif +/* This macro, if defined, allows the embedder to specify that wasm2c can remove + * linear memory reads which are unused. Normally, Wasm requires does not allow + * reads to be eliminated when using guard pages, as OOB reads must still trap. + * This a non conformant configuration, i.e., this does not respect Wasm's + * specification. Use with caution. + */ +#ifndef WASM2C_NONCONFORMING_LOAD_ELISION +#define WASM2C_NONCONFORMING_LOAD_ELISION 0 +#endif + /* We need to detect and trap stack overflows. If we use a signal handler on * POSIX systems, this can detect call stack overflows. On windows, or platforms * without a signal handler, we use stack depth counting. */