From 9dce77bc47cf9abc17313b49a36a7ac88bc77a23 Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Thu, 29 Jan 2026 18:17:50 +0000 Subject: [PATCH 1/2] 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 36eb53ad939379e39c52cb63689d16786cb35cc0 Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Tue, 3 Feb 2026 00:26:30 +0000 Subject: [PATCH 2/2] 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