diff --git a/src/passes/SignatureRefining.cpp b/src/passes/SignatureRefining.cpp index 792aedd9d5c..c1d72bc8d77 100644 --- a/src/passes/SignatureRefining.cpp +++ b/src/passes/SignatureRefining.cpp @@ -168,13 +168,12 @@ struct SignatureRefining : public Pass { 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 + // Continuations must not have params or results refined, because we do not + // update their users (e.g. cont.bind, resume) with new types. if (module->features.hasStackSwitching()) { for (auto type : ModuleUtils::collectHeapTypes(*module)) { if (type.isContinuation()) { - allInfo[type.getContinuation().type].canModifyParams = false; + allInfo[type.getContinuation().type].canModify = false; } } } diff --git a/test/lit/passes/signature-refining-cont.wast b/test/lit/passes/signature-refining-cont.wast new file mode 100644 index 00000000000..060dba2026e --- /dev/null +++ b/test/lit/passes/signature-refining-cont.wast @@ -0,0 +1,48 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. +;; RUN: wasm-opt %s --signature-refining -all -S -o - | filecheck %s + +;; cont.bind places restrictions on signature refining. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $A (func (result (ref null $cont-A)))) + (type $A (func (result (ref null $cont-A)))) + + ;; CHECK: (type $B (func (result (ref null $cont-A)))) + (type $B (func (result (ref null $cont-A)))) + + ;; CHECK: (type $cont-A (cont $A)) + (type $cont-A (cont $A)) + + ;; CHECK: (type $cont-B (cont $B)) + (type $cont-B (cont $B)) + ) + + ;; CHECK: (elem declare func $0) + + ;; CHECK: (func $1 (type $A) (result (ref null $cont-A)) + ;; CHECK-NEXT: (cont.bind $cont-B $cont-A + ;; CHECK-NEXT: (cont.new $cont-B + ;; CHECK-NEXT: (ref.func $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $1 (type $A) (result (ref null $cont-A)) + ;; cont.bind requires that the continuation type's results match, so we + ;; cannot refine the type $A: if we make it return an exact result, we would + ;; be binding a continuation that returns an inexact result to an exact one. + (cont.bind $cont-B $cont-A + (cont.new $cont-B + (ref.func $0) + ) + ) + ) + + ;; CHECK: (func $0 (type $B) (result (ref null $cont-A)) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $0 (type $B) (result (ref null $cont-A)) + (unreachable) + ) +) +