1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
;; Pre-existing imports that the pass turns into the implementations.
(module
(memory 1 2)
(import "asyncify" "start_unwind" (func $asyncify_start_unwind (param i32)))
(import "asyncify" "stop_unwind" (func $asyncify_stop_unwind))
(import "asyncify" "start_rewind" (func $asyncify_start_rewind (param i32)))
(import "asyncify" "stop_rewind" (func $asyncify_stop_rewind))
(global $sleeping (mut i32) (i32.const 0))
;; do a sleep operation: start a sleep if running, or resume after a sleep
;; if we just rewound.
(func $do_sleep
(if
(i32.eqz (global.get $sleeping))
(block
(global.set $sleeping (i32.const 1))
;; we should set up the data at address 4 around here
(call $asyncify_start_unwind (i32.const 4))
)
(block
(global.set $sleeping (i32.const 0))
(call $asyncify_stop_rewind)
)
)
)
;; a function that does some work and has a sleep (async pause/resume) in the middle
(func $work
(call $stuff) ;; do some work
(call $do_sleep) ;; take a break
(call $stuff) ;; do some more work
)
(func $stuff)
;; the first event called from the main event loop: just call into $work
(func $first_event
(call $work)
;; work will sleep, so we exit through here while it is paused
)
;; the second event called from the main event loop: to resume $work,
;; stop the unwind, then prepare a rewind, and initiate it by doing
;; the call to rewind the call stack back up to where it was
(func $second_event
(call $asyncify_stop_unwind)
(call $asyncify_start_rewind (i32.const 4))
(call $work)
)
;; a function that can't do a sleep
(func $never_sleep
(call $stuff)
(call $stuff)
(call $stuff)
)
)
;; Calls to imports that will call into asyncify themselves.
(module
(memory 1 2)
(import "env" "import" (func $import))
(import "env" "import2" (func $import2 (result i32)))
(import "env" "import3" (func $import3 (param i32)))
(import "env" "import-mv" (func $import-mv (result i32 i64)))
(func $calls-import
(call $import)
)
(func $calls-import2 (result i32)
(local $temp i32)
(local.set $temp (call $import2))
(return (local.get $temp))
)
(func $calls-import2-drop
(drop (call $import2))
)
(func $calls-nothing
(drop (i32.eqz (i32.const 17)))
)
(func $many-locals (param $x i32) (result i32)
(local $y i32)
(local $z (f32 i64))
(loop $l
(local.set $x
(i32.add (local.get $y) (i32.const 1))
)
(local.set $y
(i32.div_s (local.get $x) (i32.const 3))
)
(br_if $l (local.get $y))
)
(call $import)
(return (local.get $y))
)
(func $calls-import2-if (param $x i32)
(if (local.get $x)
(call $import)
)
)
(func $calls-import2-if-else (param $x i32)
(if (local.get $x)
(call $import3 (i32.const 1))
(call $import3 (i32.const 2))
)
)
(func $calls-import2-if-else-oneside (param $x i32) (result i32)
(if (local.get $x)
(return (i32.const 1))
(call $import3 (i32.const 2))
)
(return (i32.const 3))
)
(func $calls-import2-if-else-oneside2 (param $x i32) (result i32)
(if (local.get $x)
(call $import3 (i32.const 1))
(return (i32.const 2))
)
(return (i32.const 3))
)
(func $calls-mv
(local $x (i32 i64))
(local.set $x (call $import-mv))
)
(func $calls-loop (param $x i32)
(loop $l
(call $import3 (i32.const 1))
(local.set $x
(i32.add (local.get $x) (i32.const 1))
)
(br_if $l
(local.get $x)
)
)
)
(func $calls-loop2
(loop $l
(br_if $l
(call $import2)
)
)
)
(func $calls-mix
(call $boring)
(call $import)
(call $boring)
(call $import)
)
(func $boring)
(func $calls-mix-deep
(call $boring-deep)
(call $import-deep)
(call $boring)
(call $import)
)
(func $boring-deep
(call $boring)
)
(func $import-deep
(call $import)
)
)
;; empty module, in particular with no memory
(module
)
|