Skip continuation types in SignatureRefining (#8449)
diff --git a/src/passes/SignaturePruning.cpp b/src/passes/SignaturePruning.cpp
index e048b7b..10abe59 100644
--- a/src/passes/SignaturePruning.cpp
+++ b/src/passes/SignaturePruning.cpp
@@ -199,6 +199,17 @@
allInfo[tag->type].optimizable = false;
}
+ // Continuations must not have params refined, because we do not update
+ // their users (e.g. cont.bind, resume) with new types.
+ // TODO: support refining continuations
+ if (module->features.hasStackSwitching()) {
+ for (auto type : ModuleUtils::collectHeapTypes(*module)) {
+ if (type.isContinuation()) {
+ allInfo[type.getContinuation().type].optimizable = false;
+ }
+ }
+ }
+
// Signature-called functions must also not be modified.
// TODO: Explore whether removing parameters from the end could be
// beneficial (check if it does not regress call performance with JS).
diff --git a/test/lit/passes/signature-pruning.wast b/test/lit/passes/signature-pruning.wast
index 30ddd25..d86e855 100644
--- a/test/lit/passes/signature-pruning.wast
+++ b/test/lit/passes/signature-pruning.wast
@@ -1269,3 +1269,84 @@
)
)
)
+
+(module
+ ;; If a signature is used in a continuation, we cannot refine its parameters,
+ ;; as we do not yet support updating continuation instructions with new types.
+ (rec
+ ;; CHECK: (rec
+ ;; CHECK-NEXT: (type $cont (cont $sig))
+
+ ;; CHECK: (type $1 (func))
+
+ ;; CHECK: (type $other (func))
+
+ ;; CHECK: (type $sig (func (param anyref)))
+ (type $sig (func (param anyref)))
+ (type $other (func (param anyref)))
+ (type $cont (cont $sig))
+ )
+ ;; CHECK: (elem declare func $cont $not-cont $other)
+
+ ;; CHECK: (func $cont (type $sig) (param $0 anyref)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $cont (type $sig) (param anyref)
+ ;; The param is unused here, and in all functions below, so we want to
+ ;; remove it where possible.
+ (nop)
+ )
+
+ ;; CHECK: (func $not-cont (type $sig) (param $0 anyref)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $not-cont (type $sig) (param anyref)
+ ;; This function cannot be optimized even though it is not used in a
+ ;; continuation. It is enough that it shares a type with a continuation
+ ;; function.
+ (nop)
+ )
+
+ ;; CHECK: (func $other (type $other)
+ ;; CHECK-NEXT: (local $0 anyref)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (ref.null none)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $other (type $other) (param anyref)
+ ;; This function uses a different type, so it can be optimized.
+ (nop)
+ )
+
+
+ ;; CHECK: (func $test (type $1)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (cont.new $cont
+ ;; CHECK-NEXT: (ref.func $cont)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call_ref $sig
+ ;; CHECK-NEXT: (ref.null none)
+ ;; CHECK-NEXT: (ref.func $not-cont)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call_ref $other
+ ;; CHECK-NEXT: (ref.func $other)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $test
+ (drop
+ (cont.new $cont
+ (ref.func $cont)
+ )
+ )
+ (call_ref $sig
+ (ref.null none)
+ (ref.func $not-cont)
+ )
+ (call_ref $other
+ (ref.null none)
+ (ref.func $other)
+ )
+ )
+)
diff --git a/test/lit/passes/signature-refining.wast b/test/lit/passes/signature-refining.wast
index 26550a6..03742ca 100644
--- a/test/lit/passes/signature-refining.wast
+++ b/test/lit/passes/signature-refining.wast
@@ -1212,7 +1212,7 @@
(func $not-cont (type $sig) (param anyref)
;; This function cannot be optimized even though it is not used in a
;; continuation. It is enough that it shares a type with a continuation
- ;;function.
+ ;; function.
(nop)
)