From d91fb93ec514ca1134e8a8c3c3af40d3d36acf39 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 31 Mar 2026 11:02:24 -0700 Subject: [PATCH 1/2] fix --- src/tools/wasm-ctor-eval.cpp | 20 +++++++------- test/lit/ctor-eval/cont-unhandled.wast | 37 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 test/lit/ctor-eval/cont-unhandled.wast diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 78c12a5aa41..adc5a4fe988 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -1173,6 +1173,14 @@ EvalCtorOutcome evalCtor(EvallingModuleRunner& instance, std::cout << " ...stopping due to non-constant flow\n"; } break; + } else if (flow.suspendTag) { + // A suspend reached the exit of the function, so it is unhandled in + // it. TODO: We could support the case of the calling function + // handling it. + if (!quiet) { + std::cout << " ...stopping due to unhandled suspend\n"; + } + break; } if (flow.breakTo == RETURN_CALL_FLOW) { @@ -1235,18 +1243,8 @@ EvalCtorOutcome evalCtor(EvallingModuleRunner& instance, results = flow.values; if (flow.breaking()) { - if (flow.suspendTag) { - // A suspend reached the exit of the function, so it is unhandled in - // it. TODO: We could support the case of the calling function - // handling it. - if (!quiet) { - std::cout << " ...stopping due to unhandled suspend\n"; - } - return EvalCtorOutcome(); - } - // We are returning out of the function (either via a return, or via a - // break to |block|, which has the same outcome. That means we don't + // break to |block|, which has the same outcome). That means we don't // need to execute any more lines, and can consider them to be // executed. if (!quiet) { diff --git a/test/lit/ctor-eval/cont-unhandled.wast b/test/lit/ctor-eval/cont-unhandled.wast new file mode 100644 index 00000000000..e216d5c2b48 --- /dev/null +++ b/test/lit/ctor-eval/cont-unhandled.wast @@ -0,0 +1,37 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. +;; RUN: foreach %s %t wasm-ctor-eval --ctors=ctor --kept-exports=ctor,main --quiet -all -S -o - | filecheck %s + +;; Test that we properly stop precomputing at an unhandled suspend. $ctor will +;; decrement $global, and we apply that to the global. We should remove that +;; decrement from the export, which will only contain the suspend that we +;; stopped at. (After that, $main will print the same value, 99, as if we didn't +;; precompute.) + +(module + (type $i32-none (func (param i32))) + (type $none-none (func)) + + (import "fuzzing-support" "log-i32" (func $log (type $i32-none))) + + (global $global (mut i32) (i32.const 100)) + + (tag $tag (type $none-none)) + + (export "ctor" (func $ctor)) + (export "main" (func $main)) + + (func $ctor (type $none-none) + (global.set $global + (i32.sub + (global.get $global) + (i32.const 1) + ) + ) + (suspend $tag) + ) + + (func $main (type $none-none) + (global.get $global) + (call $log) + ) +) From ecaecf9aad700c787773a7fb65d10ce2d41142b3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 31 Mar 2026 11:02:47 -0700 Subject: [PATCH 2/2] test --- test/lit/ctor-eval/cont-unhandled.wast | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/lit/ctor-eval/cont-unhandled.wast b/test/lit/ctor-eval/cont-unhandled.wast index e216d5c2b48..d9db24eb44a 100644 --- a/test/lit/ctor-eval/cont-unhandled.wast +++ b/test/lit/ctor-eval/cont-unhandled.wast @@ -8,16 +8,25 @@ ;; precompute.) (module + ;; CHECK: (type $none-none (func)) + + ;; CHECK: (type $i32-none (func (param i32))) (type $i32-none (func (param i32))) (type $none-none (func)) + ;; CHECK: (import "fuzzing-support" "log-i32" (func $log (type $i32-none) (param i32))) (import "fuzzing-support" "log-i32" (func $log (type $i32-none))) + ;; CHECK: (global $global (mut i32) (i32.const 99)) (global $global (mut i32) (i32.const 100)) + ;; CHECK: (tag $tag (type $none-none)) (tag $tag (type $none-none)) (export "ctor" (func $ctor)) + ;; CHECK: (export "ctor" (func $ctor_3)) + + ;; CHECK: (export "main" (func $main)) (export "main" (func $main)) (func $ctor (type $none-none) @@ -30,8 +39,16 @@ (suspend $tag) ) + ;; CHECK: (func $main (type $none-none) + ;; CHECK-NEXT: (call $log + ;; CHECK-NEXT: (global.get $global) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) (func $main (type $none-none) (global.get $global) (call $log) ) ) +;; CHECK: (func $ctor_3 (type $none-none) +;; CHECK-NEXT: (suspend $tag) +;; CHECK-NEXT: )