summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-07-16 16:30:09 -0400
committerGitHub <noreply@github.com>2024-07-16 13:30:09 -0700
commit9de9d05de2f6780ac6d1394528b7e38223edf22b (patch)
tree99ad87392400c5d905f8c7a66072e5f3b9e9cd90
parentee43476328df55757614d3a7db4419426fd3d3e9 (diff)
downloadbinaryen-9de9d05de2f6780ac6d1394528b7e38223edf22b.tar.gz
binaryen-9de9d05de2f6780ac6d1394528b7e38223edf22b.tar.bz2
binaryen-9de9d05de2f6780ac6d1394528b7e38223edf22b.zip
[threads] Allow i31refs of mixed shareability to compare equal (#6752)
Normally, values of different types can never compare equal to each other, but since i31refs are not actually allocations, `ref.eq` has no way to differentiate a shared i31ref and an unshared i31ref with the same value, so it will report them as equal. Update the implementation of value equality to reflect this correctly.
-rw-r--r--src/wasm/literal.cpp12
-rw-r--r--test/spec/shared-polymorphism.wast11
2 files changed, 20 insertions, 3 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 20b6b7234..300fc3773 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -412,6 +412,14 @@ void Literal::getBits(uint8_t (&buf)[16]) const {
}
bool Literal::operator==(const Literal& other) const {
+ // As a special case, shared and unshared i31 can compare equal even if their
+ // types are different (because one is shared and the other is not).
+ if (type.isRef() && other.type.isRef() && type.getHeapType().isBasic() &&
+ other.type.getHeapType().isBasic() &&
+ type.getHeapType().getBasic(Unshared) == HeapType::i31 &&
+ other.type.getHeapType().getBasic(Unshared) == HeapType::i31) {
+ return i32 == other.i32;
+ }
if (type != other.type) {
return false;
}
@@ -445,9 +453,7 @@ bool Literal::operator==(const Literal& other) const {
if (type.isData()) {
return gcData == other.gcData;
}
- if (type.getHeapType() == HeapType::i31) {
- return i32 == other.i32;
- }
+ // i31 already handled.
WASM_UNREACHABLE("unexpected type");
}
WASM_UNREACHABLE("unexpected type");
diff --git a/test/spec/shared-polymorphism.wast b/test/spec/shared-polymorphism.wast
index be8b5e467..3ceead362 100644
--- a/test/spec/shared-polymorphism.wast
+++ b/test/spec/shared-polymorphism.wast
@@ -23,3 +23,14 @@
(extern.convert_any (local.get 0))
)
)
+
+(module
+ (func (export "eq") (param i32 i32) (result i32)
+ (ref.eq (ref.i31 (local.get 0)) (ref.i31_shared (local.get 1)))
+ )
+)
+
+(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 0))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 0)) (i32.const 0))
+(assert_return (invoke "eq" (i32.const 1) (i32.const 1)) (i32.const 1))