summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Inlining.cpp88
-rw-r--r--src/wasm-traversal.h47
-rw-r--r--test/lit/passes/inlining-unreachable.wast58
-rw-r--r--test/lit/passes/inlining_enable-tail-call.wast859
4 files changed, 841 insertions, 211 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index 0643389c2..04bc6d78a 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -242,9 +242,10 @@ private:
struct InliningAction {
Expression** callSite;
Function* contents;
+ bool insideATry;
- InliningAction(Expression** callSite, Function* contents)
- : callSite(callSite), contents(contents) {}
+ InliningAction(Expression** callSite, Function* contents, bool insideATry)
+ : callSite(callSite), contents(contents), insideATry(insideATry) {}
};
struct InliningState {
@@ -254,7 +255,7 @@ struct InliningState {
std::unordered_map<Name, std::vector<InliningAction>> actionsForFunction;
};
-struct Planner : public WalkerPass<PostWalker<Planner>> {
+struct Planner : public WalkerPass<TryDepthWalker<Planner>> {
bool isFunctionParallel() override { return true; }
Planner(InliningState* state) : state(state) {}
@@ -287,7 +288,7 @@ struct Planner : public WalkerPass<PostWalker<Planner>> {
// can't add a new element in parallel
assert(state->actionsForFunction.count(getFunction()->name) > 0);
state->actionsForFunction[getFunction()->name].emplace_back(
- &block->list[0], getModule()->getFunction(curr->target));
+ &block->list[0], getModule()->getFunction(curr->target), tryDepth > 0);
}
}
@@ -295,7 +296,7 @@ private:
InliningState* state;
};
-struct Updater : public PostWalker<Updater> {
+struct Updater : public TryDepthWalker<Updater> {
Module* module;
std::map<Index, Index> localMapping;
Name returnName;
@@ -335,19 +336,38 @@ struct Updater : public PostWalker<Updater> {
return;
}
- // Set the children to locals as necessary, then add a branch out of the
- // inlined body. The branch label will be set later when we create branch
- // targets for the calls.
- Block* childBlock = ChildLocalizer(curr, getFunction(), *module, options)
- .getChildrenReplacement();
- Break* branch = builder->makeBreak(Name());
- childBlock->list.push_back(branch);
- childBlock->type = Type::unreachable;
- replaceCurrent(childBlock);
-
- curr->isReturn = false;
- curr->type = sig.results;
- returnCallInfos.push_back({curr, branch});
+ if (tryDepth == 0) {
+ // Return calls in inlined functions should only break out of
+ // the scope of the inlined code, not the entire function they
+ // are being inlined into. To achieve this, make the call a
+ // non-return call and add a break. This does not cause
+ // unbounded stack growth because inlining and return calling
+ // both avoid creating a new stack frame.
+ curr->isReturn = false;
+ curr->type = sig.results;
+ // There might still be unreachable children causing this to be
+ // unreachable.
+ curr->finalize();
+ if (sig.results.isConcrete()) {
+ replaceCurrent(builder->makeBreak(returnName, curr));
+ } else {
+ replaceCurrent(builder->blockify(curr, builder->makeBreak(returnName)));
+ }
+ } else {
+ // Set the children to locals as necessary, then add a branch out of the
+ // inlined body. The branch label will be set later when we create branch
+ // targets for the calls.
+ Block* childBlock = ChildLocalizer(curr, getFunction(), *module, options)
+ .getChildrenReplacement();
+ Break* branch = builder->makeBreak(Name());
+ childBlock->list.push_back(branch);
+ childBlock->type = Type::unreachable;
+ replaceCurrent(childBlock);
+
+ curr->isReturn = false;
+ curr->type = sig.results;
+ returnCallInfos.push_back({curr, branch});
+ }
}
void visitCall(Call* curr) {
@@ -464,14 +484,15 @@ static Expression* doInlining(Module* module,
//
// (In this case we could use a second block and define the named block $X
// after the call's parameters, but that adds work for an extremely rare
- // situation.) The latter case does not apply if the call is a return_call,
- // because in that case the call's children do not appear inside the same
- // block as the inlined body.
+ // situation.) The latter case does not apply if the call is a
+ // return_call inside a try, because in that case the call's
+ // children do not appear inside the same block as the inlined body.
+ bool hoistCall = call->isReturn && action.insideATry;
if (BranchUtils::hasBranchTarget(from->body, block->name) ||
- (!call->isReturn && BranchUtils::BranchSeeker::has(call, block->name))) {
+ (!hoistCall && BranchUtils::BranchSeeker::has(call, block->name))) {
auto fromNames = BranchUtils::getBranchTargets(from->body);
- auto callNames = call->isReturn ? BranchUtils::NameSet{}
- : BranchUtils::BranchAccumulator::get(call);
+ auto callNames = hoistCall ? BranchUtils::NameSet{}
+ : BranchUtils::BranchAccumulator::get(call);
block->name = Names::getValidName(block->name, [&](Name test) {
return !fromNames.count(test) && !callNames.count(test);
});
@@ -490,7 +511,7 @@ static Expression* doInlining(Module* module,
updater.localMapping[i] = builder.addVar(into, from->getLocalType(i));
}
- if (call->isReturn) {
+ if (hoistCall) {
// Wrap the existing function body in a block we can branch out of before
// entering the inlined function body. This block must have a name that is
// different from any other block name above the branch.
@@ -544,7 +565,16 @@ static Expression* doInlining(Module* module,
builder.makeLocalSet(updater.localMapping[from->getVarIndexBase() + i],
LiteralUtils::makeZero(type, *module)));
}
- *action.callSite = block;
+ if (call->isReturn) {
+ assert(!action.insideATry);
+ if (retType.isConcrete()) {
+ *action.callSite = builder.makeReturn(block);
+ } else {
+ *action.callSite = builder.makeSequence(block, builder.makeReturn());
+ }
+ } else {
+ *action.callSite = block;
+ }
}
// Generate and update the inlined contents
@@ -1396,8 +1426,10 @@ struct InlineMainPass : public Pass {
// No call at all.
return;
}
- doInlining(
- module, main, InliningAction(callSite, originalMain), getPassOptions());
+ doInlining(module,
+ main,
+ InliningAction(callSite, originalMain, true),
+ getPassOptions());
}
};
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index f5f25dd1f..c8078164b 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -537,6 +537,53 @@ struct ExpressionStackWalker : public PostWalker<SubType, VisitorType> {
}
};
+// Traversal keeping track of try depth
+
+// This is used to keep track of whether we are in the scope of an
+// exception handler. This matters since return_call is not equivalent
+// to return + call within an exception handler. If another kind of
+// handler scope is added, this code will need to be updated.
+template<typename SubType, typename VisitorType = Visitor<SubType>>
+struct TryDepthWalker : public PostWalker<SubType, VisitorType> {
+ TryDepthWalker() = default;
+
+ size_t tryDepth = 0;
+
+ static void doEnterTry(SubType* self, Expression** currp) {
+ self->tryDepth++;
+ }
+
+ static void doLeaveTry(SubType* self, Expression** currp) {
+ self->tryDepth--;
+ }
+
+ static void scan(SubType* self, Expression** currp) {
+ auto* curr = *currp;
+
+ if (curr->is<Try>()) {
+ self->pushTask(SubType::doVisitTry, currp);
+ auto& catchBodies = curr->cast<Try>()->catchBodies;
+ for (int i = int(catchBodies.size()) - 1; i >= 0; i--) {
+ self->pushTask(SubType::scan, &catchBodies[i]);
+ }
+ self->pushTask(SubType::doLeaveTry, currp);
+ self->pushTask(SubType::scan, &curr->cast<Try>()->body);
+ self->pushTask(SubType::doEnterTry, currp);
+ return;
+ }
+
+ if (curr->is<TryTable>()) {
+ self->pushTask(SubType::doLeaveTry, currp);
+ }
+
+ PostWalker<SubType, VisitorType>::scan(self, currp);
+
+ if (curr->is<TryTable>()) {
+ self->pushTask(SubType::doEnterTry, currp);
+ }
+ }
+};
+
} // namespace wasm
#endif // wasm_wasm_traversal_h
diff --git a/test/lit/passes/inlining-unreachable.wast b/test/lit/passes/inlining-unreachable.wast
index 2c93359fd..1b08ac2b0 100644
--- a/test/lit/passes/inlining-unreachable.wast
+++ b/test/lit/passes/inlining-unreachable.wast
@@ -66,22 +66,51 @@
)
(module
- ;; CHECK: (type $0 (func (param i32) (result i32)))
+ ;; CHECK: (type $0 (func))
- ;; CHECK: (type $1 (func))
+ ;; CHECK: (type $1 (func (param i32) (result i32)))
- ;; CHECK: (import "env" "imported" (func $imported (type $0) (param i32) (result i32)))
+ ;; CHECK: (import "env" "imported" (func $imported (type $1) (param i32) (result i32)))
(import "env" "imported" (func $imported (param i32) (result i32)))
- ;; CHECK: (func $caller (type $1)
+ ;; CHECK: (func $caller (type $0)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$callee
+ ;; CHECK-NEXT: (call $imported
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller
+ (drop
+ (call $callee)
+ )
+ )
+
+ ;; After inlining, this return_call will turn into a call, but should still be
+ ;; unreachable. Validation will fail if it is not.
+ (func $callee (result i32)
+ (return_call $imported
+ (unreachable)
+ )
+ )
+
+ ;; CHECK: (func $caller-2 (type $0)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$callee-2$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__return_call
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (unreachable)
- ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call $imported
@@ -92,17 +121,20 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $caller
+ (func $caller-2
(drop
- (call $callee)
+ (call $callee-2)
)
)
- ;; After inlining, this return_call will turn into a call, but should still be
- ;; unreachable. Validation will fail if it is not.
- (func $callee (result i32)
- (return_call $imported
- (unreachable)
+ ;; Same as above, but with a return_call with a try block
+ (func $callee-2 (result i32)
+ (try
+ (do
+ (return_call $imported
+ (unreachable)
+ )
+ )
)
)
)
diff --git a/test/lit/passes/inlining_enable-tail-call.wast b/test/lit/passes/inlining_enable-tail-call.wast
index 49ea1c3c4..77aa77974 100644
--- a/test/lit/passes/inlining_enable-tail-call.wast
+++ b/test/lit/passes/inlining_enable-tail-call.wast
@@ -1,7 +1,7 @@
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; NOTE: This test was ported using port_passes_tests_to_lit.py and could be cleaned up.
-;; RUN: foreach %s %t wasm-opt --inlining --enable-tail-call -S -o - | filecheck %s
+;; RUN: foreach %s %t wasm-opt --inlining --enable-tail-call --enable-exception-handling -S -o - | filecheck %s
(module
(table 1 1 funcref)
@@ -474,20 +474,39 @@
;; CHECK: (type $0 (func))
;; CHECK: (func $caller
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$callee
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller
+ (return_call $callee)
+ )
+ ;; CHECK: (func $caller-2
;; CHECK-NEXT: (block $__original_body
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__original_body)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (br $__original_body)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block $__inlined_func$callee
+ ;; CHECK-NEXT: (block $__inlined_func$callee$1
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $caller
- (return_call $callee)
+ (func $caller-2
+ (try
+ (do
+ (return_call $callee)
+ )
+ )
)
(func $callee
(drop
@@ -501,19 +520,35 @@
;; CHECK: (type $0 (func (result i32)))
;; CHECK: (func $caller (result i32)
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (block $__inlined_func$callee (result i32)
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller (result i32)
+ (return_call $callee)
+ )
+ ;; CHECK: (func $caller-2 (result i32)
;; CHECK-NEXT: (block $__original_body
;; CHECK-NEXT: (return
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__original_body)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (br $__original_body)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block $__inlined_func$callee (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$callee$1 (result i32)
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $caller (result i32)
- (return_call $callee)
+ (func $caller-2 (result i32)
+ (try
+ (do
+ (return_call $callee)
+ )
+ )
)
(func $callee (result i32)
(i32.const 42)
@@ -526,26 +561,51 @@
;; CHECK: (func $caller
;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$callee
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller
+ (return_call $callee
+ (i32.const 42)
+ )
+ )
+ ;; CHECK: (func $caller-2
+ ;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (block $__original_body
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block $__inlined_func$callee
+ ;; CHECK-NEXT: (block $__inlined_func$callee$1
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $caller
- (return_call $callee
- (i32.const 42)
+ (func $caller-2
+ (try
+ (do
+ (return_call $callee
+ (i32.const 42)
+ )
+ )
)
)
(func $callee (param i32)
@@ -561,25 +621,47 @@
;; CHECK: (func $caller (result i32)
;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (block $__inlined_func$callee (result i32)
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller (result i32)
+ (return_call $callee
+ (i32.const 42)
+ )
+ )
+ ;; CHECK: (func $caller-2 (result i32)
+ ;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (block $__original_body
;; CHECK-NEXT: (return
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.set $0
- ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block $__inlined_func$callee (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$callee$1 (result i32)
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $caller (result i32)
- (return_call $callee
- (i32.const 42)
+ (func $caller-2 (result i32)
+ (try
+ (do
+ (return_call $callee
+ (i32.const 42)
+ )
+ )
)
)
(func $callee (param i32) (result i32)
@@ -596,16 +678,64 @@
;; CHECK-NEXT: (local $y i32)
;; CHECK-NEXT: (local $2 i32)
;; CHECK-NEXT: (local $3 i32)
- ;; CHECK-NEXT: (block $__original_body
- ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$callee
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.set $2
- ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (local.set $3
- ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller
+ (local $x i32)
+ (local $y i32)
+ (return_call $callee
+ (local.get $x)
+ (local.get $y)
+ )
+ )
+ (func $callee (param i32 i32)
+ (drop
+ (local.get 0)
+ )
+ (drop
+ (local.get 1)
+ )
+ )
+)
+(module
+ ;; Multiple params, no result, return_call within try block
+ ;; CHECK: (type $0 (func))
+
+ ;; CHECK: (func $caller
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (local $y i32)
+ ;; CHECK-NEXT: (local $2 i32)
+ ;; CHECK-NEXT: (local $3 i32)
+ ;; CHECK-NEXT: (block $__original_body
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
@@ -624,9 +754,13 @@
(func $caller
(local $x i32)
(local $y i32)
- (return_call $callee
- (local.get $x)
- (local.get $y)
+ (try
+ (do
+ (return_call $callee
+ (local.get $x)
+ (local.get $y)
+ )
+ )
)
)
(func $callee (param i32 i32)
@@ -644,36 +778,73 @@
;; CHECK: (type $0 (func))
;; CHECK: (func $first
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$second
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$third$2
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (return)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $first
+ (return_call $second)
+ )
+ ;; CHECK: (func $first-2
;; CHECK-NEXT: (block $__original_body_0
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__original_body
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__original_body)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (br $__original_body)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block $__inlined_func$second
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__original_body_0)
+ ;; CHECK-NEXT: (block $__inlined_func$second-2$1
+ ;; CHECK-NEXT: (try $try0
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (br $__original_body_0)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block $__inlined_func$third$1
+ ;; CHECK-NEXT: (block $__inlined_func$third$3
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $first
- (return_call $second)
+ (func $first-2
+ (try
+ (do
+ (return_call $second-2)
+ )
+ )
)
(func $second
(return_call $third)
)
+ (func $second-2
+ (try
+ (do
+ (return_call $third)
+ )
+ )
+ )
(func $third
(drop
(i32.const 42)
@@ -692,35 +863,109 @@
;; CHECK-NEXT: (local $3 i32)
;; CHECK-NEXT: (local $4 i32)
;; CHECK-NEXT: (local $5 i32)
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (block $__inlined_func$second
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (block $__inlined_func$third$1 (result i32)
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $5)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $first (result i32)
+ (local $x i32)
+ (local $y i32)
+ (return_call $second
+ (local.get $x)
+ (local.get $y)
+ )
+ )
+ (func $second (param i32 i32) (result i32)
+ (return_call $third
+ (local.get 0)
+ (local.get 1)
+ )
+ )
+ (func $third (param i32 i32) (result i32)
+ (drop
+ (local.get 0)
+ )
+ (drop
+ (local.get 1)
+ )
+ (i32.const 42)
+ )
+)
+
+(module
+ ;; Chain of return_calls with params and results, return_calls in try block.
+ ;; CHECK: (type $0 (func (result i32)))
+
+ ;; CHECK: (func $first (result i32)
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (local $y i32)
+ ;; CHECK-NEXT: (local $2 i32)
+ ;; CHECK-NEXT: (local $3 i32)
+ ;; CHECK-NEXT: (local $4 i32)
+ ;; CHECK-NEXT: (local $5 i32)
;; CHECK-NEXT: (block $__original_body_0
;; CHECK-NEXT: (return
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__original_body
;; CHECK-NEXT: (return
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.set $2
- ;; CHECK-NEXT: (local.get $x)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (local.set $3
- ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $2
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $3
+ ;; CHECK-NEXT: (local.get $y)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block $__inlined_func$second
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (try $try0
+ ;; CHECK-NEXT: (do
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.set $4
- ;; CHECK-NEXT: (local.get $2)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (local.set $5
- ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (local.set $4
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.set $5
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__original_body_0)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__original_body_0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -743,15 +988,23 @@
(func $first (result i32)
(local $x i32)
(local $y i32)
- (return_call $second
- (local.get $x)
- (local.get $y)
+ (try
+ (do
+ (return_call $second
+ (local.get $x)
+ (local.get $y)
+ )
+ )
)
)
(func $second (param i32 i32) (result i32)
- (return_call $third
- (local.get 0)
- (local.get 1)
+ (try
+ (do
+ (return_call $third
+ (local.get 0)
+ (local.get 1)
+ )
+ )
)
)
(func $third (param i32 i32) (result i32)
@@ -768,20 +1021,46 @@
(module
;; CHECK: (type $0 (func))
- ;; CHECK: (func $0
+ ;; CHECK: (func $first
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$1 (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$second (result i32)
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (br $__inlined_func$second
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$third$2 (result i32)
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $first
+ (drop
+ (call $second)
+ )
+ )
+ ;; CHECK: (func $first-2
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$second-2$1 (result i32)
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__return_call
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$2$1 (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$third$3 (result i32)
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
@@ -790,15 +1069,22 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $0
+ (func $first-2
(drop
- (call $1)
+ (call $second-2)
)
)
- (func $1 (result i32)
- (return_call $2)
+ (func $second (result i32)
+ (return_call $third)
+ )
+ (func $second-2 (result i32)
+ (try
+ (do
+ (return_call $third)
+ )
+ )
)
- (func $2 (result i32)
+ (func $third (result i32)
(i32.const 42)
)
)
@@ -806,18 +1092,45 @@
(module
;; CHECK: (type $0 (func))
- ;; CHECK: (func $0
+ ;; CHECK: (func $first
;; CHECK-NEXT: (local $0 i32)
- ;; CHECK-NEXT: (block $__inlined_func$1
+ ;; CHECK-NEXT: (block $__inlined_func$second
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block $__return_call
+ ;; CHECK-NEXT: (block
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: (block $__inlined_func$third$2
+ ;; CHECK-NEXT: (local.set $0
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__inlined_func$second)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $first
+ (call $second)
+ )
+ ;; CHECK: (func $first-2
+ ;; CHECK-NEXT: (local $0 i32)
+ ;; CHECK-NEXT: (block $__inlined_func$second-2$1
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__return_call
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__inlined_func$1)
+ ;; CHECK-NEXT: (br $__inlined_func$second-2$1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block $__inlined_func$2$1
+ ;; CHECK-NEXT: (block $__inlined_func$third$3
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: )
@@ -829,15 +1142,24 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $0
- (call $1)
+ (func $first-2
+ (call $second-2)
)
- (func $1
- (return_call $2
+ (func $second
+ (return_call $third
(i32.const 42)
)
)
- (func $2 (param i32)
+ (func $second-2
+ (try
+ (do
+ (return_call $third
+ (i32.const 42)
+ )
+ )
+ )
+ )
+ (func $third (param i32)
(drop
(local.get 0)
)
@@ -850,34 +1172,60 @@
;; CHECK: (type $1 (func (param i32)))
- ;; CHECK: (func $0
- ;; CHECK-NEXT: (block $__inlined_func$1
+ ;; CHECK: (func $first
+ ;; CHECK-NEXT: (block $__inlined_func$second
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $third
+ ;; CHECK-NEXT: (br $__inlined_func$second)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__inlined_func$second)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $first
+ (call $second)
+ )
+ ;; CHECK: (func $first-2
+ ;; CHECK-NEXT: (block $__inlined_func$second-2$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__return_call
- ;; CHECK-NEXT: (br $__inlined_func$1)
- ;; CHECK-NEXT: (br $__return_call)
- ;; CHECK-NEXT: (br $__inlined_func$1)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (br $__inlined_func$second-2$1)
+ ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__inlined_func$second-2$1)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (call $2
+ ;; CHECK-NEXT: (call $third
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $0
- (call $1)
+ (func $first-2
+ (call $second-2)
)
- (func $1
- (return_call $2
+ (func $second
+ (return_call $third
(return)
)
)
- ;; CHECK: (func $2 (param $0 i32)
+ (func $second-2
+ (try
+ (do
+ (return_call $third
+ (return)
+ )
+ )
+ )
+ )
+ ;; CHECK: (func $third (param $0 i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $2 (param i32)
+ (func $third (param i32)
(drop
(local.get 0)
)
@@ -888,24 +1236,47 @@
;; Same as above, but this time the child is not unreachable.
;; CHECK: (type $0 (func))
- ;; CHECK: (func $0
+ ;; CHECK: (type $1 (func (param i32)))
+
+ ;; CHECK: (func $first
+ ;; CHECK-NEXT: (block $__inlined_func$second
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (call $third
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (br $__inlined_func$second)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__inlined_func$second)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $first
+ (call $second)
+ )
+ ;; CHECK: (func $first-2
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
- ;; CHECK-NEXT: (block $__inlined_func$1
+ ;; CHECK-NEXT: (block $__inlined_func$second-2$1
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__return_call
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.tee $0
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__inlined_func$1)
+ ;; CHECK-NEXT: (local.tee $0
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (br $__inlined_func$second-2$1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__return_call)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__return_call)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__inlined_func$1)
+ ;; CHECK-NEXT: (br $__inlined_func$second-2$1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block $__inlined_func$2$1
+ ;; CHECK-NEXT: (block $__inlined_func$third$2
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
@@ -917,17 +1288,33 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $0
- (call $1)
+ (func $first-2
+ (call $second-2)
)
- (func $1
- (return_call $2
+ (func $second
+ (return_call $third
(block (result i32)
(return)
)
)
)
- (func $2 (param i32)
+ (func $second-2
+ (try
+ (do
+ (return_call $third
+ (block (result i32)
+ (return)
+ )
+ )
+ )
+ )
+ )
+ ;; CHECK: (func $third (param $0 i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $third (param i32)
(drop
(local.get 0)
)
@@ -942,14 +1329,43 @@
(table 10 funcref)
;; CHECK: (table $0 10 funcref)
- ;; CHECK: (func $0
+ ;; CHECK: (func $caller
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$callee (result i32)
+ ;; CHECK-NEXT: (br $__inlined_func$callee
+ ;; CHECK-NEXT: (call_indirect (type $T)
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller
+ (drop
+ (call $callee)
+ )
+ )
+ (func $callee (result i32)
+ (return_call_indirect (type $T)
+ (i32.const 42)
+ (i32.const 0)
+ )
+ )
+ ;; CHECK: (func $caller-2
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result i32)
- ;; CHECK-NEXT: (block $__inlined_func$1 (result i32)
+ ;; CHECK-NEXT: (block $__inlined_func$callee-2$1 (result i32)
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (block $__return_call
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (call_indirect (type $T)
@@ -961,15 +1377,19 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $0
+ (func $caller-2
(drop
- (call $1)
+ (call $callee-2)
)
)
- (func $1 (result i32)
- (return_call_indirect (type $T)
- (i32.const 42)
- (i32.const 0)
+ (func $callee-2 (result i32)
+ (try
+ (do
+ (return_call_indirect (type $T)
+ (i32.const 42)
+ (i32.const 0)
+ )
+ )
)
)
)
@@ -981,29 +1401,57 @@
(table 10 funcref)
;; CHECK: (table $0 10 funcref)
- ;; CHECK: (func $0
- ;; CHECK-NEXT: (block $__inlined_func$1
+ ;; CHECK: (func $caller
+ ;; CHECK-NEXT: (block $__inlined_func$callee
;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (block $__return_call
- ;; CHECK-NEXT: (br $__return_call)
- ;; CHECK-NEXT: (br $__inlined_func$1)
- ;; CHECK-NEXT: )
;; CHECK-NEXT: (call_indirect (type $T)
;; CHECK-NEXT: (i32.const 42)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__inlined_func$callee)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $0
- (call $1)
+ (func $caller
+ (call $callee)
)
- (func $1
+ (func $callee
(return_call_indirect (type $T)
(i32.const 42)
(i32.const 0)
)
)
+ ;; CHECK: (func $caller-2
+ ;; CHECK-NEXT: (block $__inlined_func$callee-2$1
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__return_call
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (br $__return_call)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__inlined_func$callee-2$1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (call_indirect (type $T)
+ ;; CHECK-NEXT: (i32.const 42)
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $caller-2
+ (call $callee-2)
+ )
+ (func $callee-2
+ (try
+ (do
+ (return_call_indirect (type $T)
+ (i32.const 42)
+ (i32.const 0)
+ )
+ )
+ )
+ )
)
(module
;; CHECK: (type $6 (func))
@@ -1040,6 +1488,80 @@
;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__inlined_func$13$1
;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (global.get $global$0)
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$2
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (global.get $global$0)
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (br $__inlined_func$2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (global.set $global$0
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $__inlined_func$13$1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ (func $19 (; 19 ;) (type $6)
+ (call $13)
+ (unreachable)
+ )
+)
+(module
+ ;; CHECK: (type $6 (func))
+ (type $6 (func))
+ ;; CHECK: (global $global$0 (mut i32) (i32.const 10))
+
+ ;; CHECK: (memory $0 1 1)
+ (memory $0 1 1)
+ (global $global$0 (mut i32) (i32.const 10))
+ ;; CHECK: (export "func_102_invoker" (func $19))
+ (export "func_102_invoker" (func $19))
+ (func $2 (; 2 ;) (type $6)
+ (if
+ (global.get $global$0)
+ (then
+ (return)
+ )
+ )
+ (global.set $global$0
+ (i32.const 1)
+ )
+ )
+ (func $13 (; 13 ;) (type $6)
+ (if
+ (global.get $global$0)
+ (then
+ (unreachable)
+ )
+ )
+ (try
+ (do
+ (return_call $2)
+ )
+ )
+ )
+ ;; CHECK: (func $19
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (block $__inlined_func$13$1
+ ;; CHECK-NEXT: (block
;; CHECK-NEXT: (block $__original_body
;; CHECK-NEXT: (block
;; CHECK-NEXT: (if
@@ -1048,8 +1570,10 @@
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (br $__original_body)
+ ;; CHECK-NEXT: (try $try
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (br $__original_body)
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $__inlined_func$13$1)
@@ -1086,42 +1610,37 @@
(export "is_even" (func $is_even))
;; CHECK: (func $is_even (param $i i32) (result i32)
;; CHECK-NEXT: (local $1 i32)
- ;; CHECK-NEXT: (block $__original_body
- ;; CHECK-NEXT: (return
- ;; CHECK-NEXT: (if (result i32)
- ;; CHECK-NEXT: (i32.eqz
- ;; CHECK-NEXT: (local.get $i)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (then
- ;; CHECK-NEXT: (i32.const 1)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (else
- ;; CHECK-NEXT: (block
- ;; CHECK-NEXT: (local.set $1
- ;; CHECK-NEXT: (i32.sub
- ;; CHECK-NEXT: (local.get $i)
- ;; CHECK-NEXT: (i32.const 1)
- ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eqz
+ ;; CHECK-NEXT: (local.get $i)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (else
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (block $__inlined_func$is_odd (result i32)
+ ;; CHECK-NEXT: (local.set $1
+ ;; CHECK-NEXT: (i32.sub
+ ;; CHECK-NEXT: (local.get $i)
+ ;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (br $__original_body)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (block $__inlined_func$is_odd (result i32)
- ;; CHECK-NEXT: (if (result i32)
- ;; CHECK-NEXT: (i32.eqz
- ;; CHECK-NEXT: (local.get $1)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (then
- ;; CHECK-NEXT: (i32.const 0)
- ;; CHECK-NEXT: )
- ;; CHECK-NEXT: (else
- ;; CHECK-NEXT: (return_call $is_even
- ;; CHECK-NEXT: (i32.sub
- ;; CHECK-NEXT: (local.get $1)
- ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.eqz
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (else
+ ;; CHECK-NEXT: (return_call $is_even
+ ;; CHECK-NEXT: (i32.sub
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )