summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-07-23 17:16:34 -0700
committerGitHub <noreply@github.com>2021-07-23 17:16:34 -0700
commitae060f070064fd87adae7ea9db5aeb2dace5a4ff (patch)
tree5dbee229ecef3af430d87bf3931034a84d379c12
parent0b0054342af5c73de62ddf0603619292443c505c (diff)
downloadbinaryen-ae060f070064fd87adae7ea9db5aeb2dace5a4ff.tar.gz
binaryen-ae060f070064fd87adae7ea9db5aeb2dace5a4ff.tar.bz2
binaryen-ae060f070064fd87adae7ea9db5aeb2dace5a4ff.zip
[Wasm GC] Handle nondefaultable types in LocalSubtyping (#4019)
The pass handled non-nullability, but another case is a tuple with nullable values in it that is assigned non-nullable values, and in general, other stuff that is nondefaultable (but not non-nullable). Ignore those.
-rw-r--r--src/passes/LocalSubtyping.cpp23
-rw-r--r--test/lit/passes/local-subtyping.wast21
2 files changed, 36 insertions, 8 deletions
diff --git a/src/passes/LocalSubtyping.cpp b/src/passes/LocalSubtyping.cpp
index f435e53d4..9c6da1131 100644
--- a/src/passes/LocalSubtyping.cpp
+++ b/src/passes/LocalSubtyping.cpp
@@ -103,14 +103,21 @@ struct LocalSubtyping : public WalkerPass<PostWalker<LocalSubtyping>> {
assert(newType != Type::none); // in valid wasm there must be a LUB
// Remove non-nullability if we disallow that in locals.
- if (!getModule()->features.hasGCNNLocals() && newType.isNonNullable()) {
- newType = Type(newType.getHeapType(), Nullable);
- // Note that the old type must have been nullable as well, as non-
- // nullable types cannot be locals without that feature being enabled,
- // which means that we will not have to do any extra work to handle
- // non-nullability if we update the type: we are just updating the
- // heap type, and leaving the type nullable as it was.
- assert(oldType.isNullable());
+ if (newType.isNonNullable()) {
+ if (!getModule()->features.hasGCNNLocals()) {
+ newType = Type(newType.getHeapType(), Nullable);
+ // Note that the old type must have been nullable as well, as non-
+ // nullable types cannot be locals without that feature being
+ // enabled, which means that we will not have to do any extra work
+ // to handle non-nullability if we update the type: we are just
+ // updating the heap type, and leaving the type nullable as it was.
+ assert(oldType.isNullable());
+ }
+ } else if (!newType.isDefaultable()) {
+ // Aside from the case we just handled of allowed non-nullability, we
+ // cannot put anything else in a local that does not have a default
+ // value.
+ continue;
}
if (newType != oldType) {
diff --git a/test/lit/passes/local-subtyping.wast b/test/lit/passes/local-subtyping.wast
index 59f93ce43..2f5c4dc4f 100644
--- a/test/lit/passes/local-subtyping.wast
+++ b/test/lit/passes/local-subtyping.wast
@@ -202,4 +202,25 @@
)
)
)
+
+ ;; CHECK: (func $nondefaultable
+ ;; CHECK-NEXT: (local $x (anyref anyref))
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (tuple.make
+ ;; CHECK-NEXT: (ref.func $i32)
+ ;; CHECK-NEXT: (ref.func $i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $nondefaultable
+ (local $x (anyref anyref))
+ ;; This tuple is assigned non-nullable values, which means the subtype is
+ ;; nondefaultable, and we must not apply it.
+ (local.set $x
+ (tuple.make
+ (ref.func $i32)
+ (ref.func $i32)
+ )
+ )
+ )
)