diff options
author | Alon Zakai <azakai@google.com> | 2021-03-23 14:23:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-23 14:23:43 -0700 |
commit | f2abcbc8d1659d3e6506b1d4128646b892ebc218 (patch) | |
tree | 30bb82cc27bc26df7cb32b889176605c54b9a0b3 /src/wasm/wasm.cpp | |
parent | 5ef255154172504385a8218f9712a48d98a47689 (diff) | |
download | binaryen-f2abcbc8d1659d3e6506b1d4128646b892ebc218.tar.gz binaryen-f2abcbc8d1659d3e6506b1d4128646b892ebc218.tar.bz2 binaryen-f2abcbc8d1659d3e6506b1d4128646b892ebc218.zip |
[Wasm GC] Add support for non-nullable types, all except for locals (#3710)
After this PR we still do not support non-nullable locals. But we no longer
turn all types into nullable upon load. In particular, we support non-nullable
types on function parameters and struct fields, etc. This should be enough to
experiment with optimizations in both binaryen and in VMs regarding non-
nullability (since we expect that optimizing VMs can do well inside functions
anyhow; it's non-nullability across calls and from data that the VM can't be
expected to think about).
Let is handled as before, by lowering it into gets and sets. In addition, we
turn non-nullable locals into nullable ones, and add a ref.as_non_null on
all their gets (to keep the type identical there). This is used not just for
loading code with a let but also is needed after inlining.
Most of the code changes here are removing FIXMEs for allowing
non-nullable types. But there is also code to handle the issues mentioned
above.
Most of the test updates are removing extra nulls that we added before
when we turned all types nullable. A few tests had actual issues, though,
and also some new tests are added to cover the code changes here.
Diffstat (limited to 'src/wasm/wasm.cpp')
-rw-r--r-- | src/wasm/wasm.cpp | 35 |
1 files changed, 8 insertions, 27 deletions
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 5eea3f315..2dba93a4a 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -928,30 +928,16 @@ void RefTest::finalize() { } } -// Helper to get the cast type for a cast instruction. They all look at the rtt -// operand's type. -template<typename T> static Type doGetCastType(T* curr) { - if (curr->rtt->type == Type::unreachable) { - // We don't have the RTT type, so just return unreachable. The type in this - // case should not matter in practice, but it may be seen while debugging. - return Type::unreachable; - } - // TODO: make non-nullable when we support that - return Type(curr->rtt->type.getHeapType(), Nullable); -} - -Type RefTest::getCastType() { return doGetCastType(this); } - void RefCast::finalize() { if (ref->type == Type::unreachable || rtt->type == Type::unreachable) { type = Type::unreachable; } else { - type = getCastType(); + // The output of ref.cast may be null if the input is null (in that case the + // null is passed through). + type = Type(rtt->type.getHeapType(), ref->type.getNullability()); } } -Type RefCast::getCastType() { return doGetCastType(this); } - void BrOn::finalize() { if (ref->type == Type::unreachable || (rtt && rtt->type == Type::unreachable)) { @@ -960,8 +946,7 @@ void BrOn::finalize() { if (op == BrOnNull) { // If BrOnNull does not branch, it flows out the existing value as // non-null. - // FIXME: When we support non-nullable types, this should be non-nullable. - type = Type(ref->type.getHeapType(), Nullable); + type = Type(ref->type.getHeapType(), NonNullable); } else { type = ref->type; } @@ -974,8 +959,7 @@ Type BrOn::getCastType() { // BrOnNull does not send a value on the branch. return Type::none; case BrOnCast: - // FIXME: When we support non-nullable types, this should be non-nullable. - return Type(rtt->type.getHeapType(), Nullable); + return Type(rtt->type.getHeapType(), NonNullable); case BrOnFunc: return Type::funcref; case BrOnData: @@ -1007,8 +991,7 @@ void StructNew::finalize() { if (handleUnreachableOperands(this)) { return; } - // TODO: make non-nullable when we support that - type = Type(rtt->type.getHeapType(), Nullable); + type = Type(rtt->type.getHeapType(), NonNullable); } void StructGet::finalize() { @@ -1033,8 +1016,7 @@ void ArrayNew::finalize() { type = Type::unreachable; return; } - // TODO: make non-nullable when we support that - type = Type(rtt->type.getHeapType(), Nullable); + type = Type(rtt->type.getHeapType(), NonNullable); } void ArrayGet::finalize() { @@ -1069,8 +1051,7 @@ void RefAs::finalize() { } switch (op) { case RefAsNonNull: - // FIXME: when we support non-nullable types, switch to NonNullable - type = Type(value->type.getHeapType(), Nullable); + type = Type(value->type.getHeapType(), NonNullable); break; case RefAsFunc: type = Type::funcref; |