summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cfg/liveness-traversal.h11
-rw-r--r--test/lit/passes/coalesce-locals-gc.wast28
2 files changed, 38 insertions, 1 deletions
diff --git a/src/cfg/liveness-traversal.h b/src/cfg/liveness-traversal.h
index d9b310d6f..650ee4f47 100644
--- a/src/cfg/liveness-traversal.h
+++ b/src/cfg/liveness-traversal.h
@@ -152,7 +152,16 @@ struct LivenessWalker : public CFGWalker<SubType, VisitorType, Liveness> {
// if it has side effects)
if (!self->currBasicBlock) {
if (curr->isTee()) {
- *currp = curr->value;
+ // We can remove the tee, but must leave something of the exact same
+ // type.
+ auto originalType = curr->type;
+ if (originalType != curr->value->type) {
+ *currp =
+ Builder(*self->getModule()).makeBlock({curr->value}, originalType);
+ } else {
+ // No special handling, just use the value.
+ *currp = curr->value;
+ }
} else {
*currp = Builder(*self->getModule()).makeDrop(curr->value);
}
diff --git a/test/lit/passes/coalesce-locals-gc.wast b/test/lit/passes/coalesce-locals-gc.wast
index 1a830b4a5..38840f1ea 100644
--- a/test/lit/passes/coalesce-locals-gc.wast
+++ b/test/lit/passes/coalesce-locals-gc.wast
@@ -250,4 +250,32 @@
)
)
)
+
+ ;; CHECK: (func $replace-struct-param (type $f64_ref?|$A|_=>_f32) (param $0 f64) (param $1 (ref null $A)) (result f32)
+ ;; CHECK-NEXT: (call $replace-struct-param
+ ;; CHECK-NEXT: (block (result f64)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (ref.cast null $A
+ ;; CHECK-NEXT: (block (result (ref null $A))
+ ;; CHECK-NEXT: (struct.new_default $A)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $replace-struct-param (param $unused f64) (param $A (ref null $A)) (result f32)
+ ;; As above, but now the value is a struct reference and it is on a local.tee.
+ ;; Again, we should replace the local operation with something of identical
+ ;; type to avoid a validation error.
+ (call $replace-struct-param
+ (block (result f64)
+ (unreachable)
+ )
+ (ref.cast null $A
+ (local.tee $A
+ (struct.new_default $A)
+ )
+ )
+ )
+ )
)