summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2021-12-20 20:18:32 -0800
committerGitHub <noreply@github.com>2021-12-20 20:18:32 -0800
commit083ab9842ec3d4ca278c95e1a33112ae7cd4d9e5 (patch)
treed3fbb726330a46bdabe80d05081418d0a3fd2d86 /src
parent80101484099e9451072eb8c10df69499031b3475 (diff)
downloadbinaryen-083ab9842ec3d4ca278c95e1a33112ae7cd4d9e5.tar.gz
binaryen-083ab9842ec3d4ca278c95e1a33112ae7cd4d9e5.tar.bz2
binaryen-083ab9842ec3d4ca278c95e1a33112ae7cd4d9e5.zip
[EH] Handle nested pops after inlining (#4404)
Inlining creates additional `block`s at inlined call sites, which can be inside a `catch`. For example: ```wast (try (do) (catch $tag (call $callee (pop i32) ) ) ) ``` After inlining, this becomes ```wast (try (do) (catch $tag (block $__inlined_func$callee (local.set $0 (pop i32) ;; Invalid!! ) (nop) ) ) ) ``` Now the `pop` is nested in a `block`, which makes this invalid. This PR runs `EHUtils::handleBlockNestedPops` at the end to assign the `pop` to a local right after the `catch`, making the code valid again: ```wast (try (do) (catch $tag (local.set $new ;; New local to store `pop` result (pop i32) ) (block $__inlined_func$callee (local.set $0 (local.get $new) ) (nop) ) ) ) ```
Diffstat (limited to 'src')
-rw-r--r--src/passes/Inlining.cpp5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index 018654882..e81649bd2 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -32,6 +32,7 @@
#include "ir/branch-utils.h"
#include "ir/debug.h"
+#include "ir/eh-utils.h"
#include "ir/element-utils.h"
#include "ir/literal-utils.h"
#include "ir/module-utils.h"
@@ -880,6 +881,10 @@ struct Inlining : public Pass {
#endif
for (auto* func : inlinedInto) {
+ EHUtils::handleBlockNestedPops(func, *module);
+ }
+
+ for (auto* func : inlinedInto) {
if (++iterationCounts[func->name] >= MaxIterationsForFunc) {
return;
}