summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-10-26 15:56:32 -0700
committerGitHub <noreply@github.com>2021-10-26 15:56:32 -0700
commit3907e07dee3ce2bd477d5c234cd7bdd6aa1294a2 (patch)
treee2dc282945db717cf9dcb9c862e226f2e0056f4b
parentc28dd3c3ef96c32e63b7944ac0d1fc8601f6d9f4 (diff)
downloadbinaryen-3907e07dee3ce2bd477d5c234cd7bdd6aa1294a2.tar.gz
binaryen-3907e07dee3ce2bd477d5c234cd7bdd6aa1294a2.tar.bz2
binaryen-3907e07dee3ce2bd477d5c234cd7bdd6aa1294a2.zip
[Wasm GC] Add missing Tuple logic to TypeRewriter (#4278)
Without this, we'd just return the old type for the tuple, which meant its fields referred to unrewritten types, and possible validation errors if the types changed.
-rw-r--r--src/ir/type-updating.cpp7
-rw-r--r--test/lit/passes/gto-mutability.wast35
2 files changed, 42 insertions, 0 deletions
diff --git a/src/ir/type-updating.cpp b/src/ir/type-updating.cpp
index d3ecf7ad6..cacdc9000 100644
--- a/src/ir/type-updating.cpp
+++ b/src/ir/type-updating.cpp
@@ -100,6 +100,13 @@ void GlobalTypeRewriter::update() {
if (type.isRtt()) {
return Type(Rtt(type.getRtt().depth, getNew(type.getHeapType())));
}
+ if (type.isTuple()) {
+ auto tuple = type.getTuple();
+ for (auto& t : tuple.types) {
+ t = getNew(t);
+ }
+ return Type(tuple);
+ }
return type;
}
diff --git a/test/lit/passes/gto-mutability.wast b/test/lit/passes/gto-mutability.wast
index bd657bb90..6cb3575d7 100644
--- a/test/lit/passes/gto-mutability.wast
+++ b/test/lit/passes/gto-mutability.wast
@@ -10,6 +10,9 @@
;; CHECK: (type $struct (struct_subtype (field (mut funcref)) (field funcref) (field (mut funcref)) data))
(type $struct (struct (field (mut funcref)) (field (mut funcref)) (field (mut funcref))))
+ ;; CHECK: (type $two-params (func_subtype (param (ref $struct) (ref $struct)) func))
+ (type $two-params (func (param (ref $struct)) (param (ref $struct))))
+
;; Test that we update tag types properly.
;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func))
@@ -17,6 +20,11 @@
;; CHECK: (type $none_=>_none (func_subtype func))
+ ;; CHECK: (table $0 0 funcref)
+ (table 0 funcref)
+
+ ;; CHECK: (elem declare func $func-two-params)
+
;; CHECK: (tag $tag (param (ref $struct)))
(tag $tag (param (ref $struct)))
@@ -117,6 +125,33 @@
(ref.null $struct)
)
+ ;; CHECK: (func $func-two-params (param $x (ref $struct)) (param $y (ref $struct))
+ ;; CHECK-NEXT: (local $z (ref null $two-params))
+ ;; CHECK-NEXT: (local.set $z
+ ;; CHECK-NEXT: (ref.func $func-two-params)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call_indirect $0 (type $two-params)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $func-two-params (param $x (ref $struct)) (param $y (ref $struct))
+ ;; This function has two params, which means a tuple type is used for its
+ ;; signature, which we must also update. To verify the update is correct,
+ ;; assign it to a local.
+ (local $z (ref null $two-params))
+ (local.set $z
+ (ref.func $func-two-params)
+ )
+ ;; Also check that a call_indirect still validates after the rewriting.
+ (call_indirect (type $two-params)
+ (local.get $x)
+ (local.get $y)
+ (i32.const 0)
+ )
+ )
+
;; CHECK: (func $field-keepalive
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.get $struct 2