summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-06-15 12:04:16 -0700
committerGitHub <noreply@github.com>2019-06-15 12:04:16 -0700
commit1cd34c211dffa66fa2f2e45f3f9291e8ad836e07 (patch)
tree74fc2c7c15872d2c23d8b7eed7865486069549ce /test
parent22ba24118ef04720e6c7605dbaf90b22cdba006f (diff)
downloadbinaryen-1cd34c211dffa66fa2f2e45f3f9291e8ad836e07.tar.gz
binaryen-1cd34c211dffa66fa2f2e45f3f9291e8ad836e07.tar.bz2
binaryen-1cd34c211dffa66fa2f2e45f3f9291e8ad836e07.zip
Bysyncify: async transform for wasm (#2172)
This adds a new pass, Bysyncify, which transforms code to allow unwind and rewinding the call stack and local state. This allows things like coroutines, turning synchronous code asynchronous, etc. The new pass file itself has a large comment on top with docs. So far the tests here seem to show this works, but this hasn't been tested heavily yet. My next step is to hook this up to emscripten as a replacement for asyncify/emterpreter, see emscripten-core/emscripten#8561 Note that this is completely usable by itself, so it could be useful for any language that needs coroutines etc., and not just ones using LLVM and/or emscripten. See docs on the ABI in the pass source.
Diffstat (limited to 'test')
-rw-r--r--test/passes/bysyncify.txt2710
-rw-r--r--test/passes/bysyncify.wast146
-rw-r--r--test/passes/bysyncify_optimize-level=1.txt1541
-rw-r--r--test/passes/bysyncify_optimize-level=1.wast97
-rw-r--r--test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.txt1998
-rw-r--r--test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.wast146
-rw-r--r--test/unit/input/bysyncify.js155
-rw-r--r--test/unit/input/bysyncify.wast200
-rw-r--r--test/unit/test_bysyncify.py20
9 files changed, 7013 insertions, 0 deletions
diff --git a/test/passes/bysyncify.txt b/test/passes/bysyncify.txt
new file mode 100644
index 000000000..1ec35057e
--- /dev/null
+++ b/test/passes/bysyncify.txt
@@ -0,0 +1,2710 @@
+(module
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$v (func))
+ (memory $0 1 2)
+ (global $sleeping (mut i32) (i32.const 0))
+ (global $__bysyncify_state (mut i32) (i32.const 0))
+ (global $__bysyncify_data (mut i32) (i32.const 0))
+ (export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
+ (export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
+ (func $do_sleep (; 0 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -8)
+ )
+ )
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (local.get $4)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $4)
+ )
+ )
+ )
+ )
+ (local.set $2
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (block
+ (local.set $0
+ (global.get $sleeping)
+ )
+ (local.set $1
+ (i32.eqz
+ (local.get $0)
+ )
+ )
+ )
+ )
+ (nop)
+ (block
+ (if
+ (i32.or
+ (local.get $1)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (global.set $sleeping
+ (i32.const 1)
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $3)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $bysyncify_start_unwind
+ (i32.const 4)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (i32.eqz
+ (local.get $1)
+ )
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (block
+ (global.set $sleeping
+ (i32.const 0)
+ )
+ (call $bysyncify_stop_rewind)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $2)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $5
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $5)
+ (local.get $0)
+ )
+ (i32.store offset=4
+ (local.get $5)
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ (func $work (; 1 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $stuff)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $do_sleep)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $stuff)
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $stuff (; 2 ;) (type $FUNCSIG$v)
+ (nop)
+ )
+ (func $first_event (; 3 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $work)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $second_event (; 4 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $bysyncify_start_rewind
+ (i32.const 4)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $work)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $never_sleep (; 5 ;) (type $FUNCSIG$v)
+ (call $stuff)
+ (call $stuff)
+ (call $stuff)
+ )
+ (func $bysyncify_start_unwind (; 6 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 7 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 2)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_stop_rewind (; 8 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+)
+(module
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$ii (func (param i32) (result i32)))
+ (import "env" "import" (func $import))
+ (import "env" "import2" (func $import2 (result i32)))
+ (import "env" "import3" (func $import3 (param i32)))
+ (memory $0 1 2)
+ (global $__bysyncify_state (mut i32) (i32.const 0))
+ (global $__bysyncify_data (mut i32) (i32.const 0))
+ (export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
+ (export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
+ (func $calls-import (; 3 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $calls-import2 (; 4 ;) (type $FUNCSIG$i) (result i32)
+ (local $temp i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (local $8 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -20)
+ )
+ )
+ (local.set $7
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $temp
+ (i32.load
+ (local.get $7)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $7)
+ )
+ )
+ (local.set $2
+ (i32.load offset=8
+ (local.get $7)
+ )
+ )
+ (local.set $3
+ (i32.load offset=12
+ (local.get $7)
+ )
+ )
+ (local.set $4
+ (i32.load offset=16
+ (local.get $7)
+ )
+ )
+ )
+ )
+ (local.set $5
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $6
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $6)
+ (i32.const 0)
+ )
+ )
+ (block
+ (local.set $2
+ (call $import2)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (return
+ (local.get $2)
+ )
+ )
+ )
+ (unreachable)
+ )
+ (unreachable)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $5)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $8
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $8)
+ (local.get $temp)
+ )
+ (i32.store offset=4
+ (local.get $8)
+ (local.get $1)
+ )
+ (i32.store offset=8
+ (local.get $8)
+ (local.get $2)
+ )
+ (i32.store offset=12
+ (local.get $8)
+ (local.get $3)
+ )
+ (i32.store offset=16
+ (local.get $8)
+ (local.get $4)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 20)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-import2-drop (; 5 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (local.get $3)
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $2
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $2)
+ (i32.const 0)
+ )
+ )
+ (block
+ (local.set $0
+ (call $import2)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $4)
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ )
+ (func $calls-nothing (; 6 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local.set $0
+ (i32.eqz
+ (i32.const 17)
+ )
+ )
+ )
+ (func $many-locals (; 7 ;) (type $FUNCSIG$ii) (param $x i32) (result i32)
+ (local $y i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (local $8 i32)
+ (local $9 i32)
+ (local $10 i32)
+ (local $11 i32)
+ (local $12 i32)
+ (local $13 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -40)
+ )
+ )
+ (local.set $12
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $x
+ (i32.load
+ (local.get $12)
+ )
+ )
+ (local.set $y
+ (i32.load offset=4
+ (local.get $12)
+ )
+ )
+ (local.set $2
+ (i32.load offset=8
+ (local.get $12)
+ )
+ )
+ (local.set $3
+ (i32.load offset=12
+ (local.get $12)
+ )
+ )
+ (local.set $4
+ (i32.load offset=16
+ (local.get $12)
+ )
+ )
+ (local.set $5
+ (i32.load offset=20
+ (local.get $12)
+ )
+ )
+ (local.set $6
+ (i32.load offset=24
+ (local.get $12)
+ )
+ )
+ (local.set $7
+ (i32.load offset=28
+ (local.get $12)
+ )
+ )
+ (local.set $8
+ (i32.load offset=32
+ (local.get $12)
+ )
+ )
+ (local.set $9
+ (i32.load offset=36
+ (local.get $12)
+ )
+ )
+ )
+ )
+ (local.set $10
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $11
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (loop $l
+ (local.set $4
+ (i32.add
+ (local.get $y)
+ (i32.const 1)
+ )
+ )
+ (local.set $y
+ (i32.div_s
+ (local.get $4)
+ (i32.const 3)
+ )
+ )
+ (br_if $l
+ (local.get $y)
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $11)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (return
+ (local.get $y)
+ )
+ )
+ )
+ (unreachable)
+ )
+ (unreachable)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $10)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $13
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $13)
+ (local.get $x)
+ )
+ (i32.store offset=4
+ (local.get $13)
+ (local.get $y)
+ )
+ (i32.store offset=8
+ (local.get $13)
+ (local.get $2)
+ )
+ (i32.store offset=12
+ (local.get $13)
+ (local.get $3)
+ )
+ (i32.store offset=16
+ (local.get $13)
+ (local.get $4)
+ )
+ (i32.store offset=20
+ (local.get $13)
+ (local.get $5)
+ )
+ (i32.store offset=24
+ (local.get $13)
+ (local.get $6)
+ )
+ (i32.store offset=28
+ (local.get $13)
+ (local.get $7)
+ )
+ (i32.store offset=32
+ (local.get $13)
+ (local.get $8)
+ )
+ (i32.store offset=36
+ (local.get $13)
+ (local.get $9)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 40)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-import2-if (; 8 ;) (type $FUNCSIG$vi) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -8)
+ )
+ )
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $x
+ (i32.load
+ (local.get $4)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $4)
+ )
+ )
+ )
+ )
+ (local.set $2
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (local.get $x)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $3)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $2)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $5
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $5)
+ (local.get $x)
+ )
+ (i32.store offset=4
+ (local.get $5)
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ (func $calls-import2-if-else (; 9 ;) (type $FUNCSIG$vi) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -8)
+ )
+ )
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $x
+ (i32.load
+ (local.get $4)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $4)
+ )
+ )
+ )
+ )
+ (local.set $2
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.or
+ (local.get $x)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $3)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import3
+ (i32.const 1)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (i32.eqz
+ (local.get $x)
+ )
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $3)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $import3
+ (i32.const 2)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $2)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $5
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $5)
+ (local.get $x)
+ )
+ (i32.store offset=4
+ (local.get $5)
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ (func $calls-import2-if-else-oneside (; 10 ;) (type $FUNCSIG$ii) (param $x i32) (result i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -16)
+ )
+ )
+ (local.set $6
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $x
+ (i32.load
+ (local.get $6)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $6)
+ )
+ )
+ (local.set $2
+ (i32.load offset=8
+ (local.get $6)
+ )
+ )
+ (local.set $3
+ (i32.load offset=12
+ (local.get $6)
+ )
+ )
+ )
+ )
+ (local.set $4
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $5
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (block
+ (if
+ (i32.or
+ (local.get $x)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (return
+ (i32.const 1)
+ )
+ )
+ )
+ (if
+ (i32.or
+ (i32.eqz
+ (local.get $x)
+ )
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $5)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import3
+ (i32.const 2)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (return
+ (i32.const 3)
+ )
+ )
+ )
+ (unreachable)
+ )
+ (unreachable)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $4)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $7
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $7)
+ (local.get $x)
+ )
+ (i32.store offset=4
+ (local.get $7)
+ (local.get $1)
+ )
+ (i32.store offset=8
+ (local.get $7)
+ (local.get $2)
+ )
+ (i32.store offset=12
+ (local.get $7)
+ (local.get $3)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-import2-if-else-oneside2 (; 11 ;) (type $FUNCSIG$ii) (param $x i32) (result i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -16)
+ )
+ )
+ (local.set $6
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $x
+ (i32.load
+ (local.get $6)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $6)
+ )
+ )
+ (local.set $2
+ (i32.load offset=8
+ (local.get $6)
+ )
+ )
+ (local.set $3
+ (i32.load offset=12
+ (local.get $6)
+ )
+ )
+ )
+ )
+ (local.set $4
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $5
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (block
+ (if
+ (i32.or
+ (local.get $x)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $5)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import3
+ (i32.const 1)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (i32.eqz
+ (local.get $x)
+ )
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (return
+ (i32.const 2)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (return
+ (i32.const 3)
+ )
+ )
+ )
+ (unreachable)
+ )
+ (unreachable)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $4)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $7
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $7)
+ (local.get $x)
+ )
+ (i32.store offset=4
+ (local.get $7)
+ (local.get $1)
+ )
+ (i32.store offset=8
+ (local.get $7)
+ (local.get $2)
+ )
+ (i32.store offset=12
+ (local.get $7)
+ (local.get $3)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-loop (; 12 ;) (type $FUNCSIG$vi) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -16)
+ )
+ )
+ (local.set $6
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $x
+ (i32.load
+ (local.get $6)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $6)
+ )
+ )
+ (local.set $2
+ (i32.load offset=8
+ (local.get $6)
+ )
+ )
+ (local.set $3
+ (i32.load offset=12
+ (local.get $6)
+ )
+ )
+ )
+ )
+ (local.set $4
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $5
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (loop $l
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $5)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import3
+ (i32.const 1)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (block
+ (local.set $x
+ (i32.add
+ (local.get $x)
+ (i32.const 1)
+ )
+ )
+ (br_if $l
+ (local.get $x)
+ )
+ )
+ )
+ (nop)
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $4)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $7
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $7)
+ (local.get $x)
+ )
+ (i32.store offset=4
+ (local.get $7)
+ (local.get $1)
+ )
+ (i32.store offset=8
+ (local.get $7)
+ (local.get $2)
+ )
+ (i32.store offset=12
+ (local.get $7)
+ (local.get $3)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
+ (func $calls-loop2 (; 13 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (local.get $3)
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $2
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (loop $l
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $2)
+ (i32.const 0)
+ )
+ )
+ (block
+ (local.set $0
+ (call $import2)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (br_if $l
+ (local.get $0)
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $4)
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ )
+ (func $calls-mix (; 14 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $boring)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $boring)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $boring (; 15 ;) (type $FUNCSIG$v)
+ (nop)
+ )
+ (func $calls-mix-deep (; 16 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $boring-deep)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import-deep)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $boring)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $boring-deep (; 17 ;) (type $FUNCSIG$v)
+ (call $boring)
+ )
+ (func $import-deep (; 18 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $bysyncify_start_unwind (; 19 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 20 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 2)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_stop_rewind (; 21 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+)
diff --git a/test/passes/bysyncify.wast b/test/passes/bysyncify.wast
new file mode 100644
index 000000000..7c92bd86f
--- /dev/null
+++ b/test/passes/bysyncify.wast
@@ -0,0 +1,146 @@
+;; Pre-existing imports that the pass turns into the implementations.
+(module
+ (memory 1 2)
+ (import "bysyncify" "start_unwind" (func $bysyncify_start_unwind (param i32)))
+ (import "bysyncify" "start_rewind" (func $bysyncify_start_rewind (param i32)))
+ (import "bysyncify" "stop_rewind" (func $bysyncify_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 $bysyncify_start_unwind (i32.const 4))
+ )
+ (block
+ (global.set $sleeping (i32.const 0))
+ (call $bysyncify_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,
+ ;; initiate a rewind, and then do the call to start things back up
+ (func $second_event
+ (call $bysyncify_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 bysyncify themselves.
+(module
+ (memory 1 2)
+ (import "env" "import" (func $import))
+ (import "env" "import2" (func $import2 (result i32)))
+ (import "env" "import3" (func $import3 (param i32)))
+ (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)
+ (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-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)
+ )
+)
+
diff --git a/test/passes/bysyncify_optimize-level=1.txt b/test/passes/bysyncify_optimize-level=1.txt
new file mode 100644
index 000000000..6eb7217e4
--- /dev/null
+++ b/test/passes/bysyncify_optimize-level=1.txt
@@ -0,0 +1,1541 @@
+(module
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$ii (func (param i32) (result i32)))
+ (import "env" "import" (func $import))
+ (import "env" "import2" (func $import2 (result i32)))
+ (import "env" "import3" (func $import3 (param i32)))
+ (memory $0 1 2)
+ (global $__bysyncify_state (mut i32) (i32.const 0))
+ (global $__bysyncify_data (mut i32) (i32.const 0))
+ (export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
+ (export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
+ (func $calls-import (; 3 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (select
+ (i32.eqz
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block (result i32)
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ (local.get $0)
+ )
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import)
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $calls-import2 (; 4 ;) (type $FUNCSIG$i) (result i32)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (select
+ (i32.eqz
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block (result i32)
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ (local.get $1)
+ )
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (local.set $0
+ (call $import2)
+ )
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (return
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-import2-drop (; 5 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (select
+ (i32.eqz
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block (result i32)
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ (local.get $0)
+ )
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (drop
+ (call $import2)
+ )
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $calls-nothing (; 6 ;) (type $FUNCSIG$v)
+ (nop)
+ )
+ (func $many-locals (; 7 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
+ (local $1 i32)
+ (local $2 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -8)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (local.tee $1
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $1)
+ )
+ )
+ )
+ )
+ (local.set $2
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $2
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (loop $l
+ (br_if $l
+ (local.tee $1
+ (i32.div_s
+ (i32.add
+ (local.get $1)
+ (i32.const 1)
+ )
+ (i32.const 3)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (select
+ (i32.eqz
+ (local.get $2)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import)
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (return
+ (local.get $1)
+ )
+ )
+ (unreachable)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $2)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.store
+ (local.tee $2
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.get $0)
+ )
+ (i32.store offset=4
+ (local.get $2)
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 8)
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-import2-if (; 8 ;) (type $FUNCSIG$vi) (param $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (local.get $0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (select
+ (i32.eqz
+ (local.get $1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import)
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $calls-import2-if-else (; 9 ;) (type $FUNCSIG$vi) (param $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (local.get $0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (select
+ (i32.eqz
+ (local.get $1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import3
+ (i32.const 1)
+ )
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (i32.eqz
+ (local.get $0)
+ )
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (select
+ (i32.eq
+ (local.get $1)
+ (i32.const 1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import3
+ (i32.const 2)
+ )
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 1)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $calls-import2-if-else-oneside (; 10 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (local.get $0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (return
+ (i32.const 1)
+ )
+ )
+ )
+ (if
+ (i32.or
+ (i32.eqz
+ (local.get $0)
+ )
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (select
+ (i32.eqz
+ (local.get $1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import3
+ (i32.const 2)
+ )
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (return
+ (i32.const 3)
+ )
+ )
+ (unreachable)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-import2-if-else-oneside2 (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (local.get $0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (select
+ (i32.eqz
+ (local.get $1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import3
+ (i32.const 1)
+ )
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (i32.eqz
+ (local.get $0)
+ )
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (return
+ (i32.const 2)
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (return
+ (i32.const 3)
+ )
+ )
+ (unreachable)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-loop (; 12 ;) (type $FUNCSIG$vi) (param $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (loop $l
+ (if
+ (select
+ (i32.eqz
+ (local.get $1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import3
+ (i32.const 1)
+ )
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (br_if $l
+ (local.tee $0
+ (i32.add
+ (local.get $0)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $calls-loop2 (; 13 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (loop $l
+ (if
+ (select
+ (i32.eqz
+ (local.get $1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (local.set $0
+ (call $import2)
+ )
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (br_if $l
+ (local.get $0)
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $calls-mix (; 14 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (call $boring)
+ )
+ (if
+ (select
+ (i32.eqz
+ (local.get $0)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import)
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (call $boring)
+ )
+ (if
+ (select
+ (i32.eq
+ (local.get $0)
+ (i32.const 1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import)
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 1)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $boring (; 15 ;) (type $FUNCSIG$v)
+ (nop)
+ )
+ (func $calls-mix-deep (; 16 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (call $boring-deep)
+ )
+ (if
+ (select
+ (i32.eqz
+ (local.get $0)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import-deep)
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (global.get $__bysyncify_state)
+ )
+ (call $boring)
+ )
+ (if
+ (select
+ (i32.eq
+ (local.get $0)
+ (i32.const 1)
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import)
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 1)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $boring-deep (; 17 ;) (type $FUNCSIG$v)
+ (call $boring)
+ )
+ (func $import-deep (; 18 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (if
+ (select
+ (i32.eqz
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block (result i32)
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ (local.get $0)
+ )
+ )
+ (i32.const 1)
+ (global.get $__bysyncify_state)
+ )
+ (block
+ (call $import)
+ (drop
+ (br_if $__bysyncify_unwind
+ (i32.const 0)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (func $bysyncify_start_unwind (; 19 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 20 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 2)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_stop_rewind (; 21 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+)
diff --git a/test/passes/bysyncify_optimize-level=1.wast b/test/passes/bysyncify_optimize-level=1.wast
new file mode 100644
index 000000000..a89103e8a
--- /dev/null
+++ b/test/passes/bysyncify_optimize-level=1.wast
@@ -0,0 +1,97 @@
+(module
+ (memory 1 2)
+ (import "env" "import" (func $import))
+ (import "env" "import2" (func $import2 (result i32)))
+ (import "env" "import3" (func $import3 (param i32)))
+ (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)
+ (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-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)
+ )
+)
+
diff --git a/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.txt b/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.txt
new file mode 100644
index 000000000..e850da6cf
--- /dev/null
+++ b/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.txt
@@ -0,0 +1,1998 @@
+(module
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$v (func))
+ (memory $0 1 2)
+ (global $sleeping (mut i32) (i32.const 0))
+ (global $__bysyncify_state (mut i32) (i32.const 0))
+ (global $__bysyncify_data (mut i32) (i32.const 0))
+ (export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
+ (export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
+ (func $do_sleep (; 0 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -8)
+ )
+ )
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (local.get $4)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $4)
+ )
+ )
+ )
+ )
+ (local.set $2
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (block
+ (local.set $0
+ (global.get $sleeping)
+ )
+ (local.set $1
+ (i32.eqz
+ (local.get $0)
+ )
+ )
+ )
+ )
+ (nop)
+ (block
+ (if
+ (i32.or
+ (local.get $1)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (global.set $sleeping
+ (i32.const 1)
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $3)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $bysyncify_start_unwind
+ (i32.const 4)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (i32.eqz
+ (local.get $1)
+ )
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (block
+ (global.set $sleeping
+ (i32.const 0)
+ )
+ (call $bysyncify_stop_rewind)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $2)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $5
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $5)
+ (local.get $0)
+ )
+ (i32.store offset=4
+ (local.get $5)
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ (func $work (; 1 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $stuff)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $do_sleep)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $stuff)
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $stuff (; 2 ;) (type $FUNCSIG$v)
+ (nop)
+ )
+ (func $first_event (; 3 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $work)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $second_event (; 4 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $bysyncify_start_rewind
+ (i32.const 4)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $work)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $never_sleep (; 5 ;) (type $FUNCSIG$v)
+ (call $stuff)
+ (call $stuff)
+ (call $stuff)
+ )
+ (func $bysyncify_start_unwind (; 6 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 7 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 2)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_stop_rewind (; 8 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+)
+(module
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$ii (func (param i32) (result i32)))
+ (import "env" "import" (func $import))
+ (import "env" "import2" (func $import2 (result i32)))
+ (import "env" "import3" (func $import3 (param i32)))
+ (memory $0 1 2)
+ (global $__bysyncify_state (mut i32) (i32.const 0))
+ (global $__bysyncify_data (mut i32) (i32.const 0))
+ (export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
+ (export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
+ (func $calls-import (; 3 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $calls-import2 (; 4 ;) (type $FUNCSIG$i) (result i32)
+ (local $temp i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (local $8 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -20)
+ )
+ )
+ (local.set $7
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $temp
+ (i32.load
+ (local.get $7)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $7)
+ )
+ )
+ (local.set $2
+ (i32.load offset=8
+ (local.get $7)
+ )
+ )
+ (local.set $3
+ (i32.load offset=12
+ (local.get $7)
+ )
+ )
+ (local.set $4
+ (i32.load offset=16
+ (local.get $7)
+ )
+ )
+ )
+ )
+ (local.set $5
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $6
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $6)
+ (i32.const 0)
+ )
+ )
+ (block
+ (local.set $2
+ (call $import2)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (return
+ (local.get $2)
+ )
+ )
+ )
+ (unreachable)
+ )
+ (unreachable)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $5)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $8
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $8)
+ (local.get $temp)
+ )
+ (i32.store offset=4
+ (local.get $8)
+ (local.get $1)
+ )
+ (i32.store offset=8
+ (local.get $8)
+ (local.get $2)
+ )
+ (i32.store offset=12
+ (local.get $8)
+ (local.get $3)
+ )
+ (i32.store offset=16
+ (local.get $8)
+ (local.get $4)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 20)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-import2-drop (; 5 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (local.get $3)
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $2
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $2)
+ (i32.const 0)
+ )
+ )
+ (block
+ (local.set $0
+ (call $import2)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $4)
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ )
+ (func $calls-nothing (; 6 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local.set $0
+ (i32.eqz
+ (i32.const 17)
+ )
+ )
+ )
+ (func $many-locals (; 7 ;) (type $FUNCSIG$ii) (param $x i32) (result i32)
+ (local $y i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (local $6 i32)
+ (local $7 i32)
+ (local $8 i32)
+ (local $9 i32)
+ (local $10 i32)
+ (local $11 i32)
+ (local $12 i32)
+ (local $13 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -40)
+ )
+ )
+ (local.set $12
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $x
+ (i32.load
+ (local.get $12)
+ )
+ )
+ (local.set $y
+ (i32.load offset=4
+ (local.get $12)
+ )
+ )
+ (local.set $2
+ (i32.load offset=8
+ (local.get $12)
+ )
+ )
+ (local.set $3
+ (i32.load offset=12
+ (local.get $12)
+ )
+ )
+ (local.set $4
+ (i32.load offset=16
+ (local.get $12)
+ )
+ )
+ (local.set $5
+ (i32.load offset=20
+ (local.get $12)
+ )
+ )
+ (local.set $6
+ (i32.load offset=24
+ (local.get $12)
+ )
+ )
+ (local.set $7
+ (i32.load offset=28
+ (local.get $12)
+ )
+ )
+ (local.set $8
+ (i32.load offset=32
+ (local.get $12)
+ )
+ )
+ (local.set $9
+ (i32.load offset=36
+ (local.get $12)
+ )
+ )
+ )
+ )
+ (local.set $10
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $11
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (loop $l
+ (local.set $4
+ (i32.add
+ (local.get $y)
+ (i32.const 1)
+ )
+ )
+ (local.set $y
+ (i32.div_s
+ (local.get $4)
+ (i32.const 3)
+ )
+ )
+ (br_if $l
+ (local.get $y)
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $11)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (return
+ (local.get $y)
+ )
+ )
+ )
+ (unreachable)
+ )
+ (unreachable)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $10)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $13
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $13)
+ (local.get $x)
+ )
+ (i32.store offset=4
+ (local.get $13)
+ (local.get $y)
+ )
+ (i32.store offset=8
+ (local.get $13)
+ (local.get $2)
+ )
+ (i32.store offset=12
+ (local.get $13)
+ (local.get $3)
+ )
+ (i32.store offset=16
+ (local.get $13)
+ (local.get $4)
+ )
+ (i32.store offset=20
+ (local.get $13)
+ (local.get $5)
+ )
+ (i32.store offset=24
+ (local.get $13)
+ (local.get $6)
+ )
+ (i32.store offset=28
+ (local.get $13)
+ (local.get $7)
+ )
+ (i32.store offset=32
+ (local.get $13)
+ (local.get $8)
+ )
+ (i32.store offset=36
+ (local.get $13)
+ (local.get $9)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 40)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $calls-import2-if (; 8 ;) (type $FUNCSIG$vi) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (local $5 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -8)
+ )
+ )
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $x
+ (i32.load
+ (local.get $4)
+ )
+ )
+ (local.set $1
+ (i32.load offset=4
+ (local.get $4)
+ )
+ )
+ )
+ )
+ (local.set $2
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (i32.or
+ (local.get $x)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $3)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $2)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $5
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $5)
+ (local.get $x)
+ )
+ (i32.store offset=4
+ (local.get $5)
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ (func $calls-import2-if-else (; 9 ;) (type $FUNCSIG$vi) (param $x i32)
+ (local $1 i32)
+ (if
+ (local.get $x)
+ (call $import3
+ (i32.const 1)
+ )
+ (call $import3
+ (i32.const 2)
+ )
+ )
+ )
+ (func $calls-import2-if-else-oneside (; 10 ;) (type $FUNCSIG$ii) (param $x i32) (result i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (if
+ (local.get $x)
+ (return
+ (i32.const 1)
+ )
+ (call $import3
+ (i32.const 2)
+ )
+ )
+ (return
+ (i32.const 3)
+ )
+ )
+ (func $calls-import2-if-else-oneside2 (; 11 ;) (type $FUNCSIG$ii) (param $x i32) (result i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (if
+ (local.get $x)
+ (call $import3
+ (i32.const 1)
+ )
+ (return
+ (i32.const 2)
+ )
+ )
+ (return
+ (i32.const 3)
+ )
+ )
+ (func $calls-loop (; 12 ;) (type $FUNCSIG$vi) (param $x i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 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 (; 13 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (local $4 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $3
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (local.set $0
+ (i32.load
+ (local.get $3)
+ )
+ )
+ )
+ )
+ (local.set $1
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $2
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (loop $l
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $2)
+ (i32.const 0)
+ )
+ )
+ (block
+ (local.set $0
+ (call $import2)
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (br_if $l
+ (local.get $0)
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $1)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (block
+ (local.set $4
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ (i32.store
+ (local.get $4)
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ )
+ (func $calls-mix (; 14 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $boring)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $boring)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $boring (; 15 ;) (type $FUNCSIG$v)
+ (nop)
+ )
+ (func $calls-mix-deep (; 16 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $boring-deep)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import-deep)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (call $boring)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $boring-deep (; 17 ;) (type $FUNCSIG$v)
+ (call $boring)
+ )
+ (func $import-deep (; 18 ;) (type $FUNCSIG$v)
+ (local $0 i32)
+ (local $1 i32)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (nop)
+ )
+ (local.set $0
+ (block $__bysyncify_unwind (result i32)
+ (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 2)
+ )
+ (block
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const -4)
+ )
+ )
+ (local.set $1
+ (i32.load
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 0)
+ )
+ )
+ (block
+ (call $import)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ )
+ (return)
+ )
+ )
+ )
+ (block
+ (i32.store
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (local.get $0)
+ )
+ (i32.store
+ (global.get $__bysyncify_data)
+ (i32.add
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.const 4)
+ )
+ )
+ )
+ (nop)
+ )
+ (func $bysyncify_start_unwind (; 19 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 20 ;) (param $0 i32)
+ (if
+ (i32.gt_u
+ (i32.load
+ (local.get $0)
+ )
+ (i32.load offset=4
+ (local.get $0)
+ )
+ )
+ (unreachable)
+ )
+ (global.set $__bysyncify_state
+ (i32.const 2)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
+ )
+ (func $bysyncify_stop_rewind (; 21 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+)
diff --git a/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.wast b/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.wast
new file mode 100644
index 000000000..7c92bd86f
--- /dev/null
+++ b/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.wast
@@ -0,0 +1,146 @@
+;; Pre-existing imports that the pass turns into the implementations.
+(module
+ (memory 1 2)
+ (import "bysyncify" "start_unwind" (func $bysyncify_start_unwind (param i32)))
+ (import "bysyncify" "start_rewind" (func $bysyncify_start_rewind (param i32)))
+ (import "bysyncify" "stop_rewind" (func $bysyncify_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 $bysyncify_start_unwind (i32.const 4))
+ )
+ (block
+ (global.set $sleeping (i32.const 0))
+ (call $bysyncify_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,
+ ;; initiate a rewind, and then do the call to start things back up
+ (func $second_event
+ (call $bysyncify_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 bysyncify themselves.
+(module
+ (memory 1 2)
+ (import "env" "import" (func $import))
+ (import "env" "import2" (func $import2 (result i32)))
+ (import "env" "import3" (func $import3 (param i32)))
+ (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)
+ (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-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)
+ )
+)
+
diff --git a/test/unit/input/bysyncify.js b/test/unit/input/bysyncify.js
new file mode 100644
index 000000000..97d7a0da5
--- /dev/null
+++ b/test/unit/input/bysyncify.js
@@ -0,0 +1,155 @@
+
+function assert(x, y) {
+ if (!x) throw (y || 'assertion failed') + '\n' + new Error().stack;
+}
+
+var fs = require('fs');
+
+// Get and compile the wasm.
+
+var binary = fs.readFileSync('a.wasm');
+
+var module = new WebAssembly.Module(binary);
+
+var DATA_ADDR = 4;
+
+var sleeps = 0;
+
+var sleeping = false;
+
+var instance = new WebAssembly.Instance(module, {
+ env: {
+ sleep: function() {
+ logMemory();
+assert(view[0] == 0);
+ if (!sleeping) {
+ // We are called in order to start a sleep/unwind.
+ console.log('sleep...');
+ sleeps++;
+ // Unwinding.
+ exports.bysyncify_start_unwind(DATA_ADDR);
+ // Fill in the data structure. The first value has the stack location,
+ // which for simplicity we can start right after the data structure itself.
+ view[DATA_ADDR >> 2] = DATA_ADDR + 8;
+ // The end of the stack will not be reached here anyhow.
+ view[DATA_ADDR + 4 >> 2] = 1024;
+ sleeping = true;
+ } else {
+ // We are called as part of a resume/rewind. Stop sleeping.
+ console.log('resume...');
+ exports.bysyncify_stop_rewind();
+ // The stack should have been all used up, and so returned to the original state.
+ assert(view[DATA_ADDR >> 2] == DATA_ADDR + 8);
+ assert(view[DATA_ADDR + 4 >> 2] == 1024);
+ sleeping = false;
+ }
+ logMemory();
+ },
+ tunnel: function(x) {
+ console.log('tunneling, sleep == ' + sleeping);
+ return exports.end_tunnel(x);
+ }
+ }
+});
+
+var exports = instance.exports;
+var view = new Int32Array(exports.memory.buffer);
+
+function logMemory() {
+ // Log the relevant memory locations for debugging purposes.
+ console.log('memory: ', view[0 >> 2], view[4 >> 2], view[8 >> 2], view[12 >> 2], view[16 >> 2], view[20 >> 2], view[24 >> 2]);
+}
+
+function runTest(name, expectedSleeps, expectedResult, params) {
+ params = params || [];
+
+ console.log('\n==== testing ' + name + ' ====');
+
+ sleeps = 0;
+
+ logMemory();
+
+ // Run until the sleep.
+ var result = exports[name].apply(null, params);
+ logMemory();
+
+ if (expectedSleeps > 0) {
+ assert(!result, 'results during sleep are meaningless, just 0');
+
+ for (var i = 0; i < expectedSleeps - 1; i++) {
+ console.log('rewind, run until the next sleep');
+ exports.bysyncify_start_rewind(DATA_ADDR);
+ result = exports[name](); // no need for params on later times
+ assert(!result, 'results during sleep are meaningless, just 0');
+ assert(!result, 'bad first sleep result');
+ logMemory();
+ }
+
+ console.log('rewind and run til the end.');
+ exports.bysyncify_start_rewind(DATA_ADDR);
+ result = exports[name]();
+ }
+
+ console.log('final result: ' + result);
+ assert(result == expectedResult, 'bad final result');
+ logMemory();
+
+ assert(sleeps == expectedSleeps, 'expectedSleeps');
+}
+
+//================
+// Tests
+//================
+
+// A minimal single sleep.
+runTest('minimal', 1, 21);
+
+// Two sleeps.
+runTest('repeat', 2, 42);
+
+// A value in a local is preserved across a sleep.
+runTest('local', 1, 10);
+
+// A local with more operations done on it.
+runTest('local2', 1, 22);
+
+// A local with more operations done on it.
+runTest('params', 1, 18);
+runTest('params', 1, 21, [1, 2]);
+
+// Calls to multiple other functions, only one of whom
+// sleeps, and keep locals and globals valid throughout.
+runTest('deeper', 0, 27, [0]);
+runTest('deeper', 1, 3, [1]);
+
+// A recursive factorial, that sleeps on each iteration
+// above 1.
+runTest('factorial-recursive', 0, 1, [1]);
+runTest('factorial-recursive', 1, 2, [2]);
+runTest('factorial-recursive', 2, 6, [3]);
+runTest('factorial-recursive', 3, 24, [4]);
+runTest('factorial-recursive', 4, 120, [5]);
+
+// A looping factorial, that sleeps on each iteration
+// above 1.
+runTest('factorial-loop', 0, 1, [1]);
+runTest('factorial-loop', 1, 2, [2]);
+runTest('factorial-loop', 2, 6, [3]);
+runTest('factorial-loop', 3, 24, [4]);
+runTest('factorial-loop', 4, 120, [5]);
+
+// Test calling into JS in the middle (which can work if
+// the JS just forwards the call and has no side effects or
+// state of its own that needs to be saved).
+runTest('do_tunnel', 2, 72, [1]);
+
+// Test indirect function calls.
+runTest('call_indirect', 3, 432, [1, 2]);
+
+// Test indirect function calls.
+runTest('if_else', 3, 1460, [1, 1000]);
+runTest('if_else', 3, 2520, [2, 2000]);
+
+// All done.
+console.log('\ntests completed successfully');
+
diff --git a/test/unit/input/bysyncify.wast b/test/unit/input/bysyncify.wast
new file mode 100644
index 000000000..91fb5a327
--- /dev/null
+++ b/test/unit/input/bysyncify.wast
@@ -0,0 +1,200 @@
+(module
+ (memory 1 2)
+ (type $ii (func (param i32) (result i32)))
+ (import "env" "sleep" (func $sleep))
+ (import "env" "tunnel" (func $tunnel (param $x i32) (result i32)))
+ (export "memory" (memory 0))
+ (export "factorial-recursive" (func $factorial-recursive))
+ (global $temp (mut i32) (i32.const 0))
+ (table 10 funcref)
+ (elem (i32.const 5) $tablefunc)
+ (func "minimal" (result i32)
+ (call $sleep)
+ (i32.const 21)
+ )
+ (func "repeat" (result i32)
+ ;; sleep twice, then return 42
+ (call $sleep)
+ (call $sleep)
+ (i32.const 42)
+ )
+ (func "local" (result i32)
+ (local $x i32)
+ (local.set $x (i32.load (i32.const 0))) ;; a zero that the optimizer won't see
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 10)) ;; add 10
+ )
+ (call $sleep)
+ (local.get $x)
+ )
+ (func "local2" (result i32)
+ (local $x i32)
+ (local.set $x (i32.load (i32.const 0))) ;; a zero that the optimizer won't see
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 10)) ;; add 10
+ )
+ (call $sleep)
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 12)) ;; add 12 more
+ )
+ (local.get $x)
+ )
+ (func "params" (param $x i32) (param $y i32) (result i32)
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 17)) ;; add 10
+ )
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 1)) ;; add 12 more
+ )
+ (call $sleep)
+ (i32.add (local.get $x) (local.get $y))
+ )
+ (func $pre
+ (global.set $temp (i32.const 1))
+ )
+ (func $inner (param $x i32)
+ (if (i32.eqz (local.get $x)) (call $post))
+ (if (local.get $x) (call $sleep))
+ (if (i32.eqz (local.get $x)) (call $post))
+ )
+ (func $post
+ (global.set $temp
+ (i32.mul
+ (global.get $temp)
+ (i32.const 3)
+ )
+ )
+ )
+ (func "deeper" (param $x i32) (result i32)
+ (call $pre)
+ (call $inner (local.get $x))
+ (call $post)
+ (global.get $temp)
+ )
+ (func $factorial-recursive (param $x i32) (result i32)
+ (if
+ (i32.eq
+ (local.get $x)
+ (i32.const 1)
+ )
+ (return (i32.const 1))
+ )
+ (call $sleep)
+ (return
+ (i32.mul
+ (local.get $x)
+ (call $factorial-recursive
+ (i32.sub
+ (local.get $x)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (func "factorial-loop" (param $x i32) (result i32)
+ (local $i i32)
+ (local $ret i32)
+ (local.set $ret (i32.const 1))
+ (local.set $i (i32.const 2))
+ (loop $l
+ (if
+ (i32.gt_u
+ (local.get $i)
+ (local.get $x)
+ )
+ (return (local.get $ret))
+ )
+ (local.set $ret
+ (i32.mul
+ (local.get $ret)
+ (local.get $i)
+ )
+ )
+ (call $sleep)
+ (local.set $i
+ (i32.add
+ (local.get $i)
+ (i32.const 1)
+ )
+ )
+ (br $l)
+ )
+ )
+ (func "end_tunnel" (param $x i32) (result i32)
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 22))
+ )
+ (call $sleep)
+ (i32.add (local.get $x) (i32.const 5))
+ )
+ (func "do_tunnel" (param $x i32) (result i32)
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 11))
+ )
+ (local.set $x
+ (call $tunnel (local.get $x)) ;; calls js which calls back into wasm for end_tunnel
+ )
+ (call $sleep)
+ (i32.add (local.get $x) (i32.const 33))
+ )
+ (func $tablefunc (param $y i32) (result i32)
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 10))
+ )
+ (call $sleep)
+ (i32.add (local.get $y) (i32.const 30))
+ )
+ (func "call_indirect" (param $x i32) (param $y i32) (result i32)
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 1))
+ )
+ (call $sleep)
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 3))
+ )
+ (local.set $y
+ (call_indirect (type $ii) (local.get $y) (local.get $x)) ;; call function pointer x + 4, which will be 5
+ )
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 90))
+ )
+ (call $sleep)
+ (i32.add (local.get $y) (i32.const 300)) ;; total is 10+30+90+300=430 + y's original value
+ )
+ (func "if_else" (param $x i32) (param $y i32) (result i32)
+ (if (i32.eq (local.get $x) (i32.const 1))
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 10))
+ )
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 20))
+ )
+ )
+ (if (i32.eq (local.get $x) (i32.const 1))
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 40))
+ )
+ (call $sleep)
+ )
+ (if (i32.eq (local.get $x) (i32.const 1))
+ (call $sleep)
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 90))
+ )
+ )
+ (if (i32.eq (local.get $x) (i32.const 1))
+ (call $sleep)
+ (call $sleep)
+ )
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 160))
+ )
+ (call $sleep)
+ (local.set $y
+ (i32.add (local.get $y) (i32.const 250))
+ )
+ (local.get $y)
+ )
+)
+
diff --git a/test/unit/test_bysyncify.py b/test/unit/test_bysyncify.py
new file mode 100644
index 000000000..5373a4def
--- /dev/null
+++ b/test/unit/test_bysyncify.py
@@ -0,0 +1,20 @@
+import os
+
+from scripts.test.shared import WASM_OPT, NODEJS, run_process
+from utils import BinaryenTestCase
+
+
+class BysyncifyTest(BinaryenTestCase):
+ def test_bysyncify(self):
+ def test(args):
+ print(args)
+ run_process(WASM_OPT + args + [self.input_path('bysyncify.wast'), '--bysyncify', '-o', 'a.wasm'])
+ print(' file size: %d' % os.path.getsize('a.wasm'))
+ run_process([NODEJS, self.input_path('bysyncify.js')])
+
+ test(['-g'])
+ test([])
+ test(['-O1'])
+ test(['--optimize-level=1'])
+ test(['-O3'])
+ test(['-Os', '-g'])