diff options
author | Alon Zakai <azakai@google.com> | 2021-05-10 20:06:53 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-10 20:06:53 -0700 |
commit | 09052c055c07ec5a1385cd5c142ff4d8534f1d1c (patch) | |
tree | 13302b7379e425d9babbf440c6eb3a31740fce14 | |
parent | 5670de328320a554d4b6fa20b2fde37b4f337ce3 (diff) | |
download | binaryen-09052c055c07ec5a1385cd5c142ff4d8534f1d1c.tar.gz binaryen-09052c055c07ec5a1385cd5c142ff4d8534f1d1c.tar.bz2 binaryen-09052c055c07ec5a1385cd5c142ff4d8534f1d1c.zip |
[Wasm GC] Fix StructSet::finalize on an unreachable value (#3874)
Also fix printing of unreachable StructSets, which must handle the case
of an unreachable reference, which means we do not know the RTT,
and so we must print a replacement for the StructSet somehow. Emit a
block with drops, fixing the old behavior which was missing the drops.
-rw-r--r-- | src/passes/Print.cpp | 29 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 2 | ||||
-rw-r--r-- | test/heap-types.wast | 16 | ||||
-rw-r--r-- | test/heap-types.wast.from-wast | 36 | ||||
-rw-r--r-- | test/heap-types.wast.fromBinary | 18 | ||||
-rw-r--r-- | test/heap-types.wast.fromBinary.noDebugInfo | 16 |
6 files changed, 98 insertions, 19 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 1392ccb6f..ef78bf582 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1926,7 +1926,7 @@ struct PrintExpressionContents // where if the ref is unreachable, we don't know what heap type to print), // then print the children in a block, which is good enough as this // instruction is never reached anyhow. - printMedium(o, "block "); + printMedium(o, "block"); } void printFieldName(HeapType type, Index index) { processFieldName(wasm, type, index, [&](Name name) { @@ -2346,6 +2346,33 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> { o << " ;; end try"; } } + void printUnreachableReplacement(Expression* curr) { + // See the parallel function in PrintExpressionContents for background. + // + // Emit a block with drops of the children. + o << "(block"; + incIndent(); + for (auto* child : ChildIterator(curr)) { + Drop drop; + drop.value = child; + printFullLine(&drop); + } + decIndent(); + } + void visitStructSet(StructSet* curr) { + if (curr->ref->type == Type::unreachable) { + printUnreachableReplacement(curr); + return; + } + visitExpression(curr); + } + void visitStructGet(StructGet* curr) { + if (curr->ref->type == Type::unreachable) { + printUnreachableReplacement(curr); + return; + } + visitExpression(curr); + } // Module-level visitors void handleSignature(Signature curr, Name name = Name()) { o << "(func"; diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 410ba0573..69464e73f 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -977,7 +977,7 @@ void StructGet::finalize() { } void StructSet::finalize() { - if (ref->type == Type::unreachable) { + if (ref->type == Type::unreachable || value->type == Type::unreachable) { type = Type::unreachable; } else { type = Type::none; diff --git a/test/heap-types.wast b/test/heap-types.wast index e932df82f..da22cc7d9 100644 --- a/test/heap-types.wast +++ b/test/heap-types.wast @@ -258,12 +258,18 @@ ) ) ) - (func $unreachables + (func $unreachables-1 (drop - (struct.get $struct.A 0 (unreachable)) - ) - (drop - (struct.set $struct.A 0 (unreachable) (unreachable)) + (struct.get $struct.C 0 (unreachable)) ) ) + (func $unreachables-2 + (struct.set $struct.C 0 (ref.null $struct.C) (unreachable)) + ) + (func $unreachables-3 + (struct.set $struct.C 0 (unreachable) (unreachable)) + ) + (func $unreachables-4 + (struct.set $struct.C 0 (unreachable) (f32.const 1)) + ) ) diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast index 4fbf5026c..fbbc47af9 100644 --- a/test/heap-types.wast.from-wast +++ b/test/heap-types.wast.from-wast @@ -1,14 +1,14 @@ (module (type $struct.A (struct (field i32) (field f32) (field $named f64))) (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A))))) + (type $none_=>_none (func)) (type $grandchild (struct (field i32) (field i64))) + (type $struct.C (struct (field $named-mut (mut f32)))) (type $vector (array (mut f64))) (type $matrix (array (mut (ref null $vector)))) (type $anyref_=>_none (func (param anyref))) (type $parent (struct )) (type $child (struct (field i32))) - (type $struct.C (struct (field $named-mut (mut f32)))) - (type $none_=>_none (func)) (type $nested-child-struct (struct (field (mut (ref $child))))) (type $rtt_1_$parent_=>_none (func (param (rtt 1 $parent)))) (type $rtt_$parent_=>_none (func (param (rtt $parent)))) @@ -307,17 +307,39 @@ ) ) ) - (func $unreachables + (func $unreachables-1 (drop - (block - (unreachable) + (block + (drop + (unreachable) + ) ) ) - (drop - (block + ) + (func $unreachables-2 + (struct.set $struct.C $named-mut + (ref.null $struct.C) + (unreachable) + ) + ) + (func $unreachables-3 + (block + (drop + (unreachable) + ) + (drop (unreachable) + ) + ) + ) + (func $unreachables-4 + (block + (drop (unreachable) ) + (drop + (f32.const 1) + ) ) ) ) diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary index 65c04bd32..4ee4be42a 100644 --- a/test/heap-types.wast.fromBinary +++ b/test/heap-types.wast.fromBinary @@ -1,14 +1,14 @@ (module (type $struct.A (struct (field i32) (field f32) (field $named f64))) (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A))))) + (type $none_=>_none (func)) (type $grandchild (struct (field i32) (field i64))) (type $vector (array (mut f64))) (type $matrix (array (mut (ref null $vector)))) + (type $struct.C (struct (field $named-mut (mut f32)))) (type $anyref_=>_none (func (param anyref))) (type $parent (struct )) (type $child (struct (field i32))) - (type $struct.C (struct (field $named-mut (mut f32)))) - (type $none_=>_none (func)) (type $nested-child-struct (struct (field (mut (ref $child))))) (type $rtt_1_$parent_=>_none (func (param (rtt 1 $parent)))) (type $rtt_$parent_=>_none (func (param (rtt $parent)))) @@ -306,7 +306,19 @@ ) ) ) - (func $unreachables + (func $unreachables-1 + (unreachable) + ) + (func $unreachables-2 + (drop + (ref.null $struct.C) + ) + (unreachable) + ) + (func $unreachables-3 + (unreachable) + ) + (func $unreachables-4 (unreachable) ) ) diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo index 2a0156000..525e265a4 100644 --- a/test/heap-types.wast.fromBinary.noDebugInfo +++ b/test/heap-types.wast.fromBinary.noDebugInfo @@ -1,14 +1,14 @@ (module (type ${i32_f32_f64} (struct (field i32) (field f32) (field f64))) (type ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref ${i32_f32_f64})) (field (mut (ref ${i32_f32_f64}))))) + (type $none_=>_none (func)) (type ${i32_i64} (struct (field i32) (field i64))) (type $[mut:f64] (array (mut f64))) (type $[mut:ref?|[mut:f64]|] (array (mut (ref null $[mut:f64])))) + (type ${mut:f32} (struct (field (mut f32)))) (type $anyref_=>_none (func (param anyref))) (type ${} (struct )) (type ${i32} (struct (field i32))) - (type ${mut:f32} (struct (field (mut f32)))) - (type $none_=>_none (func)) (type ${mut:ref|{i32}|} (struct (field (mut (ref ${i32}))))) (type $rtt_1_{}_=>_none (func (param (rtt 1 ${})))) (type $rtt_{}_=>_none (func (param (rtt ${})))) @@ -309,5 +309,17 @@ (func $8 (unreachable) ) + (func $9 + (drop + (ref.null ${mut:f32}) + ) + (unreachable) + ) + (func $10 + (unreachable) + ) + (func $11 + (unreachable) + ) ) |