diff options
Diffstat (limited to 'src/passes/Flatten.cpp')
-rw-r--r-- | src/passes/Flatten.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index 298b6241e..be43e57f2 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -41,6 +41,7 @@ #include <ir/branch-utils.h> #include <ir/effects.h> +#include <ir/eh-utils.h> #include <ir/flat.h> #include <ir/properties.h> #include <ir/type-updating.h> @@ -192,6 +193,37 @@ struct Flatten loop->finalize(); replaceCurrent(rep); + } else if (auto* tryy = curr->dynCast<Try>()) { + // remove a try value + Expression* rep = tryy; + auto* originalBody = tryy->body; + std::vector<Expression*> originalCatchBodies(tryy->catchBodies.begin(), + tryy->catchBodies.end()); + auto type = tryy->type; + if (type.isConcrete()) { + Index temp = builder.addVar(getFunction(), type); + if (tryy->body->type.isConcrete()) { + tryy->body = builder.makeLocalSet(temp, tryy->body); + } + for (Index i = 0; i < tryy->catchBodies.size(); i++) { + if (tryy->catchBodies[i]->type.isConcrete()) { + tryy->catchBodies[i] = + builder.makeLocalSet(temp, tryy->catchBodies[i]); + } + } + // and we leave just a get of the value + rep = builder.makeLocalGet(temp, type); + // the whole try is now a prelude + ourPreludes.push_back(tryy); + } + tryy->body = getPreludesWithExpression(originalBody, tryy->body); + for (Index i = 0; i < tryy->catchBodies.size(); i++) { + tryy->catchBodies[i] = getPreludesWithExpression( + originalCatchBodies[i], tryy->catchBodies[i]); + } + tryy->finalize(); + replaceCurrent(rep); + } else { WASM_UNREACHABLE("unexpected expr type"); } @@ -347,6 +379,10 @@ struct Flatten << type; } } + + // Flatten can generate blocks within 'catch', making pops invalid. Fix them + // up. + EHUtils::handleBlockNestedPops(curr, *getModule()); } private: |