From eba4ddf98af181424ca8f6f3db67039a7f6f9a2b Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 30 Sep 2025 08:05:02 +0200 Subject: [PATCH 1/8] [ci] Disable JS tests again --- .github/workflows/ci-interpreter.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-interpreter.yml b/.github/workflows/ci-interpreter.yml index 6edfa0c4..1a7511ff 100644 --- a/.github/workflows/ci-interpreter.yml +++ b/.github/workflows/ci-interpreter.yml @@ -23,12 +23,17 @@ jobs: with: ocaml-compiler: 4.12.x - name: Setup OCaml tools - run: opam install --yes ocamlbuild.0.14.0 ocamlfind.1.9.5 js_of_ocaml.4.0.0 js_of_ocaml-ppx.4.0.0 - - name: Setup Node.js - uses: actions/setup-node@v2 - with: - node-version: 19.x + run: opam install --yes ocamlfind.1.9.5 js_of_ocaml.4.0.0 js_of_ocaml-ppx.4.0.0 - name: Build interpreter run: cd interpreter && opam exec make + # Neither V8 nor SpiderMonkey can currently handle all 3.0 tests, so we disable checking JS translation for now. + #- name: Setup Node.js + # uses: actions/setup-node@v4 + # with: + # node-version: 25-nightly + #- name: Setup SpiderMonkey + # run: curl -O https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/jsshell-linux-x86_64.zip && unzip jsshell-linux-x86_64.zip - name: Run tests - run: cd interpreter && opam exec make JS=node ci + run: cd interpreter && opam exec make ci # don't test JS translation + # run: cd interpreter && opam exec make JS=node ci # test with V8 + # run: cd interpreter && opam exec make JS=../js ci # test with SM From 9eae252c06b6b182cf3bea7825add06497e0593a Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Mon, 9 Feb 2026 22:45:38 +0000 Subject: [PATCH 2/8] Use setup-ocaml@v3 --- .github/workflows/ci-interpreter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-interpreter.yml b/.github/workflows/ci-interpreter.yml index 1a7511ff..6ca5db55 100644 --- a/.github/workflows/ci-interpreter.yml +++ b/.github/workflows/ci-interpreter.yml @@ -19,7 +19,7 @@ jobs: - name: Checkout repo uses: actions/checkout@v2 - name: Setup OCaml - uses: ocaml/setup-ocaml@v2 + uses: ocaml/setup-ocaml@v3 with: ocaml-compiler: 4.12.x - name: Setup OCaml tools From af539d8020cc73697c5e71e906e79fa90feae94d Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Mon, 9 Feb 2026 23:51:16 +0000 Subject: [PATCH 3/8] Fix race in os.makedirs --- test/core/run.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/core/run.py b/test/core/run.py index 2aa93b30..517b705f 100755 --- a/test/core/run.py +++ b/test/core/run.py @@ -113,8 +113,7 @@ def _runTestFile(self, inputPath): if __name__ == "__main__": - if not os.path.exists(outputDir): - os.makedirs(outputDir) + os.makedirs(outputDir, exist_ok=True) for fileName in inputFiles: testName = 'test ' + os.path.basename(fileName) setattr(RunTests, testName, lambda self, file=fileName: self._runTestFile(file)) From 1f97aef3e88224af47830273bb73cc9e068296de Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Thu, 29 Jan 2026 18:17:50 +0000 Subject: [PATCH 4/8] Add tests for alignment hint less than natural alignment --- test/core/threads/atomic.wast | 137 ++++++++++++++++++++++++++++++++-- 1 file changed, 131 insertions(+), 6 deletions(-) diff --git a/test/core/threads/atomic.wast b/test/core/threads/atomic.wast index 3ddbdc6a..ceea831a 100644 --- a/test/core/threads/atomic.wast +++ b/test/core/threads/atomic.wast @@ -70,12 +70,12 @@ (func (export "i64.atomic.rmw32.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xchg_u (local.get $addr) (local.get $value))) (func (export "i32.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw.cmpxchg (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i64.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw.cmpxchg (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i32.atomic.rmw8.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw8.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i32.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw16.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i64.atomic.rmw8.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw8.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i64.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw16.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i64.atomic.rmw32.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw32.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i64.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw.cmpxchg (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i32.atomic.rmw8.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw8.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i32.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw16.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i64.atomic.rmw8.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw8.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i64.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw16.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i64.atomic.rmw32.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw32.cmpxchg_u (local.get $addr) (local.get $expected) (local.get $value))) ) @@ -437,6 +437,131 @@ (assert_trap (invoke "i64.atomic.rmw16.cmpxchg_u" (i32.const 1) (i64.const 0) (i64.const 0)) "unaligned atomic") (assert_trap (invoke "i64.atomic.rmw32.cmpxchg_u" (i32.const 1) (i64.const 0) (i64.const 0)) "unaligned atomic") +;; Alignment hint is lower than the natural alignment. Execution will trap even if the address being read is aligned. + +(module + (memory 1 1 shared) + + (func (export "i32.atomic.load") (param $addr i32) (result i32) (i32.atomic.load align=1 (local.get $addr))) + (func (export "i64.atomic.load") (param $addr i32) (result i64) (i64.atomic.load align=1 (local.get $addr))) + (func (export "i32.atomic.load8_u") (param $addr i32) (result i32) (i32.atomic.load8_u align=1 (local.get $addr))) + (func (export "i32.atomic.load16_u") (param $addr i32) (result i32) (i32.atomic.load16_u align=1 (local.get $addr))) + (func (export "i64.atomic.load8_u") (param $addr i32) (result i64) (i64.atomic.load8_u align=1 (local.get $addr))) + (func (export "i64.atomic.load16_u") (param $addr i32) (result i64) (i64.atomic.load16_u align=1 (local.get $addr))) + (func (export "i64.atomic.load32_u") (param $addr i32) (result i64) (i64.atomic.load32_u align=1 (local.get $addr))) + + (func (export "i32.atomic.store") (param $addr i32) (param $value i32) (i32.atomic.store align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.store") (param $addr i32) (param $value i64) (i64.atomic.store align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.store8") (param $addr i32) (param $value i32) (i32.atomic.store8 align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.store16") (param $addr i32) (param $value i32) (i32.atomic.store16 align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.store8") (param $addr i32) (param $value i64) (i64.atomic.store8 align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.store16") (param $addr i32) (param $value i64) (i64.atomic.store16 align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.store32") (param $addr i32) (param $value i64) (i64.atomic.store32 align=1 (local.get $addr) (local.get $value))) + + (func (export "i32.atomic.rmw.add") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.add align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw.add") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.add align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw8.add_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.add_u align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw16.add_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.add_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw8.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.add_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw16.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.add_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw32.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.add_u align=1 (local.get $addr) (local.get $value))) + + (func (export "i32.atomic.rmw.sub") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.sub align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw.sub") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.sub align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw8.sub_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.sub_u align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw16.sub_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.sub_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw8.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.sub_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw16.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.sub_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw32.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.sub_u align=1 (local.get $addr) (local.get $value))) + + (func (export "i32.atomic.rmw.and") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.and align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw.and") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.and align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw8.and_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.and_u align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw16.and_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.and_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw8.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.and_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw16.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.and_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw32.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.and_u align=1 (local.get $addr) (local.get $value))) + + (func (export "i32.atomic.rmw.or") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.or align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw.or") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.or align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw8.or_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.or_u align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw16.or_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.or_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw8.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.or_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw16.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.or_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw32.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.or_u align=1 (local.get $addr) (local.get $value))) + + (func (export "i32.atomic.rmw.xor") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.xor align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw.xor") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.xor align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw8.xor_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.xor_u align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw16.xor_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.xor_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw8.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.xor_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw16.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.xor_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw32.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xor_u align=1 (local.get $addr) (local.get $value))) + + (func (export "i32.atomic.rmw.xchg") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.xchg align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw.xchg") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.xchg align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw8.xchg_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.xchg_u align=1 (local.get $addr) (local.get $value))) + (func (export "i32.atomic.rmw16.xchg_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.xchg_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw8.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.xchg_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw16.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.xchg_u align=1 (local.get $addr) (local.get $value))) + (func (export "i64.atomic.rmw32.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xchg_u align=1 (local.get $addr) (local.get $value))) + + (func (export "i32.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw.cmpxchg align=1 (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i64.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw.cmpxchg align=1 (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i32.atomic.rmw8.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw8.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i32.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw16.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i64.atomic.rmw8.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw8.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i64.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw16.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) + (func (export "i64.atomic.rmw32.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw32.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) +) + +(assert_trap (invoke "i32.atomic.load" (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.load" (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.load16_u" (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.load16_u" (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.load32_u" (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.store" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.store" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.store16" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.store16" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.store32" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw.add" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw.add" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw16.add_u" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw16.add_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw32.add_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw.sub" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw.sub" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw16.sub_u" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw16.sub_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw32.sub_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw.and" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw.and" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw16.and_u" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw16.and_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw32.and_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw.or" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw.or" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw16.or_u" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw16.or_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw32.or_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw.xor" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw.xor" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw16.xor_u" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw16.xor_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw32.xor_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw.xchg" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw.xchg" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw16.xchg_u" (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw16.xchg_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw32.xchg_u" (i32.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw.cmpxchg" (i32.const 0) (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw.cmpxchg" (i32.const 0) (i64.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i32.atomic.rmw16.cmpxchg_u" (i32.const 0) (i32.const 0) (i32.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw16.cmpxchg_u" (i32.const 0) (i64.const 0) (i64.const 0)) "unaligned atomic") +(assert_trap (invoke "i64.atomic.rmw32.cmpxchg_u" (i32.const 0) (i64.const 0) (i64.const 0)) "unaligned atomic") + + ;; wait/notify (module (memory 1 1 shared) From 86d0760783d01f0365a035c4f8c6667080b9f11d Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Tue, 3 Feb 2026 00:26:30 +0000 Subject: [PATCH 5/8] Make non-natural alignment on atomic memroy operations a validation error --- interpreter/valid/valid.ml | 30 +- test/core/threads/atomic.wast | 525 ++++++++++++++++++++++++++-------- 2 files changed, 420 insertions(+), 135 deletions(-) diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 259d3cd7..15dd28e5 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -189,7 +189,7 @@ let check_vec_binop binop at = error at "invalid lane index" | _ -> () -let check_memop (c : context) (memop : ('t, 's) memop) ty_size get_sz at = +let check_memop (c : context) (memop : ('t, 's) memop) ty_size get_sz at ~(isAtomic : bool) = let _mt = memory c (0l @@ at) in let size = match get_sz memop.pack with @@ -199,7 +199,9 @@ let check_memop (c : context) (memop : ('t, 's) memop) ty_size get_sz at = packed_size sz in require (1 lsl memop.align <= size) at - "alignment must not be larger than natural" + "alignment must not be larger than natural"; + if isAtomic then + require (1 lsl memop.align == size) at "atomic memory instruction's alignment must equal the instruction's natural alignment" (* @@ -354,29 +356,29 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : op_type [] --> [] | Load memop -> - check_memop c memop num_size (Lib.Option.map fst) e.at; + check_memop ~isAtomic:false c memop num_size (Lib.Option.map fst) e.at; [NumType I32Type] --> [NumType memop.ty] | Store memop -> - check_memop c memop num_size (fun sz -> sz) e.at; + check_memop ~isAtomic:false c memop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType memop.ty] --> [] | VecLoad memop -> - check_memop c memop vec_size (Lib.Option.map fst) e.at; + check_memop ~isAtomic:false c memop vec_size (Lib.Option.map fst) e.at; [NumType I32Type] --> [VecType memop.ty] | VecStore memop -> - check_memop c memop vec_size (fun _ -> None) e.at; + check_memop ~isAtomic:false c memop vec_size (fun _ -> None) e.at; [NumType I32Type; VecType memop.ty] --> [] | VecLoadLane (memop, i) -> - check_memop c memop vec_size (fun sz -> Some sz) e.at; + check_memop ~isAtomic:false c memop vec_size (fun sz -> Some sz) e.at; require (i < vec_size memop.ty / packed_size memop.pack) e.at "invalid lane index"; [NumType I32Type; VecType memop.ty] --> [VecType memop.ty] | VecStoreLane (memop, i) -> - check_memop c memop vec_size (fun sz -> Some sz) e.at; + check_memop ~isAtomic:false c memop vec_size (fun sz -> Some sz) e.at; require (i < vec_size memop.ty / packed_size memop.pack) e.at "invalid lane index"; [NumType I32Type; VecType memop.ty] --> [] @@ -514,23 +516,23 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : op_type "invalid lane index"; [t; NumType t2] --> [t] | MemoryAtomicWait atomicop -> - check_memop c atomicop num_size (fun sz -> sz) e.at; + check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType atomicop.ty; NumType I64Type] --> [NumType I32Type] | MemoryAtomicNotify atomicop -> - check_memop c atomicop num_size (fun sz -> sz) e.at; + check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType I32Type] --> [NumType I32Type] | AtomicFence -> [] --> [] | AtomicLoad atomicop -> - check_memop c atomicop num_size (fun sz -> sz) e.at; + check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type] --> [NumType atomicop.ty] | AtomicStore atomicop -> - check_memop c atomicop num_size (fun sz -> sz) e.at; + check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType atomicop.ty] --> [] | AtomicRmw (rmwop, atomicop) -> - check_memop c atomicop num_size (fun sz -> sz) e.at; + check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType atomicop.ty] --> [NumType atomicop.ty] | AtomicRmwCmpXchg atomicop -> - check_memop c atomicop num_size (fun sz -> sz) e.at; + check_memop ~isAtomic: true c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType atomicop.ty; NumType atomicop.ty] --> [NumType atomicop.ty] and check_seq (c : context) (s : infer_result_type) (es : instr list) diff --git a/test/core/threads/atomic.wast b/test/core/threads/atomic.wast index ceea831a..8a0f61e9 100644 --- a/test/core/threads/atomic.wast +++ b/test/core/threads/atomic.wast @@ -437,129 +437,412 @@ (assert_trap (invoke "i64.atomic.rmw16.cmpxchg_u" (i32.const 1) (i64.const 0) (i64.const 0)) "unaligned atomic") (assert_trap (invoke "i64.atomic.rmw32.cmpxchg_u" (i32.const 1) (i64.const 0) (i64.const 0)) "unaligned atomic") -;; Alignment hint is lower than the natural alignment. Execution will trap even if the address being read is aligned. +;; non-natural alignment -(module - (memory 1 1 shared) +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.load") (param $addr i32) (result i32) (i32.atomic.load align=1 (local.get $addr))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.load") (param $addr i32) (result i64) (i64.atomic.load align=1 (local.get $addr))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.load16_u") (param $addr i32) (result i32) (i32.atomic.load16_u align=1 (local.get $addr))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.load16_u") (param $addr i32) (result i64) (i64.atomic.load16_u align=1 (local.get $addr))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.load32_u") (param $addr i32) (result i64) (i64.atomic.load32_u align=1 (local.get $addr))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.store") (param $addr i32) (param $value i32) (i32.atomic.store align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.store") (param $addr i32) (param $value i64) (i64.atomic.store align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.store16") (param $addr i32) (param $value i32) (i32.atomic.store16 align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.store16") (param $addr i32) (param $value i64) (i64.atomic.store16 align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.store32") (param $addr i32) (param $value i64) (i64.atomic.store32 align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw.add") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.add align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw.add") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.add align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw16.add_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.add_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw16.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.add_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw32.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.add_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw.sub") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.sub align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw.sub") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.sub align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw16.sub_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.sub_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw16.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.sub_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw32.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.sub_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw.and") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.and align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw.and") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.and align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) - (func (export "i32.atomic.load") (param $addr i32) (result i32) (i32.atomic.load align=1 (local.get $addr))) - (func (export "i64.atomic.load") (param $addr i32) (result i64) (i64.atomic.load align=1 (local.get $addr))) - (func (export "i32.atomic.load8_u") (param $addr i32) (result i32) (i32.atomic.load8_u align=1 (local.get $addr))) - (func (export "i32.atomic.load16_u") (param $addr i32) (result i32) (i32.atomic.load16_u align=1 (local.get $addr))) - (func (export "i64.atomic.load8_u") (param $addr i32) (result i64) (i64.atomic.load8_u align=1 (local.get $addr))) - (func (export "i64.atomic.load16_u") (param $addr i32) (result i64) (i64.atomic.load16_u align=1 (local.get $addr))) - (func (export "i64.atomic.load32_u") (param $addr i32) (result i64) (i64.atomic.load32_u align=1 (local.get $addr))) - - (func (export "i32.atomic.store") (param $addr i32) (param $value i32) (i32.atomic.store align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.store") (param $addr i32) (param $value i64) (i64.atomic.store align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.store8") (param $addr i32) (param $value i32) (i32.atomic.store8 align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.store16") (param $addr i32) (param $value i32) (i32.atomic.store16 align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.store8") (param $addr i32) (param $value i64) (i64.atomic.store8 align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.store16") (param $addr i32) (param $value i64) (i64.atomic.store16 align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.store32") (param $addr i32) (param $value i64) (i64.atomic.store32 align=1 (local.get $addr) (local.get $value))) - - (func (export "i32.atomic.rmw.add") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.add align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw.add") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.add align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw8.add_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.add_u align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw16.add_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.add_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw8.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.add_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw16.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.add_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw32.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.add_u align=1 (local.get $addr) (local.get $value))) - - (func (export "i32.atomic.rmw.sub") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.sub align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw.sub") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.sub align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw8.sub_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.sub_u align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw16.sub_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.sub_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw8.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.sub_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw16.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.sub_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw32.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.sub_u align=1 (local.get $addr) (local.get $value))) - - (func (export "i32.atomic.rmw.and") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.and align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw.and") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.and align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw8.and_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.and_u align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw16.and_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.and_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw8.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.and_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw16.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.and_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw32.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.and_u align=1 (local.get $addr) (local.get $value))) - - (func (export "i32.atomic.rmw.or") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.or align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw.or") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.or align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw8.or_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.or_u align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw16.or_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.or_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw8.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.or_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw16.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.or_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw32.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.or_u align=1 (local.get $addr) (local.get $value))) - - (func (export "i32.atomic.rmw.xor") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.xor align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw.xor") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.xor align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw8.xor_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.xor_u align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw16.xor_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.xor_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw8.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.xor_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw16.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.xor_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw32.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xor_u align=1 (local.get $addr) (local.get $value))) - - (func (export "i32.atomic.rmw.xchg") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.xchg align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw.xchg") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.xchg align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw8.xchg_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw8.xchg_u align=1 (local.get $addr) (local.get $value))) - (func (export "i32.atomic.rmw16.xchg_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.xchg_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw8.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw8.xchg_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw16.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.xchg_u align=1 (local.get $addr) (local.get $value))) - (func (export "i64.atomic.rmw32.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xchg_u align=1 (local.get $addr) (local.get $value))) - - (func (export "i32.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw.cmpxchg align=1 (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i64.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw.cmpxchg align=1 (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i32.atomic.rmw8.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw8.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i32.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw16.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i64.atomic.rmw8.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw8.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i64.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw16.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) - (func (export "i64.atomic.rmw32.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw32.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) -) - -(assert_trap (invoke "i32.atomic.load" (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.load" (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.load16_u" (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.load16_u" (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.load32_u" (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.store" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.store" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.store16" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.store16" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.store32" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw.add" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw.add" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw16.add_u" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw16.add_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw32.add_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw.sub" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw.sub" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw16.sub_u" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw16.sub_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw32.sub_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw.and" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw.and" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw16.and_u" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw16.and_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw32.and_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw.or" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw.or" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw16.or_u" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw16.or_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw32.or_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw.xor" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw.xor" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw16.xor_u" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw16.xor_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw32.xor_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw.xchg" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw.xchg" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw16.xchg_u" (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw16.xchg_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw32.xchg_u" (i32.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw.cmpxchg" (i32.const 0) (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw.cmpxchg" (i32.const 0) (i64.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i32.atomic.rmw16.cmpxchg_u" (i32.const 0) (i32.const 0) (i32.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw16.cmpxchg_u" (i32.const 0) (i64.const 0) (i64.const 0)) "unaligned atomic") -(assert_trap (invoke "i64.atomic.rmw32.cmpxchg_u" (i32.const 0) (i64.const 0) (i64.const 0)) "unaligned atomic") + (func (export "i32.atomic.rmw16.and_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.and_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw16.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.and_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw32.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.and_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw.or") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.or align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw.or") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.or align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw16.or_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.or_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw16.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.or_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw32.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.or_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw.xor") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.xor align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw.xor") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.xor align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw16.xor_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.xor_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw16.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.xor_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw32.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xor_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw.xchg") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.xchg align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw.xchg") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.xchg align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw16.xchg_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.xchg_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw16.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.xchg_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw32.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xchg_u align=1 (local.get $addr) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw.cmpxchg align=1 (local.get $addr) (local.get $expected) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw.cmpxchg align=1 (local.get $addr) (local.get $expected) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i32.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw16.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw16.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) + +(assert_invalid + (module + (memory 1 1 shared) + + (func (export "i64.atomic.rmw32.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw32.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) + ) + "atomic memory instruction's alignment must equal the instruction's natural alignment" +) ;; wait/notify From a0647a8ba5f005e1d818f75bea65c637e1216e5f Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Wed, 4 Feb 2026 21:22:42 +0000 Subject: [PATCH 6/8] PR updates --- interpreter/valid/valid.ml | 39 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 15dd28e5..a685a475 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -189,7 +189,9 @@ let check_vec_binop binop at = error at "invalid lane index" | _ -> () -let check_memop (c : context) (memop : ('t, 's) memop) ty_size get_sz at ~(isAtomic : bool) = +type mem_mode = NonAtomic | Atomic + +let check_memop (mode : mem_mode) (c : context) (memop : ('t, 's) memop) ty_size get_sz at = let _mt = memory c (0l @@ at) in let size = match get_sz memop.pack with @@ -197,11 +199,12 @@ let check_memop (c : context) (memop : ('t, 's) memop) ty_size get_sz at ~(isAto | Some sz -> check_pack sz (ty_size memop.ty) at; packed_size sz - in - require (1 lsl memop.align <= size) at - "alignment must not be larger than natural"; - if isAtomic then - require (1 lsl memop.align == size) at "atomic memory instruction's alignment must equal the instruction's natural alignment" + in match mode with + | NonAtomic -> + require (1 lsl memop.align <= size) at + "alignment must not be larger than natural"; + | Atomic -> + require (1 lsl memop.align == size) at "atomic memory instruction's alignment must equal the instruction's natural alignment" (* @@ -356,29 +359,29 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : op_type [] --> [] | Load memop -> - check_memop ~isAtomic:false c memop num_size (Lib.Option.map fst) e.at; + check_memop NonAtomic c memop num_size (Lib.Option.map fst) e.at; [NumType I32Type] --> [NumType memop.ty] | Store memop -> - check_memop ~isAtomic:false c memop num_size (fun sz -> sz) e.at; + check_memop NonAtomic c memop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType memop.ty] --> [] | VecLoad memop -> - check_memop ~isAtomic:false c memop vec_size (Lib.Option.map fst) e.at; + check_memop NonAtomic c memop vec_size (Lib.Option.map fst) e.at; [NumType I32Type] --> [VecType memop.ty] | VecStore memop -> - check_memop ~isAtomic:false c memop vec_size (fun _ -> None) e.at; + check_memop NonAtomic c memop vec_size (fun _ -> None) e.at; [NumType I32Type; VecType memop.ty] --> [] | VecLoadLane (memop, i) -> - check_memop ~isAtomic:false c memop vec_size (fun sz -> Some sz) e.at; + check_memop NonAtomic c memop vec_size (fun sz -> Some sz) e.at; require (i < vec_size memop.ty / packed_size memop.pack) e.at "invalid lane index"; [NumType I32Type; VecType memop.ty] --> [VecType memop.ty] | VecStoreLane (memop, i) -> - check_memop ~isAtomic:false c memop vec_size (fun sz -> Some sz) e.at; + check_memop NonAtomic c memop vec_size (fun sz -> Some sz) e.at; require (i < vec_size memop.ty / packed_size memop.pack) e.at "invalid lane index"; [NumType I32Type; VecType memop.ty] --> [] @@ -516,23 +519,23 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : op_type "invalid lane index"; [t; NumType t2] --> [t] | MemoryAtomicWait atomicop -> - check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; + check_memop Atomic c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType atomicop.ty; NumType I64Type] --> [NumType I32Type] | MemoryAtomicNotify atomicop -> - check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; + check_memop Atomic c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType I32Type] --> [NumType I32Type] | AtomicFence -> [] --> [] | AtomicLoad atomicop -> - check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; + check_memop Atomic c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type] --> [NumType atomicop.ty] | AtomicStore atomicop -> - check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; + check_memop Atomic c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType atomicop.ty] --> [] | AtomicRmw (rmwop, atomicop) -> - check_memop ~isAtomic:true c atomicop num_size (fun sz -> sz) e.at; + check_memop Atomic c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType atomicop.ty] --> [NumType atomicop.ty] | AtomicRmwCmpXchg atomicop -> - check_memop ~isAtomic: true c atomicop num_size (fun sz -> sz) e.at; + check_memop Atomic c atomicop num_size (fun sz -> sz) e.at; [NumType I32Type; NumType atomicop.ty; NumType atomicop.ty] --> [NumType atomicop.ty] and check_seq (c : context) (s : infer_result_type) (es : instr list) From f61ac0341abb2f2bf9de89630906010337a73e52 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 6 Feb 2026 12:33:30 +0100 Subject: [PATCH 7/8] Update interpreter/valid/valid.ml --- interpreter/valid/valid.ml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index a685a475..4385daff 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -199,12 +199,14 @@ let check_memop (mode : mem_mode) (c : context) (memop : ('t, 's) memop) ty_size | Some sz -> check_pack sz (ty_size memop.ty) at; packed_size sz - in match mode with - | NonAtomic -> - require (1 lsl memop.align <= size) at - "alignment must not be larger than natural"; - | Atomic -> - require (1 lsl memop.align == size) at "atomic memory instruction's alignment must equal the instruction's natural alignment" + in + match mode with + | NonAtomic -> + require (1 lsl memop.align <= size) at + "alignment must not be larger than natural"; + | Atomic -> + require (1 lsl memop.align = size) at + "atomic alignment must be natural" (* From 87376662d919250546592c1cef645698de795077 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 6 Feb 2026 12:37:46 +0100 Subject: [PATCH 8/8] Update atomic.wast --- test/core/threads/atomic.wast | 90 +++++++++++++++++------------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/test/core/threads/atomic.wast b/test/core/threads/atomic.wast index 8a0f61e9..7c340f98 100644 --- a/test/core/threads/atomic.wast +++ b/test/core/threads/atomic.wast @@ -445,7 +445,7 @@ (func (export "i32.atomic.load") (param $addr i32) (result i32) (i32.atomic.load align=1 (local.get $addr))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -454,7 +454,7 @@ (func (export "i64.atomic.load") (param $addr i32) (result i64) (i64.atomic.load align=1 (local.get $addr))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -463,7 +463,7 @@ (func (export "i32.atomic.load16_u") (param $addr i32) (result i32) (i32.atomic.load16_u align=1 (local.get $addr))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -472,7 +472,7 @@ (func (export "i64.atomic.load16_u") (param $addr i32) (result i64) (i64.atomic.load16_u align=1 (local.get $addr))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -481,7 +481,7 @@ (func (export "i64.atomic.load32_u") (param $addr i32) (result i64) (i64.atomic.load32_u align=1 (local.get $addr))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -490,7 +490,7 @@ (func (export "i32.atomic.store") (param $addr i32) (param $value i32) (i32.atomic.store align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -499,7 +499,7 @@ (func (export "i64.atomic.store") (param $addr i32) (param $value i64) (i64.atomic.store align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -508,7 +508,7 @@ (func (export "i32.atomic.store16") (param $addr i32) (param $value i32) (i32.atomic.store16 align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -517,7 +517,7 @@ (func (export "i64.atomic.store16") (param $addr i32) (param $value i64) (i64.atomic.store16 align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -526,7 +526,7 @@ (func (export "i64.atomic.store32") (param $addr i32) (param $value i64) (i64.atomic.store32 align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -535,7 +535,7 @@ (func (export "i32.atomic.rmw.add") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.add align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -544,7 +544,7 @@ (func (export "i64.atomic.rmw.add") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.add align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -553,7 +553,7 @@ (func (export "i32.atomic.rmw16.add_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.add_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -562,7 +562,7 @@ (func (export "i64.atomic.rmw16.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.add_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -571,7 +571,7 @@ (func (export "i64.atomic.rmw32.add_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.add_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -580,7 +580,7 @@ (func (export "i32.atomic.rmw.sub") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.sub align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -589,7 +589,7 @@ (func (export "i64.atomic.rmw.sub") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.sub align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -598,7 +598,7 @@ (func (export "i32.atomic.rmw16.sub_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.sub_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -607,7 +607,7 @@ (func (export "i64.atomic.rmw16.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.sub_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -616,7 +616,7 @@ (func (export "i64.atomic.rmw32.sub_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.sub_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -625,7 +625,7 @@ (func (export "i32.atomic.rmw.and") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.and align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -634,7 +634,7 @@ (func (export "i64.atomic.rmw.and") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.and align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -643,7 +643,7 @@ (func (export "i32.atomic.rmw16.and_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.and_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -652,7 +652,7 @@ (func (export "i64.atomic.rmw16.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.and_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -661,7 +661,7 @@ (func (export "i64.atomic.rmw32.and_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.and_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -670,7 +670,7 @@ (func (export "i32.atomic.rmw.or") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.or align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -679,7 +679,7 @@ (func (export "i64.atomic.rmw.or") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.or align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -688,7 +688,7 @@ (func (export "i32.atomic.rmw16.or_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.or_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -697,7 +697,7 @@ (func (export "i64.atomic.rmw16.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.or_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -706,7 +706,7 @@ (func (export "i64.atomic.rmw32.or_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.or_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -715,7 +715,7 @@ (func (export "i32.atomic.rmw.xor") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.xor align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -724,7 +724,7 @@ (func (export "i64.atomic.rmw.xor") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.xor align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -733,7 +733,7 @@ (func (export "i32.atomic.rmw16.xor_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.xor_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -742,7 +742,7 @@ (func (export "i64.atomic.rmw16.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.xor_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -751,7 +751,7 @@ (func (export "i64.atomic.rmw32.xor_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xor_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -760,7 +760,7 @@ (func (export "i32.atomic.rmw.xchg") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw.xchg align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -769,7 +769,7 @@ (func (export "i64.atomic.rmw.xchg") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw.xchg align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -778,7 +778,7 @@ (func (export "i32.atomic.rmw16.xchg_u") (param $addr i32) (param $value i32) (result i32) (i32.atomic.rmw16.xchg_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -787,7 +787,7 @@ (func (export "i64.atomic.rmw16.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw16.xchg_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -796,7 +796,7 @@ (func (export "i64.atomic.rmw32.xchg_u") (param $addr i32) (param $value i64) (result i64) (i64.atomic.rmw32.xchg_u align=1 (local.get $addr) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -805,7 +805,7 @@ (func (export "i32.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw.cmpxchg align=1 (local.get $addr) (local.get $expected) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -814,7 +814,7 @@ (func (export "i64.atomic.rmw.cmpxchg") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw.cmpxchg align=1 (local.get $addr) (local.get $expected) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -823,7 +823,7 @@ (func (export "i32.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i32) (param $value i32) (result i32) (i32.atomic.rmw16.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -832,7 +832,7 @@ (func (export "i64.atomic.rmw16.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw16.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" ) (assert_invalid @@ -841,7 +841,7 @@ (func (export "i64.atomic.rmw32.cmpxchg_u") (param $addr i32) (param $expected i64) (param $value i64) (result i64) (i64.atomic.rmw32.cmpxchg_u align=1 (local.get $addr) (local.get $expected) (local.get $value))) ) - "atomic memory instruction's alignment must equal the instruction's natural alignment" + "atomic alignment must be natural" )