| ;; 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-i32" (func $log (param i32))) | |
| (tag $more) | |
| (tag $more-i32 (result i32)) | |
| (table $table 10 10 funcref) | |
| (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] export 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] export 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] export 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] export 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] export 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] export 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] export 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] export 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] export 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] export 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] export 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] export 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] export 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] export 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] export 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)) | |
| ) | |
| ) | |
| (func $calls | |
| ;; Suspend before and after calling a child, who also suspends. | |
| (local $x i32) | |
| ;; Set a value here to check that we do not get confused between locals in | |
| ;; different scopes. | |
| (local.set $x (i32.const -1)) | |
| (suspend $more) | |
| (call $calls-child (i32.const 41)) | |
| (suspend $more) | |
| (call $calls-child (i32.const 1336)) | |
| (suspend $more) | |
| (call $log (local.get $x)) | |
| ) | |
| (func $calls-child (param $x i32) | |
| (suspend $more) | |
| (local.set $x | |
| (i32.add | |
| (local.get $x) | |
| (i32.const 1) | |
| ) | |
| ) | |
| (suspend $more) | |
| (call $log (local.get $x)) | |
| (suspend $more) | |
| ) | |
| ;; CHECK: [fuzz-exec] export run-calls | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 100] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 42] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 1337] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging -1] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 300] | |
| (func $run-calls (export "run-calls") | |
| (call $run | |
| (cont.new $k (ref.func $calls)) | |
| ) | |
| ) | |
| (func $call_indirect | |
| ;; Test that indirect calls go to the right place, even if we modify the | |
| ;; table in between. | |
| (table.set $table | |
| (i32.const 7) | |
| (ref.func $call_indirect-child) | |
| ) | |
| (call $log (i32.const -1)) | |
| (call_indirect (type $f) | |
| (i32.const 7) | |
| ) | |
| (call $log (i32.const -2)) | |
| ) | |
| (func $call_indirect-child | |
| ;; When we resume the suspend below, the table entry will have null, but we | |
| ;; should still rewind the stack properly. | |
| (call $log (i32.const -10)) | |
| (call $log | |
| (ref.is_null | |
| (table.get $table | |
| (i32.const 7) | |
| ) | |
| ) | |
| ) | |
| (table.set $table | |
| (i32.const 7) | |
| (ref.null func) | |
| ) | |
| (suspend $more) | |
| (call $log (i32.const -20)) | |
| (call $log | |
| (ref.is_null | |
| (table.get $table | |
| (i32.const 7) | |
| ) | |
| ) | |
| ) | |
| (suspend $more) | |
| ) | |
| ;; CHECK: [fuzz-exec] export run-call_indirect | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 100] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging -1] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging -10] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 0] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging -20] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 1] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging -2] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 300] | |
| (func $run-call_indirect (export "run-call_indirect") | |
| (call $run | |
| (cont.new $k (ref.func $call_indirect)) | |
| ) | |
| ) | |
| (func $call_ref | |
| (suspend $more) | |
| (call_ref $f | |
| (ref.func $call_ref-child) | |
| ) | |
| (suspend $more) | |
| ) | |
| (func $call_ref-child | |
| (suspend $more) | |
| (call $log (i32.const -20)) | |
| (suspend $more) | |
| ) | |
| ;; CHECK: [fuzz-exec] export run-call_ref | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 100] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging -20] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 300] | |
| (func $run-call_ref (export "run-call_ref") | |
| (call $run | |
| (cont.new $k (ref.func $call_ref)) | |
| ) | |
| ) | |
| (func $bind (param $x i32) | |
| ;; Test that cont.bind works when used on this. | |
| (suspend $more) | |
| (call $log (local.get $x)) | |
| (suspend $more) | |
| ;; Test that the bound arguments do not get applied to child calls. | |
| (call $bind-child | |
| (i32.const 1337) | |
| ) | |
| (suspend $more) | |
| ) | |
| (func $bind-child (param $x i32) | |
| (suspend $more) | |
| (call $log (local.get $x)) | |
| (suspend $more) | |
| ) | |
| ;; CHECK: [fuzz-exec] export run-bind | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 100] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 42] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 1337] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 200] | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 300] | |
| (func $run-bind (export "run-bind") | |
| (call $run | |
| (cont.bind $k-get-i32 $k | |
| (i32.const 42) | |
| (cont.new $k-get-i32 (ref.func $bind)) | |
| ) | |
| ) | |
| ) | |
| (func $never | |
| ;; This will be resume_throw'd on the first execution, so this code is never | |
| ;; reached. | |
| (call $log (i32.const 1337)) | |
| ) | |
| ;; CHECK: [fuzz-exec] export resume_throw-never | |
| ;; CHECK-NEXT: [LoggingExternalInterface logging 42] | |
| (func $resume_throw-never (export "resume_throw-never") | |
| (block $more | |
| (try_table (catch $more $more) | |
| (resume_throw $k $more | |
| (cont.new $k (ref.func $never)) | |
| ) | |
| ) | |
| ) | |
| ;; This will be reached. | |
| (call $log (i32.const 42)) | |
| ) | |
| ;; CHECK: [fuzz-exec] export suspend-unhandled-block | |
| ;; CHECK-NEXT: [exception thrown: unhandled suspend] | |
| (func $suspend-unhandled-block (export "suspend-unhandled-block") | |
| ;; The nop here means that we are inside a block. The block will try to save | |
| ;; resume data, but we should skip that without erroring, and just report an | |
| ;; unhandled suspend. | |
| (suspend $more) | |
| (nop) | |
| ) | |
| ) |