diff options
-rwxr-xr-x | scripts/fuzz_opt.py | 1 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 3 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 6 | ||||
-rw-r--r-- | test/spec/shared-polymorphism.wast | 2 | ||||
-rw-r--r-- | test/spec/shared-ref_eq.wast | 202 |
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" +) |