summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/eh-utils.cpp84
-rw-r--r--src/ir/eh-utils.h11
-rw-r--r--src/wasm/wasm-binary.cpp5
3 files changed, 55 insertions, 45 deletions
diff --git a/src/ir/eh-utils.cpp b/src/ir/eh-utils.cpp
index 37af738ce..3d369573d 100644
--- a/src/ir/eh-utils.cpp
+++ b/src/ir/eh-utils.cpp
@@ -107,54 +107,56 @@ bool containsValidDanglingPop(Expression* catchBody) {
return pop != nullptr && !isPopNested;
}
+void handleBlockNestedPop(Try* try_, Function* func, Module& wasm) {
+ Builder builder(wasm);
+ for (Index i = 0; i < try_->catchTags.size(); i++) {
+ Name tagName = try_->catchTags[i];
+ auto* tag = wasm.getTag(tagName);
+ if (tag->sig.params == Type::none) {
+ continue;
+ }
+
+ auto* catchBody = try_->catchBodies[i];
+ bool isPopNested = false;
+ Expression** popPtr = nullptr;
+ Expression* pop = getFirstPop(catchBody, isPopNested, popPtr);
+ assert(pop && "Pop has not been found in this catch");
+
+ // Change code like
+ // (catch $e
+ // ...
+ // (block
+ // (pop i32)
+ // )
+ // )
+ // into
+ // (catch $e
+ // (local.set $new
+ // (pop i32)
+ // )
+ // ...
+ // (block
+ // (local.get $new)
+ // )
+ // )
+ if (isPopNested) {
+ assert(popPtr);
+ Index newLocal = builder.addVar(func, pop->type);
+ try_->catchBodies[i] =
+ builder.makeSequence(builder.makeLocalSet(newLocal, pop), catchBody);
+ *popPtr = builder.makeLocalGet(newLocal, pop->type);
+ }
+ }
+}
+
void handleBlockNestedPops(Function* func, Module& wasm) {
if (!wasm.features.hasExceptionHandling()) {
return;
}
-
- Builder builder(wasm);
FindAll<Try> trys(func->body);
for (auto* try_ : trys.list) {
- for (Index i = 0; i < try_->catchTags.size(); i++) {
- Name tagName = try_->catchTags[i];
- auto* tag = wasm.getTag(tagName);
- if (tag->sig.params == Type::none) {
- continue;
- }
-
- auto* catchBody = try_->catchBodies[i];
- bool isPopNested = false;
- Expression** popPtr = nullptr;
- Expression* pop = getFirstPop(catchBody, isPopNested, popPtr);
- assert(pop && "Pop has not been found in this catch");
-
- // Change code like
- // (catch $e
- // ...
- // (block
- // (pop i32)
- // )
- // )
- // into
- // (catch $e
- // (local.set $new
- // (pop i32)
- // )
- // ...
- // (block
- // (local.get $new)
- // )
- // )
- if (isPopNested) {
- assert(popPtr);
- Index newLocal = builder.addVar(func, pop->type);
- try_->catchBodies[i] =
- builder.makeSequence(builder.makeLocalSet(newLocal, pop), catchBody);
- *popPtr = builder.makeLocalGet(newLocal, pop->type);
- }
- }
+ handleBlockNestedPop(try_, func, wasm);
}
-
// Pops we handled can be of non-defaultable types, so we may have created
// non-nullable type locals. Fix them.
TypeUpdating::handleNonDefaultableLocals(func, wasm);
diff --git a/src/ir/eh-utils.h b/src/ir/eh-utils.h
index c0d6e59ea..25677a32e 100644
--- a/src/ir/eh-utils.h
+++ b/src/ir/eh-utils.h
@@ -31,10 +31,13 @@ namespace EHUtils {
// catch body, which is invalid. That will be taken care of in validation.
bool containsValidDanglingPop(Expression* catchBody);
-// Fixes up 'pop's nested in blocks, which are currently not supported without
-// block param types, by creating a new local, putting a (local.set $new (pop
-// type)) right after 'catch', and putting a '(local.get $new)' where the 'pop'
-// used to be.
+// Given a 'Try' expression, fixes up 'pop's nested in blocks, which are
+// currently not supported without block param types, by creating a new local,
+// putting a (local.set $new (pop type)) right after 'catch', and putting a
+// '(local.get $new)' where the 'pop' used to be.
+void handleBlockNestedPop(Try* try_, Function* func, Module& wasm);
+
+// Calls handleBlockNestedPop for each 'Try's in a given function.
void handleBlockNestedPops(Function* func, Module& wasm);
} // namespace EHUtils
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index d8a3c2f74..57a2bc95c 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -17,6 +17,7 @@
#include <algorithm>
#include <fstream>
+#include "ir/eh-utils.h"
#include "ir/module-utils.h"
#include "ir/table-utils.h"
#include "ir/type-updating.h"
@@ -6419,6 +6420,10 @@ void WasmBinaryBuilder::visitTryOrTryInBlock(Expression*& out) {
}
exceptionTargetNames.erase(catchLabel);
}
+
+ // If catch bodies contained stacky code, 'pop's can be nested within a block.
+ // Fix that up.
+ EHUtils::handleBlockNestedPop(curr, currFunction, wasm);
curr->finalize(curr->type);
// For simplicity, we create an inner block within the catch body too, but the