diff options
author | Heejin Ahn <aheejin@gmail.com> | 2021-12-20 20:18:32 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-20 20:18:32 -0800 |
commit | 083ab9842ec3d4ca278c95e1a33112ae7cd4d9e5 (patch) | |
tree | d3fbb726330a46bdabe80d05081418d0a3fd2d86 /src | |
parent | 80101484099e9451072eb8c10df69499031b3475 (diff) | |
download | binaryen-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.cpp | 5 |
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; } |