summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2022-10-04 19:09:13 -0700
committerGitHub <noreply@github.com>2022-10-04 19:09:13 -0700
commit9868e17f729983722ca0f8f5a4c91f63db52a703 (patch)
treea4160f2561d8ebd7b3ad286f1fe94893ff30c856
parent2e848a0090b4c74df259b7063140200b06129ee9 (diff)
downloadbinaryen-9868e17f729983722ca0f8f5a4c91f63db52a703.tar.gz
binaryen-9868e17f729983722ca0f8f5a4c91f63db52a703.tar.bz2
binaryen-9868e17f729983722ca0f8f5a4c91f63db52a703.zip
Make Asyncify work with wasm64 (#5105)
The emscripten side is a little tricky but I've got some tests passing. Currently blocked on: https://github.com/emscripten-core/emscripten/issues/17969
-rw-r--r--src/passes/Asyncify.cpp132
-rw-r--r--test/lit/passes/asyncify-wasm64.wast1335
2 files changed, 1410 insertions, 57 deletions
diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp
index 89e9a3ad5..e5886a348 100644
--- a/src/passes/Asyncify.cpp
+++ b/src/passes/Asyncify.cpp
@@ -107,11 +107,18 @@
// contains a pointer to a data structure with the info needed to rewind
// and unwind:
//
-// { // offsets
+// { // offsets
// i32 - current asyncify stack location // 0
// i32 - asyncify stack end // 4
// }
//
+// Or for wasm64:
+//
+// { // offsets
+// i64 - current asyncify stack location // 0
+// i64 - asyncify stack end // 8
+// }
+//
// The asyncify stack is a representation of the call frame, as a list of
// indexes of calls. In the example above, we saw index "0" for calling "bar"
// from "foo". When unwinding, the indexes are added to the stack; when
@@ -130,7 +137,7 @@
// The pass will also create five functions that let you control unwinding
// and rewinding:
//
-// * asyncify_start_unwind(data : i32): call this to start unwinding the
+// * asyncify_start_unwind(data : iPTR): call this to start unwinding the
// stack from the current location. "data" must point to a data
// structure as described above (with fields containing valid data).
//
@@ -142,7 +149,7 @@
// the code will think it is still unwinding when it should not be,
// which means it will keep unwinding in a meaningless way.
//
-// * asyncify_start_rewind(data : i32): call this to start rewinding the
+// * asyncify_start_rewind(data : iPTR): call this to start rewinding the
// stack vack up to the location stored in the provided data. This prepares
// for the rewind; to start it, you must call the first function in the
// call stack to be unwound.
@@ -335,7 +342,7 @@ static const Name ASYNCIFY_CHECK_CALL_INDEX = "__asyncify_check_call_index";
// size, but make debugging harder
enum class State { Normal = 0, Unwinding = 1, Rewinding = 2 };
-enum class DataOffset { BStackPos = 0, BStackEnd = 4 };
+enum class DataOffset { BStackPos = 0, BStackEnd = 4, BStackEnd64 = 8 };
const auto STACK_ALIGN = 4;
@@ -795,16 +802,18 @@ static bool doesCall(Expression* curr) {
class AsyncifyBuilder : public Builder {
public:
Module& wasm;
+ Type pointerType;
- AsyncifyBuilder(Module& wasm) : Builder(wasm), wasm(wasm) {}
+ AsyncifyBuilder(Module& wasm)
+ : Builder(wasm), wasm(wasm), pointerType(wasm.memories[0]->indexType) {}
Expression* makeGetStackPos() {
- return makeLoad(4,
+ return makeLoad(pointerType.getByteSize(),
false,
- int32_t(DataOffset::BStackPos),
- 4,
- makeGlobalGet(ASYNCIFY_DATA, Type::i32),
- Type::i32,
+ int(DataOffset::BStackPos),
+ pointerType.getByteSize(),
+ makeGlobalGet(ASYNCIFY_DATA, pointerType),
+ pointerType,
wasm.memories[0]->name);
}
@@ -812,14 +821,16 @@ public:
if (by == 0) {
return makeNop();
}
- return makeStore(
- 4,
- int32_t(DataOffset::BStackPos),
- 4,
- makeGlobalGet(ASYNCIFY_DATA, Type::i32),
- makeBinary(AddInt32, makeGetStackPos(), makeConst(Literal(by))),
- Type::i32,
- wasm.memories[0]->name);
+ auto literal = Literal::makeFromInt64(by, pointerType);
+ return makeStore(pointerType.getByteSize(),
+ int(DataOffset::BStackPos),
+ pointerType.getByteSize(),
+ makeGlobalGet(ASYNCIFY_DATA, pointerType),
+ makeBinary(Abstract::getBinary(pointerType, Abstract::Add),
+ makeGetStackPos(),
+ makeConst(literal)),
+ pointerType,
+ wasm.memories[0]->name);
}
Expression* makeStateCheck(State value) {
@@ -829,7 +840,8 @@ public:
}
Expression* makeNegatedStateCheck(State value) {
- return makeUnary(EqZInt32, makeStateCheck(value));
+ return makeUnary(Abstract::getUnary(pointerType, Abstract::EqZ),
+ makeStateCheck(value));
}
};
@@ -1384,7 +1396,7 @@ private:
}
auto* block = builder->makeBlock();
block->list.push_back(builder->makeIncStackPos(-total));
- auto tempIndex = builder->addVar(func, Type::i32);
+ auto tempIndex = builder->addVar(func, builder->pointerType);
block->list.push_back(
builder->makeLocalSet(tempIndex, builder->makeGetStackPos()));
Index offset = 0;
@@ -1398,14 +1410,14 @@ private:
auto size = getByteSize(type);
assert(size % STACK_ALIGN == 0);
// TODO: higher alignment?
- loads.push_back(
- builder->makeLoad(size,
- true,
- offset,
- STACK_ALIGN,
- builder->makeLocalGet(tempIndex, Type::i32),
- type,
- getModule()->memories[0]->name));
+ loads.push_back(builder->makeLoad(
+ size,
+ true,
+ offset,
+ STACK_ALIGN,
+ builder->makeLocalGet(tempIndex, builder->pointerType),
+ type,
+ getModule()->memories[0]->name));
offset += size;
}
Expression* load;
@@ -1429,7 +1441,7 @@ private:
auto* func = getFunction();
auto numLocals = func->getNumLocals();
auto* block = builder->makeBlock();
- auto tempIndex = builder->addVar(func, Type::i32);
+ auto tempIndex = builder->addVar(func, builder->pointerType);
block->list.push_back(
builder->makeLocalSet(tempIndex, builder->makeGetStackPos()));
Index offset = 0;
@@ -1447,14 +1459,14 @@ private:
}
assert(size % STACK_ALIGN == 0);
// TODO: higher alignment?
- block->list.push_back(
- builder->makeStore(size,
- offset,
- STACK_ALIGN,
- builder->makeLocalGet(tempIndex, Type::i32),
- localGet,
- type,
- getModule()->memories[0]->name));
+ block->list.push_back(builder->makeStore(
+ size,
+ offset,
+ STACK_ALIGN,
+ builder->makeLocalGet(tempIndex, builder->pointerType),
+ localGet,
+ type,
+ getModule()->memories[0]->name));
offset += size;
++j;
}
@@ -1497,6 +1509,8 @@ struct Asyncify : public Pass {
void run(Module* module) override {
auto& options = getPassOptions();
bool optimize = options.optimizeLevel > 0;
+ is64 = module->memories.size() && module->memories[0]->is64();
+ pointerType = is64 ? Type::i64 : Type::i32;
// Ensure there is a memory, as we need it.
MemoryUtils::ensureExists(module);
@@ -1640,8 +1654,8 @@ private:
module->addGlobal(std::move(asyncifyState));
auto asyncifyData = builder.makeGlobal(ASYNCIFY_DATA,
- Type::i32,
- builder.makeConst(int32_t(0)),
+ pointerType,
+ builder.makeConst(pointerType),
Builder::Mutable);
if (imported) {
asyncifyData->module = ENV;
@@ -1655,35 +1669,36 @@ private:
auto makeFunction = [&](Name name, bool setData, State state) {
std::vector<Type> params;
if (setData) {
- params.push_back(Type::i32);
+ params.push_back(pointerType);
}
auto* body = builder.makeBlock();
body->list.push_back(builder.makeGlobalSet(
ASYNCIFY_STATE, builder.makeConst(int32_t(state))));
if (setData) {
body->list.push_back(builder.makeGlobalSet(
- ASYNCIFY_DATA, builder.makeLocalGet(0, Type::i32)));
+ ASYNCIFY_DATA, builder.makeLocalGet(0, pointerType)));
}
// Verify the data is valid.
auto* stackPos =
- builder.makeLoad(4,
- false,
- int32_t(DataOffset::BStackPos),
- 4,
- builder.makeGlobalGet(ASYNCIFY_DATA, Type::i32),
- Type::i32,
- module->memories[0]->name);
- auto* stackEnd =
- builder.makeLoad(4,
+ builder.makeLoad(pointerType.getByteSize(),
false,
- int32_t(DataOffset::BStackEnd),
- 4,
- builder.makeGlobalGet(ASYNCIFY_DATA, Type::i32),
- Type::i32,
+ int(DataOffset::BStackPos),
+ pointerType.getByteSize(),
+ builder.makeGlobalGet(ASYNCIFY_DATA, pointerType),
+ pointerType,
module->memories[0]->name);
- body->list.push_back(
- builder.makeIf(builder.makeBinary(GtUInt32, stackPos, stackEnd),
- builder.makeUnreachable()));
+ auto* stackEnd = builder.makeLoad(
+ pointerType.getByteSize(),
+ false,
+ int(is64 ? DataOffset::BStackEnd64 : DataOffset::BStackEnd),
+ pointerType.getByteSize(),
+ builder.makeGlobalGet(ASYNCIFY_DATA, pointerType),
+ pointerType,
+ module->memories[0]->name);
+ body->list.push_back(builder.makeIf(
+ builder.makeBinary(
+ Abstract::getBinary(pointerType, Abstract::GtU), stackPos, stackEnd),
+ builder.makeUnreachable()));
body->finalize();
auto func = builder.makeFunction(
name, Signature(Type(params), Type::none), {}, body);
@@ -1704,6 +1719,9 @@ private:
module->addExport(builder.makeExport(
ASYNCIFY_GET_STATE, ASYNCIFY_GET_STATE, ExternalKind::Function));
}
+
+ bool is64;
+ Type pointerType;
};
Pass* createAsyncifyPass() { return new Asyncify(); }
diff --git a/test/lit/passes/asyncify-wasm64.wast b/test/lit/passes/asyncify-wasm64.wast
new file mode 100644
index 000000000..7d6c216e5
--- /dev/null
+++ b/test/lit/passes/asyncify-wasm64.wast
@@ -0,0 +1,1335 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
+
+;; RUN: wasm-opt --enable-memory64 --asyncify %s -S -o - | filecheck %s
+
+(module
+ ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32)))
+
+ ;; CHECK: (type $f (func (param i32)))
+ (type $f (func (param i32)))
+ (memory i64 1 2)
+ ;; CHECK: (type $none_=>_none (func))
+
+ ;; CHECK: (type $i64_=>_none (func (param i64)))
+
+ ;; CHECK: (type $none_=>_i32 (func (result i32)))
+
+ ;; CHECK: (import "env" "import" (func $import))
+ (import "env" "import" (func $import))
+ ;; CHECK: (import "env" "import2" (func $import2 (param i32)))
+ (import "env" "import2" (func $import2 (param i32)))
+ (table funcref (elem $liveness2 $liveness2))
+ ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0))
+
+ ;; CHECK: (global $__asyncify_data (mut i64) (i64.const 0))
+
+ ;; CHECK: (memory $0 i64 1 2)
+
+ ;; CHECK: (table $0 2 2 funcref)
+
+ ;; CHECK: (elem (i32.const 0) $liveness2 $liveness2)
+
+ ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind))
+
+ ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind))
+
+ ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind))
+
+ ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind))
+
+ ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state))
+
+ ;; CHECK: (func $liveness1 (param $live0 i32) (param $dead0 i32)
+ ;; CHECK-NEXT: (local $live1 i32)
+ ;; CHECK-NEXT: (local $dead1 i32)
+ ;; CHECK-NEXT: (local $4 i32)
+ ;; CHECK-NEXT: (local $5 i32)
+ ;; CHECK-NEXT: (local $6 i32)
+ ;; CHECK-NEXT: (local $7 i32)
+ ;; CHECK-NEXT: (local $8 i32)
+ ;; CHECK-NEXT: (local $9 i32)
+ ;; CHECK-NEXT: (local $10 i64)
+ ;; CHECK-NEXT: (local $11 i64)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $10
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $live0
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (local.get $10)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $live1
+ ;; CHECK-NEXT: (i32.load offset=4
+ ;; CHECK-NEXT: (local.get $10)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $8
+ ;; CHECK-NEXT: (block $__asyncify_unwind (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $9
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (local.get $dead0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (local.get $dead1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $5)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (local.get $9)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $import)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__asyncify_unwind
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $6
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $7
+ ;; CHECK-NEXT: (local.get $live1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $7)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $11
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (local.get $11)
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store offset=4
+ ;; CHECK-NEXT: (local.get $11)
+ ;; CHECK-NEXT: (local.get $live1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $liveness1 (param $live0 i32) (param $dead0 i32)
+ (local $live1 i32)
+ (local $dead1 i32)
+ (drop (local.get $dead0))
+ (drop (local.get $dead1))
+ (call $import)
+ (drop (local.get $live0))
+ (drop (local.get $live1))
+ )
+ ;; CHECK: (func $liveness2 (param $live0 i32) (param $dead0 i32)
+ ;; CHECK-NEXT: (local $live1 i32)
+ ;; CHECK-NEXT: (local $dead1 i32)
+ ;; CHECK-NEXT: (local $4 i32)
+ ;; CHECK-NEXT: (local $5 i32)
+ ;; CHECK-NEXT: (local $6 i32)
+ ;; CHECK-NEXT: (local $7 i32)
+ ;; CHECK-NEXT: (local $8 i32)
+ ;; CHECK-NEXT: (local $9 i32)
+ ;; CHECK-NEXT: (local $10 i64)
+ ;; CHECK-NEXT: (local $11 i64)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $10
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $live0
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (local.get $10)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $live1
+ ;; CHECK-NEXT: (i32.load offset=4
+ ;; CHECK-NEXT: (local.get $10)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $8
+ ;; CHECK-NEXT: (block $__asyncify_unwind (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $9
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (local.get $dead0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (local.get $dead1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $5)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (local.get $9)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $import)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__asyncify_unwind
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $6
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $7
+ ;; CHECK-NEXT: (local.get $live1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $7)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $11
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (local.get $11)
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store offset=4
+ ;; CHECK-NEXT: (local.get $11)
+ ;; CHECK-NEXT: (local.get $live1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $liveness2 (param $live0 i32) (param $dead0 i32)
+ (local $live1 i32)
+ (local $dead1 i32)
+ (drop (local.get $dead0))
+ (drop (local.get $dead1))
+ (call $import)
+ (drop (local.get $live0))
+ (drop (local.get $live1))
+ )
+ ;; CHECK: (func $liveness3 (param $live0 i32) (param $dead0 i32)
+ ;; CHECK-NEXT: (local $live1 i32)
+ ;; CHECK-NEXT: (local $dead1 i32)
+ ;; CHECK-NEXT: (local $4 i32)
+ ;; CHECK-NEXT: (local $5 i32)
+ ;; CHECK-NEXT: (local $6 i32)
+ ;; CHECK-NEXT: (local $7 i32)
+ ;; CHECK-NEXT: (local $8 i64)
+ ;; CHECK-NEXT: (local $9 i64)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $8
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $live0
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (local.get $8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $live1
+ ;; CHECK-NEXT: (i32.load offset=4
+ ;; CHECK-NEXT: (local.get $8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $6
+ ;; CHECK-NEXT: (block $__asyncify_unwind (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $7
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (local.get $7)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $import)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__asyncify_unwind
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (local.get $7)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $import)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__asyncify_unwind
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (local.get $live1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $5)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $9
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (local.get $9)
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store offset=4
+ ;; CHECK-NEXT: (local.get $9)
+ ;; CHECK-NEXT: (local.get $live1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $liveness3 (param $live0 i32) (param $dead0 i32)
+ (local $live1 i32)
+ (local $dead1 i32)
+ (call $import)
+ (drop (local.get $live0))
+ (call $import)
+ (drop (local.get $live1))
+ )
+ ;; CHECK: (func $liveness4 (param $live0 i32) (param $dead0 i32)
+ ;; CHECK-NEXT: (local $2 i32)
+ ;; CHECK-NEXT: (local $3 i32)
+ ;; CHECK-NEXT: (local $4 i32)
+ ;; CHECK-NEXT: (local $5 i64)
+ ;; CHECK-NEXT: (local $6 i64)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $live0
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (local.get $5)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (block $__asyncify_unwind (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.or
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $import)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__asyncify_unwind
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $6
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (local.get $6)
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $liveness4 (param $live0 i32) (param $dead0 i32)
+ (if (i32.const 0)
+ (call $import)
+ )
+ (drop (local.get $live0))
+ )
+ ;; CHECK: (func $liveness5 (param $dead0 i32)
+ ;; CHECK-NEXT: (local $1 i32)
+ ;; CHECK-NEXT: (local $2 i32)
+ ;; CHECK-NEXT: (local $3 i32)
+ ;; CHECK-NEXT: (local $4 i32)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (block $__asyncify_unwind (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (local.get $dead0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.or
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $import)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__asyncify_unwind
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $dead0
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (local.get $dead0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: )
+ (func $liveness5 (param $dead0 i32)
+ (drop (local.get $dead0))
+ (if (i32.const 0)
+ (call $import) ;; live before and after call, but not during
+ )
+ (local.set $dead0 (i32.const 1))
+ (drop (local.get $dead0))
+ )
+ ;; CHECK: (func $liveness-call-kills (param $live i32)
+ ;; CHECK-NEXT: (local $1 i32)
+ ;; CHECK-NEXT: (local $2 i32)
+ ;; CHECK-NEXT: (local $3 i32)
+ ;; CHECK-NEXT: (local $4 i64)
+ ;; CHECK-NEXT: (local $5 i64)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (block $__asyncify_unwind (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (local.get $live)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $import2
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__asyncify_unwind
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (local.get $5)
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $liveness-call-kills (param $live i32)
+ (call $import2 (local.get $live))
+ )
+ ;; CHECK: (func $liveness-indirect-kills (param $live0 i32) (param $live1 i32)
+ ;; CHECK-NEXT: (local $2 i32)
+ ;; CHECK-NEXT: (local $3 i32)
+ ;; CHECK-NEXT: (local $4 i32)
+ ;; CHECK-NEXT: (local $5 i32)
+ ;; CHECK-NEXT: (local $6 i64)
+ ;; CHECK-NEXT: (local $7 i64)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $6
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (local.get $6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (i32.load offset=4
+ ;; CHECK-NEXT: (local.get $6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (block $__asyncify_unwind (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const -4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (i32.load
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (local.get $live0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (local.get $live1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (local.get $5)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call_indirect (type $f)
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.eq
+ ;; CHECK-NEXT: (global.get $__asyncify_state)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__asyncify_unwind
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $7
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store
+ ;; CHECK-NEXT: (local.get $7)
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.store offset=4
+ ;; CHECK-NEXT: (local.get $7)
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: (i64.add
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (global.get $__asyncify_data)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 8)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $liveness-indirect-kills (param $live0 i32) (param $live1 i32)
+ (call_indirect (type $f) (local.get $live0) (local.get $live1))
+ )
+)
+;; CHECK: (func $asyncify_start_unwind (param $0 i64)
+;; CHECK-NEXT: (global.set $__asyncify_state
+;; CHECK-NEXT: (i32.const 1)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (global.set $__asyncify_data
+;; CHECK-NEXT: (local.get $0)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (if
+;; CHECK-NEXT: (i64.gt_u
+;; CHECK-NEXT: (i64.load
+;; CHECK-NEXT: (global.get $__asyncify_data)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (i64.load offset=8
+;; CHECK-NEXT: (global.get $__asyncify_data)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (unreachable)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+
+;; CHECK: (func $asyncify_stop_unwind
+;; CHECK-NEXT: (global.set $__asyncify_state
+;; CHECK-NEXT: (i32.const 0)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (if
+;; CHECK-NEXT: (i64.gt_u
+;; CHECK-NEXT: (i64.load
+;; CHECK-NEXT: (global.get $__asyncify_data)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (i64.load offset=8
+;; CHECK-NEXT: (global.get $__asyncify_data)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (unreachable)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+
+;; CHECK: (func $asyncify_start_rewind (param $0 i64)
+;; CHECK-NEXT: (global.set $__asyncify_state
+;; CHECK-NEXT: (i32.const 2)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (global.set $__asyncify_data
+;; CHECK-NEXT: (local.get $0)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (if
+;; CHECK-NEXT: (i64.gt_u
+;; CHECK-NEXT: (i64.load
+;; CHECK-NEXT: (global.get $__asyncify_data)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (i64.load offset=8
+;; CHECK-NEXT: (global.get $__asyncify_data)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (unreachable)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+
+;; CHECK: (func $asyncify_stop_rewind
+;; CHECK-NEXT: (global.set $__asyncify_state
+;; CHECK-NEXT: (i32.const 0)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (if
+;; CHECK-NEXT: (i64.gt_u
+;; CHECK-NEXT: (i64.load
+;; CHECK-NEXT: (global.get $__asyncify_data)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (i64.load offset=8
+;; CHECK-NEXT: (global.get $__asyncify_data)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (unreachable)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+
+;; CHECK: (func $asyncify_get_state (result i32)
+;; CHECK-NEXT: (global.get $__asyncify_state)
+;; CHECK-NEXT: )