blob: ca568b5eec4c293837fb3ee3bc1cd0467c3d76bf [file] [log] [blame] [edit]
;; 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
(module
(type $f (func))
(type $k (cont $f))
(type $f-i32 (func (result i32)))
(type $k-i32 (cont $f-i32))
(type $f-get-i32 (func (param i32)))
(type $k-get-i32 (cont $f-get-i32))
(import "fuzzing-support" "log" (func $log (param i32)))
(tag $more)
(tag $more-i32 (result i32))
(func $run (param $k (ref $k))
;; Run a coroutine, continuing to resume it until it is complete.
(call $log (i32.const 100)) ;; start
(loop $loop
(block $on (result (ref $k))
(resume $k (on $more $on)
(local.get $k)
)
(call $log (i32.const 300)) ;; stop
(return)
)
(call $log (i32.const 200)) ;; continue
(local.set $k)
(br $loop)
)
(unreachable)
)
;; A coroutine with only control flow in a single basic block (no locals, no
;; params, no branching, no value stack). When $run-block, below, runs this,
;; the result should be to log -1, -2, -3 (with interleaved logging from
;; $run itself, above, 100, 200, 200, 300).
(func $block
(call $log (i32.const -1))
(suspend $more)
(call $log (i32.const -2))
(suspend $more)
(call $log (i32.const -3))
)
;; CHECK: [fuzz-exec] calling run-block
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging -1]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -2]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -3]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-block (export "run-block")
(call $run
(cont.new $k (ref.func $block))
)
)
;; Nested blocks, so when we suspend/resume we must traverse that stack
;; properly.
(func $block-nested
(block $a
(call $log (i32.const -1))
(suspend $more)
(block $b
(block $c
(call $log (i32.const -2))
(suspend $more)
(call $log (i32.const -3))
)
(call $log (i32.const -4))
)
(suspend $more)
(call $log (i32.const -5))
(suspend $more)
)
(call $log (i32.const -6))
)
;; CHECK: [fuzz-exec] calling run-block-nested
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging -1]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -2]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -3]
;; CHECK-NEXT: [LoggingExternalInterface logging -4]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -5]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -6]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-block-nested (export "run-block-nested")
(call $run
(cont.new $k (ref.func $block-nested))
)
)
;; The local's state must be saved and restored.
(func $local
(local $x i32)
(local.set $x (i32.const 42))
(suspend $more)
(call $log (local.get $x))
(local.set $x (i32.const 1337))
(suspend $more)
(call $log (local.get $x))
)
;; CHECK: [fuzz-exec] calling run-local
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 42]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 1337]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-local (export "run-local")
(call $run
(cont.new $k (ref.func $local))
)
)
(func $multi-locals
(local $i32 i32)
(local $f64 f64)
(local.set $i32 (i32.const 42))
(local.set $f64 (f64.const 3.14159))
(suspend $more)
(call $log
(local.get $i32)
)
(call $log
(i32.trunc_f64_s
(local.get $f64)
)
)
)
;; CHECK: [fuzz-exec] calling run-multi-locals
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 42]
;; CHECK-NEXT: [LoggingExternalInterface logging 3]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-multi-locals (export "run-multi-locals")
(call $run
(cont.new $k (ref.func $multi-locals))
)
)
;; This loop should suspend 4 times and log 3, 2, 1, 0.
(func $loop
(local $x i32)
(local.set $x (i32.const 4))
(loop $loop
(local.set $x
(i32.sub
(local.get $x)
(i32.const 1)
)
)
(call $log (local.get $x))
(suspend $more)
(br_if $loop
(local.get $x)
)
)
)
;; CHECK: [fuzz-exec] calling run-loop
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 3]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 2]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 1]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-loop (export "run-loop")
(call $run
(cont.new $k (ref.func $loop))
)
)
;; We should log -1, -2, -3, -4
(func $if
(local $x i32)
(if
(local.get $x)
(then
(unreachable)
)
(else
;; We should get here.
(call $log (i32.const -1))
(local.set $x (i32.const 1))
(suspend $more)
;; A nested if.
(if
(local.get $x)
(then
;; We should get here
(suspend $more)
(call $log (i32.const -2))
)
(else
(unreachable)
)
)
)
)
;; If with one arm.
(if
(local.get $x)
(then
;; We should get here.
(call $log (i32.const -3))
(suspend $more)
(call $log (i32.const -4))
)
)
(if
(i32.eqz
(local.get $x)
)
(then
(unreachable)
)
)
)
;; CHECK: [fuzz-exec] calling run-if
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging -1]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -2]
;; CHECK-NEXT: [LoggingExternalInterface logging -3]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -4]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-if (export "run-if")
(call $run
(cont.new $k (ref.func $if))
)
)
;; Suspend in the if's condition.
(func $if-condition
(if
(block (result i32)
(call $log (i32.const -1))
(suspend $more)
(call $log (i32.const -2))
(i32.const 1)
)
(then
(call $log (i32.const -3))
)
)
)
;; CHECK: [fuzz-exec] calling run-if-condition
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging -1]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -2]
;; CHECK-NEXT: [LoggingExternalInterface logging -3]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-if-condition (export "run-if-condition")
(call $run
(cont.new $k (ref.func $if-condition))
)
)
;; Check that we properly stash things on the value stack.
(func $value-stack
;; Suspend on the left. No value is actually saved on the stack, as we
;; resume before we execute the right side.
(call $log
(i32.sub ;; 1 - 2 => -1
(block (result i32)
(suspend $more)
(i32.const 1)
)
(i32.const 2)
)
)
;; On the right. Now we save the 2 when we suspend.
(call $log
(i32.sub ;; 2 - 4 => -2
(i32.const 2)
(block (result i32)
(suspend $more)
(i32.const 4)
)
)
)
;; Both sides suspend.
(call $log
(i32.sub ;; 3 - 6 => -3
(block (result i32)
(suspend $more)
(i32.const 3)
)
(block (result i32)
(suspend $more)
(i32.const 6)
)
)
)
)
;; CHECK: [fuzz-exec] calling run-value-stack
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -1]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -2]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -3]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-value-stack (export "run-value-stack")
(call $run
(cont.new $k (ref.func $value-stack))
)
)
(func $nested-unary
;; Suspend at the top.
(call $log
(i32.eqz
(i32.eqz
(i32.eqz
(block (result i32)
(suspend $more)
(i32.const 1)
)
)
)
)
)
;; Suspend everywhere.
(call $log
(block (result i32)
(suspend $more)
(i32.eqz
(block (result i32)
(suspend $more)
(i32.eqz
(block (result i32)
(suspend $more)
(i32.eqz
(block (result i32)
(suspend $more)
(i32.const 0)
)
)
)
)
)
)
)
)
)
;; CHECK: [fuzz-exec] calling run-nested-unary
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 1]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-nested-unary (export "run-nested-unary")
(call $run
(cont.new $k (ref.func $nested-unary))
)
)
(func $nested-unary-more
(local $temp i32)
;; Suspend before and after each operation.
(call $log
(block (result i32)
i32.const 0
suspend $more
i32.eqz
suspend $more
i32.eqz
suspend $more
i32.eqz
suspend $more
)
)
)
;; CHECK: [fuzz-exec] calling run-nested-unary-more
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 1]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-nested-unary-more (export "run-nested-unary-more")
(call $run
(cont.new $k (ref.func $nested-unary-more))
)
)
(func $nested-binary
(local $temp i32)
;; Both sides suspend, in different places.
(call $log ;; (2 + 1) - (4 + 2) => -3
(i32.sub
(block (result i32)
(i32.add
(block (result i32)
(suspend $more)
(i32.const 2)
)
(i32.const 1)
)
)
(block (result i32)
(suspend $more)
(i32.add
(i32.const 4)
(i32.const 2)
)
)
)
)
;; Ditto, but with suspensions moved in the arms, and others on the
;; outside. Also add 1.
(call $log
(block (result i32)
(suspend $more)
(local.set $temp
(i32.sub
(block (result i32)
(suspend $more)
(i32.add
(i32.const 3)
(i32.const 1)
)
)
(block (result i32)
(i32.add
(i32.const 4)
(block (result i32)
(suspend $more)
(i32.const 2)
)
)
)
)
)
(suspend $more)
(local.get $temp)
)
)
)
;; CHECK: [fuzz-exec] calling run-nested-binary
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -3]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging -2]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-nested-binary (export "run-nested-binary")
(call $run
(cont.new $k (ref.func $nested-binary))
)
)
(func $trinary
;; Suspend in one of the arms.
(call $log
(select
(block (result i32)
(suspend $more)
(i32.const 1)
)
(i32.const 2)
(i32.const 3)
)
)
(call $log
(select
(i32.const 4)
(block (result i32)
(suspend $more)
(i32.const 5)
)
(i32.const 6)
)
)
(call $log
(select
(i32.const 7)
(i32.const 8)
(block (result i32)
(suspend $more)
(i32.const 9)
)
)
)
;; Suspend in them all.
(call $log
(select
(block (result i32)
(suspend $more)
(i32.const 10)
)
(block (result i32)
(suspend $more)
(i32.const 11)
)
(block (result i32)
(suspend $more)
(i32.const 12)
)
)
)
)
;; CHECK: [fuzz-exec] calling run-trinary
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 1]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 4]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 7]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 10]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-trinary (export "run-trinary")
(call $run
(cont.new $k (ref.func $trinary))
)
)
(func $run-i32 (param $k-i32 (ref $k-i32)) (result i32)
;; As $run, but the coroutine returns an i32.
(call $log (i32.const 100)) ;; start
(loop $loop
(block $on (result (ref $k-i32))
(resume $k-i32 (on $more $on)
(local.get $k-i32)
)
(call $log (i32.const 300)) ;; stop
(return)
)
(call $log (i32.const 200)) ;; continue
(local.set $k-i32)
(br $loop)
)
(unreachable)
)
(func $ret-i32 (result i32)
;; Just immediately return.
(i32.const 42)
)
;; CHECK: [fuzz-exec] calling run-ret-i32
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
;; CHECK-NEXT: [fuzz-exec] note result: run-ret-i32 => 42
(func $run-ret-i32 (export "run-ret-i32") (result i32)
(call $run-i32
(cont.new $k-i32 (ref.func $ret-i32))
)
)
(func $pause-i32 (result i32)
(local $x i32)
;; Pause before returning.
(local.set $x
(i32.const 1336)
)
(suspend $more)
(i32.add
(local.get $x)
(i32.const 1)
)
)
;; CHECK: [fuzz-exec] calling run-pause-i32
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
;; CHECK-NEXT: [fuzz-exec] note result: run-pause-i32 => 1337
(func $run-pause-i32 (export "run-pause-i32") (result i32)
(call $run-i32
(cont.new $k-i32 (ref.func $pause-i32))
)
)
(func $run-get-i32 (param $x i32) (param $k-get-i32 (ref $k-get-i32))
;; As $run, but the coroutine receives an i32.
(call $log (i32.const 100)) ;; start
(loop $loop
(block $on (result (ref $k-get-i32))
(resume $k-get-i32 (on $more-i32 $on)
(local.get $x)
(local.get $k-get-i32)
)
(call $log (i32.const 300)) ;; stop
(return)
)
(call $log (i32.const 200)) ;; continue
;; Modify $x, so we can see differences in the loggings.
(local.set $x
(i32.sub
(local.get $x)
(i32.const 1)
)
)
(local.set $k-get-i32)
(br $loop)
)
(unreachable)
)
(func $param (param $x i32)
(call $log (local.get $x))
(local.set $x
(i32.add
(local.get $x)
(i32.const 1295)
)
)
(call $log (suspend $more-i32))
(call $log (local.get $x))
(call $log (suspend $more-i32))
)
;; CHECK: [fuzz-exec] calling run-param
;; CHECK-NEXT: [LoggingExternalInterface logging 100]
;; CHECK-NEXT: [LoggingExternalInterface logging 42]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 41]
;; CHECK-NEXT: [LoggingExternalInterface logging 1337]
;; CHECK-NEXT: [LoggingExternalInterface logging 200]
;; CHECK-NEXT: [LoggingExternalInterface logging 40]
;; CHECK-NEXT: [LoggingExternalInterface logging 300]
(func $run-param (export "run-param")
(call $run-get-i32
(i32.const 42)
(cont.new $k-get-i32 (ref.func $param))
)
)
)