summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/fuzz_opt.py1
-rw-r--r--src/wasm/literal.cpp3
-rw-r--r--src/wasm/wasm-validator.cpp6
-rw-r--r--test/spec/shared-polymorphism.wast2
-rw-r--r--test/spec/shared-ref_eq.wast202
5 files changed, 211 insertions, 3 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py
index f4b64f44c..b9d42d634 100755
--- a/scripts/fuzz_opt.py
+++ b/scripts/fuzz_opt.py
@@ -360,6 +360,7 @@ INITIAL_CONTENTS_IGNORE = [
'shared-null.wast',
'shared-absheaptype.wast',
'type-ssa-shared.wast',
+ 'shared-ref_eq.wast',
]
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 20b6b7234..a49fa1b62 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -445,7 +445,8 @@ bool Literal::operator==(const Literal& other) const {
if (type.isData()) {
return gcData == other.gcData;
}
- if (type.getHeapType() == HeapType::i31) {
+ assert(type.getHeapType().isBasic());
+ if (type.getHeapType().getBasic(Unshared) == HeapType::i31) {
return i32 == other.i32;
}
WASM_UNREACHABLE("unexpected type");
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index e18191bea..29e7a2c9c 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2306,6 +2306,12 @@ void FunctionValidator::visitRefEq(RefEq* curr) {
eqref,
curr->right,
"ref.eq's right argument should be a subtype of eqref");
+ if (curr->left->type.isRef() && curr->right->type.isRef()) {
+ shouldBeEqual(curr->left->type.getHeapType().getShared(),
+ curr->right->type.getHeapType().getShared(),
+ curr,
+ "ref.eq operands must have the same shareability");
+ }
}
void FunctionValidator::visitTableGet(TableGet* curr) {
diff --git a/test/spec/shared-polymorphism.wast b/test/spec/shared-polymorphism.wast
index be8b5e467..5c9d905e7 100644
--- a/test/spec/shared-polymorphism.wast
+++ b/test/spec/shared-polymorphism.wast
@@ -2,8 +2,6 @@
;; references.
(module
(func (drop (ref.eq (ref.null (shared none)) (ref.null (shared none)))))
- (func (drop (ref.eq (ref.null (shared none)) (ref.null none))))
- (func (drop (ref.eq (ref.null none) (ref.null (shared none)))))
(func (param (ref null (shared i31))) (drop (i31.get_s (local.get 0))))
(func (param (ref null (shared i31))) (drop (i31.get_u (local.get 0))))
diff --git a/test/spec/shared-ref_eq.wast b/test/spec/shared-ref_eq.wast
new file mode 100644
index 000000000..662138ee6
--- /dev/null
+++ b/test/spec/shared-ref_eq.wast
@@ -0,0 +1,202 @@
+(module
+ (type $st (sub (shared (struct))))
+ (type $st' (sub (shared (struct (field i32)))))
+ (type $at (shared (array i8)))
+ (type $st-sub1 (sub $st (shared (struct))))
+ (type $st-sub2 (sub $st (shared (struct))))
+ (type $st'-sub1 (sub $st' (shared (struct (field i32)))))
+ (type $st'-sub2 (sub $st' (shared (struct (field i32)))))
+
+ (table 20 (ref null (shared eq)))
+
+ (func (export "init")
+ (table.set (i32.const 0) (ref.null (shared eq)))
+ (table.set (i32.const 1) (ref.null (shared i31)))
+ (table.set (i32.const 2) (ref.i31_shared (i32.const 7)))
+ (table.set (i32.const 3) (ref.i31_shared (i32.const 7)))
+ (table.set (i32.const 4) (ref.i31_shared (i32.const 8)))
+ (table.set (i32.const 5) (struct.new_default $st))
+ (table.set (i32.const 6) (struct.new_default $st))
+ (table.set (i32.const 7) (array.new_default $at (i32.const 0)))
+ (table.set (i32.const 8) (array.new_default $at (i32.const 0)))
+ )
+
+ (func (export "eq") (param $i i32) (param $j i32) (result i32)
+ (ref.eq (table.get (local.get $i)) (table.get (local.get $j)))
+ )
+)
+
+(invoke "init")
+
+(assert_return (invoke "eq" (i32.const 0) (i32.const 0)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 0) (i32.const 1)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 0) (i32.const 2)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 0) (i32.const 3)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 0) (i32.const 4)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 0) (i32.const 5)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 0) (i32.const 6)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 0) (i32.const 7)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 0) (i32.const 8)) (i32.const 0))
+
+(assert_return (invoke "eq" (i32.const 1) (i32.const 0)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 1)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 2)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 3)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 4)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 5)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 6)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 7)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 8)) (i32.const 0))
+
+(assert_return (invoke "eq" (i32.const 2) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 2) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 2) (i32.const 2)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 2) (i32.const 3)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 2) (i32.const 4)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 2) (i32.const 5)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 2) (i32.const 6)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 2) (i32.const 7)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 2) (i32.const 8)) (i32.const 0))
+
+(assert_return (invoke "eq" (i32.const 3) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 3) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 3) (i32.const 2)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 3) (i32.const 3)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 3) (i32.const 4)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 3) (i32.const 5)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 3) (i32.const 6)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 3) (i32.const 7)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 3) (i32.const 8)) (i32.const 0))
+
+(assert_return (invoke "eq" (i32.const 4) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 4) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 4) (i32.const 2)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 4) (i32.const 3)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 4) (i32.const 4)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 4) (i32.const 5)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 4) (i32.const 6)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 4) (i32.const 7)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 4) (i32.const 8)) (i32.const 0))
+
+(assert_return (invoke "eq" (i32.const 5) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 5) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 5) (i32.const 2)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 5) (i32.const 3)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 5) (i32.const 4)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 5) (i32.const 5)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 5) (i32.const 6)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 5) (i32.const 7)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 5) (i32.const 8)) (i32.const 0))
+
+(assert_return (invoke "eq" (i32.const 6) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 6) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 6) (i32.const 2)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 6) (i32.const 3)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 6) (i32.const 4)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 6) (i32.const 5)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 6) (i32.const 6)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 6) (i32.const 7)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 6) (i32.const 8)) (i32.const 0))
+
+(assert_return (invoke "eq" (i32.const 7) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 7) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 7) (i32.const 2)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 7) (i32.const 3)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 7) (i32.const 4)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 7) (i32.const 5)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 7) (i32.const 6)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 7) (i32.const 7)) (i32.const 1))
+(assert_return (invoke "eq" (i32.const 7) (i32.const 8)) (i32.const 0))
+
+(assert_return (invoke "eq" (i32.const 8) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 8) (i32.const 1)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 8) (i32.const 2)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 8) (i32.const 3)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 8) (i32.const 4)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 8) (i32.const 5)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 8) (i32.const 6)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 8) (i32.const 7)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 8) (i32.const 8)) (i32.const 1))
+
+(assert_invalid
+ (module
+ (func (export "eq") (param $r (ref (shared any))) (result i32)
+ (ref.eq (local.get $r) (local.get $r))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (func (export "eq") (param $r (ref null (shared any))) (result i32)
+ (ref.eq (local.get $r) (local.get $r))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (func (export "eq") (param $r (ref null (shared func))) (result i32)
+ (ref.eq (local.get $r) (local.get $r))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (func (export "eq") (param $r (ref null (shared func))) (result i32)
+ (ref.eq (local.get $r) (local.get $r))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (func (export "eq") (param $r (ref (shared extern))) (result i32)
+ (ref.eq (local.get $r) (local.get $r))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (func (export "eq") (param $r (ref null (shared extern))) (result i32)
+ (ref.eq (local.get $r) (local.get $r))
+ )
+ )
+ "type mismatch"
+)
+
+;; Mixed shared / unshared eq
+(assert_invalid
+ (module
+ (func (export "eq") (param $r1 (ref eq)) (param $r2 (ref (shared eq))) (result i32)
+ (ref.eq (local.get $r1) (local.get $r2))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (func (export "eq") (param $r1 (ref (shared eq))) (param $r2 (ref eq)) (result i32)
+ (ref.eq (local.get $r1) (local.get $r2))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (func (export "eq") (param $r1 eqref) (param $r2 (ref null (shared eq))) (result i32)
+ (ref.eq (local.get $r1) (local.get $r2))
+ )
+ )
+ "type mismatch"
+)
+(assert_invalid
+ (module
+ (func (export "eq") (param $r1 (ref null (shared eq))) (param $r2 eqref) (result i32)
+ (ref.eq (local.get $r1) (local.get $r2))
+ )
+ )
+ "type mismatch"
+)