diff --git a/src/ir/subtype-exprs.h b/src/ir/subtype-exprs.h index e2cf5b14f20..61a0d6a2267 100644 --- a/src/ir/subtype-exprs.h +++ b/src/ir/subtype-exprs.h @@ -368,8 +368,12 @@ struct SubtypingDiscoverer : public OverriddenVisitor { } const auto& fields = curr->ref->type.getHeapType().getStruct().fields; auto type = fields[curr->index].type; - self()->noteSubtype(curr->expected, - type.isRef() ? Type(HeapType::eq, Nullable) : type); + Type expectedType = type; + if (type.isRef()) { + expectedType = + Type(HeapTypes::eq.getBasic(type.getHeapType().getShared()), Nullable); + } + self()->noteSubtype(curr->expected, expectedType); self()->noteSubtype(curr->replacement, type); } void visitStructWait(StructWait* curr) {} @@ -445,8 +449,12 @@ struct SubtypingDiscoverer : public OverriddenVisitor { return; } auto type = curr->ref->type.getHeapType().getArray().element.type; - self()->noteSubtype(curr->expected, - type.isRef() ? Type(HeapType::eq, Nullable) : type); + Type expectedType = type; + if (type.isRef()) { + expectedType = + Type(HeapTypes::eq.getBasic(type.getHeapType().getShared()), Nullable); + } + self()->noteSubtype(curr->expected, expectedType); self()->noteSubtype(curr->replacement, type); } void visitRefAs(RefAs* curr) { diff --git a/test/lit/passes/unsubtyping-cmpxchg.wast b/test/lit/passes/unsubtyping-cmpxchg.wast new file mode 100644 index 00000000000..91f28863e8d --- /dev/null +++ b/test/lit/passes/unsubtyping-cmpxchg.wast @@ -0,0 +1,82 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; RUN: wasm-opt %s -all --closed-world --unsubtyping -S -o - | filecheck %s + +(module + ;; CHECK: (rec + ;; CHECK-NEXT: (type $array-unshared (array (mut eqref))) + + ;; CHECK: (type $array-shared (shared (array (mut (ref null (shared eq)))))) + + ;; CHECK: (type $struct-unshared (struct (field (mut eqref)))) + + ;; CHECK: (type $struct-shared (struct (field (mut (ref null (shared eq)))))) + (type $struct-shared (struct (field (mut (ref null (shared eq)))))) + (type $struct-unshared (struct (field (mut eqref)))) + + (type $array-shared (shared (array (mut (ref null (shared eq)))))) + (type $array-unshared (array (mut eqref))) + + ;; CHECK: (func $struct-shared-eq (type $7) (param $struct (ref $struct-shared)) (param $eq (ref null (shared eq))) (result (ref null (shared eq))) + ;; CHECK-NEXT: (struct.atomic.rmw.cmpxchg $struct-shared 0 + ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: (local.get $eq) + ;; CHECK-NEXT: (local.get $eq) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-shared-eq (param $struct (ref $struct-shared)) (param $eq (ref null (shared eq))) (result (ref null (shared eq))) + (struct.atomic.rmw.cmpxchg $struct-shared 0 + (local.get $struct) + (local.get $eq) + (local.get $eq) + ) + ) + + ;; CHECK: (func $struct-unshared-eq (type $6) (param $struct (ref $struct-unshared)) (param $eq eqref) (result eqref) + ;; CHECK-NEXT: (struct.atomic.rmw.cmpxchg $struct-unshared 0 + ;; CHECK-NEXT: (local.get $struct) + ;; CHECK-NEXT: (local.get $eq) + ;; CHECK-NEXT: (local.get $eq) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $struct-unshared-eq (param $struct (ref $struct-unshared)) (param $eq eqref) (result eqref) + (struct.atomic.rmw.cmpxchg $struct-unshared 0 + (local.get $struct) + (local.get $eq) + (local.get $eq) + ) + ) + + ;; CHECK: (func $array-shared-eq (type $5) (param $array (ref $array-shared)) (param $eq (ref null (shared eq))) (result (ref null (shared eq))) + ;; CHECK-NEXT: (array.atomic.rmw.cmpxchg $array-shared + ;; CHECK-NEXT: (local.get $array) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $eq) + ;; CHECK-NEXT: (local.get $eq) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-shared-eq (param $array (ref $array-shared)) (param $eq (ref null (shared eq))) (result (ref null (shared eq))) + (array.atomic.rmw.cmpxchg $array-shared + (local.get $array) + (i32.const 0) + (local.get $eq) + (local.get $eq) + ) + ) + + ;; CHECK: (func $array-unshared-eq (type $4) (param $array (ref $array-unshared)) (param $eq eqref) (result eqref) + ;; CHECK-NEXT: (array.atomic.rmw.cmpxchg $array-unshared + ;; CHECK-NEXT: (local.get $array) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $eq) + ;; CHECK-NEXT: (local.get $eq) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $array-unshared-eq (param $array (ref $array-unshared)) (param $eq eqref) (result eqref) + (array.atomic.rmw.cmpxchg $array-unshared + (local.get $array) + (i32.const 0) + (local.get $eq) + (local.get $eq) + ) + ) +)