summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-05-10 20:06:53 -0700
committerGitHub <noreply@github.com>2021-05-10 20:06:53 -0700
commit09052c055c07ec5a1385cd5c142ff4d8534f1d1c (patch)
tree13302b7379e425d9babbf440c6eb3a31740fce14
parent5670de328320a554d4b6fa20b2fde37b4f337ce3 (diff)
downloadbinaryen-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.cpp29
-rw-r--r--src/wasm/wasm.cpp2
-rw-r--r--test/heap-types.wast16
-rw-r--r--test/heap-types.wast.from-wast36
-rw-r--r--test/heap-types.wast.fromBinary18
-rw-r--r--test/heap-types.wast.fromBinary.noDebugInfo16
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)
+ )
)