;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited.
;; RUN: foreach %s %t wasm-opt -all --fuzz-exec-before -q -o /dev/null 2>&1 | filecheck %s
;; Test suspend/resume through a return call. $cont return_calls $sub, which
;; then suspends. The return_call removes $cont from the stack before that
;; suspend, so we should jump into $sub during resuming, and not hit any errors.
(module
(type $i32 (func (result i32)))
(type $cont (cont $i32))
(type $none (func))
(import "fuzzing-support" "log-i32" (func $log (param i32)))
(tag $tag (type $none))
;; CHECK: [fuzz-exec] export main
;; CHECK-NEXT: [LoggingExternalInterface logging 50]
;; CHECK-NEXT: [LoggingExternalInterface logging -1]
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -1]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
;; CHECK-NEXT: [LoggingExternalInterface logging 400]
;; CHECK-NEXT: [LoggingExternalInterface logging -1]
;; CHECK-NEXT: [LoggingExternalInterface logging 500]
;; CHECK-NEXT: [trap unreachable]
(func $main (export "main")
(local $c (ref $cont))
;; Create a continuation and keep resuming it while it suspends.
(local.set $c
(cont.new $cont
(ref.func $cont)
)
)
(loop $label
(local.set $c
(block $block (result (ref $cont))
(drop
(resume $cont (on $tag $block)
(local.get $c)
)
)
(unreachable)
)
)
(call $log (i32.const -1)) ;; logged each time we suspend
(br $label)
)
)
(func $cont (type $i32) (result i32)
(call $log (i32.const 50)) ;; only reached once
(suspend $tag)
(call $log (i32.const 100)) ;; only reached once
(return_call $sub)
(call $log (i32.const -100)) ;; never reached
)
(func $sub (result i32)
(call $log (i32.const 200))
(suspend $tag)
(call $log (i32.const 300))
(return_call $subsub)
)
(func $subsub (result i32)
(call $log (i32.const 400))
(suspend $tag)
(call $log (i32.const 500))
(i32.const 0)
)
)