diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/eh-utils.cpp | 31 | ||||
-rw-r--r-- | src/ir/eh-utils.h | 20 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 27 |
3 files changed, 53 insertions, 25 deletions
diff --git a/src/ir/eh-utils.cpp b/src/ir/eh-utils.cpp index 3d369573d..fe33b09c2 100644 --- a/src/ir/eh-utils.cpp +++ b/src/ir/eh-utils.cpp @@ -162,6 +162,37 @@ void handleBlockNestedPops(Function* func, Module& wasm) { TypeUpdating::handleNonDefaultableLocals(func, wasm); } +Pop* findPop(Expression* expr) { + auto pops = findPops(expr); + if (pops.size() == 0) { + return nullptr; + } + assert(pops.size() == 1); + return pops[0]; +} + +SmallVector<Pop*, 1> findPops(Expression* expr) { + SmallVector<Pop*, 1> pops; + SmallVector<Expression*, 8> work; + work.push_back(expr); + while (!work.empty()) { + auto* curr = work.back(); + work.pop_back(); + if (auto* pop = curr->dynCast<Pop>()) { + pops.push_back(pop); + } else if (auto* try_ = curr->dynCast<Try>()) { + // We don't go into inner catch bodies; pops in inner catch bodies + // belong to the inner catches + work.push_back(try_->body); + } else { + for (auto* child : ChildIterator(curr)) { + work.push_back(child); + } + } + } + return pops; +}; + } // namespace EHUtils } // namespace wasm diff --git a/src/ir/eh-utils.h b/src/ir/eh-utils.h index 25677a32e..79ccbc507 100644 --- a/src/ir/eh-utils.h +++ b/src/ir/eh-utils.h @@ -17,6 +17,7 @@ #ifndef wasm_ir_eh_h #define wasm_ir_eh_h +#include "support/small_vector.h" #include "wasm.h" namespace wasm { @@ -40,6 +41,25 @@ void handleBlockNestedPop(Try* try_, Function* func, Module& wasm); // Calls handleBlockNestedPop for each 'Try's in a given function. void handleBlockNestedPops(Function* func, Module& wasm); +// Given a catch body, find the pop corresponding to the catch. There might be +// pops nested inside a try inside this catch, and we must ignore them, like +// here: +// +// (catch +// (pop) ;; we want this for the outer catch +// (try +// (catch +// (pop) ;; but we do not want this for the outer catch +// +// If there is no pop, which can happen if the tag has no params, then nullptr +// is returned. +Pop* findPop(Expression* expr); + +// Like findPop(), but it does *not* assume that the module validates. A catch +// might therefore have any number of pops. This function is primarily useful in +// the validator - normally you should call findPop(), above. +SmallVector<Pop*, 1> findPops(Expression* expr); + } // namespace EHUtils } // namespace wasm diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 9845da72c..57b52e182 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2165,29 +2165,6 @@ void FunctionValidator::visitTry(Try* curr) { curr, "try cannot have both catch and delegate at the same time"); - // Given a catch body, find pops corresponding to the catch - auto findPops = [](Expression* expr) { - SmallVector<Pop*, 1> pops; - SmallVector<Expression*, 8> work; - work.push_back(expr); - while (!work.empty()) { - auto* curr = work.back(); - work.pop_back(); - if (auto* pop = curr->dynCast<Pop>()) { - pops.push_back(pop); - } else if (auto* try_ = curr->dynCast<Try>()) { - // We don't go into inner catch bodies; pops in inner catch bodies - // belong to the inner catches - work.push_back(try_->body); - } else { - for (auto* child : ChildIterator(curr)) { - work.push_back(child); - } - } - } - return pops; - }; - for (Index i = 0; i < curr->catchTags.size(); i++) { Name tagName = curr->catchTags[i]; auto* tag = getModule()->getTagOrNull(tagName); @@ -2196,7 +2173,7 @@ void FunctionValidator::visitTry(Try* curr) { } auto* catchBody = curr->catchBodies[i]; - SmallVector<Pop*, 1> pops = findPops(catchBody); + auto pops = EHUtils::findPops(catchBody); if (tag->sig.params == Type::none) { if (!shouldBeTrue(pops.empty(), curr, "")) { getStream() << "catch's tag (" << tagName @@ -2225,7 +2202,7 @@ void FunctionValidator::visitTry(Try* curr) { if (curr->hasCatchAll()) { auto* catchAllBody = curr->catchBodies.back(); - shouldBeTrue(findPops(catchAllBody).empty(), + shouldBeTrue(EHUtils::findPops(catchAllBody).empty(), curr, "catch_all's body should not have pops"); } |