diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index 597d04d2357..24e42cf1c42 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -1277,7 +1277,7 @@ struct InfoCollector } } } - void visitThrow(Throw* curr) { + template void handleThrow(T* curr) { auto& operands = curr->operands; if (!isRelevant(operands)) { return; @@ -1289,6 +1289,7 @@ struct InfoCollector {ExpressionLocation{operands[i], 0}, TagLocation{tag, i}}); } } + void visitThrow(Throw* curr) { handleThrow(curr); } void visitRethrow(Rethrow* curr) {} void visitThrowRef(ThrowRef* curr) {} @@ -1390,7 +1391,10 @@ struct InfoCollector } void visitResume(Resume* curr) { handleResume(curr); } - void visitResumeThrow(ResumeThrow* curr) { handleResume(curr); } + void visitResumeThrow(ResumeThrow* curr) { + handleResume(curr); + handleThrow(curr); + } void visitStackSwitch(StackSwitch* curr) { // TODO: optimize when possible addRoot(curr); diff --git a/test/lit/passes/gufa-eh.wast b/test/lit/passes/gufa-eh.wast index d4e30473d81..c7211e531b1 100644 --- a/test/lit/passes/gufa-eh.wast +++ b/test/lit/passes/gufa-eh.wast @@ -58,3 +58,63 @@ ) ) ) + +(module + ;; CHECK: (type $func (func)) + (type $func (func)) + ;; CHECK: (type $cont (cont $func)) + (type $cont (cont $func)) + + ;; CHECK: (type $2 (func (param i32))) + + ;; CHECK: (type $3 (func (result i32))) + + ;; CHECK: (elem declare func $func) + + ;; CHECK: (tag $tag (type $2) (param i32)) + (tag $tag (param i32)) + + ;; CHECK: (export "handle" (func $handle)) + + ;; CHECK: (func $func (type $func) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $func (type $func) + (nop) + ) + + ;; CHECK: (func $handle (type $3) (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block $block (result i32) + ;; CHECK-NEXT: (try_table (catch $tag $block) + ;; CHECK-NEXT: (resume_throw $cont $tag + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (cont.new $cont + ;; CHECK-NEXT: (ref.func $func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + (func $handle (export "handle") (result i32) + ;; Resume a new continuation and throw inside it immediately. We handle the + ;; exception in the try_table, returning 42. GUFA should not think we do not + ;; handle it (if it did, it would add an unreachable and trap). This tests + ;; that we see that resume_throw sends values to the tag, like a throw. + (block $block (result i32) + (try_table (catch $tag $block) + (resume_throw $cont $tag + (i32.const 42) + (cont.new $cont + (ref.func $func) + ) + ) + (unreachable) + ) + ) + ) +) +