summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-02-23 23:07:11 +0000
committerGitHub <noreply@github.com>2021-02-23 15:07:11 -0800
commit538fe22e53b14695bb179796b91a6a168e99cd34 (patch)
treeca47b4510cf1ba5a33a3cfbcebeb7cb430e427f8
parenta7c66754ba86854ea3e0381986796e6565b93199 (diff)
downloadbinaryen-538fe22e53b14695bb179796b91a6a168e99cd34.tar.gz
binaryen-538fe22e53b14695bb179796b91a6a168e99cd34.tar.bz2
binaryen-538fe22e53b14695bb179796b91a6a168e99cd34.zip
[Wasm Exceptions] Fix StackIR writing of nested delegates (#3599)
We were missing a pop of catchIndexStack at a Delegate. It ends the scope, so it should do that, like TryEnd does. Found by emscripten-core/emscripten#13485 on -O2.
-rw-r--r--src/wasm-stack.h2
-rw-r--r--src/wasm/wasm-stack.cpp5
-rw-r--r--test/passes/generate-stack-ir_roundtrip_all-features.txt32
-rw-r--r--test/passes/generate-stack-ir_roundtrip_all-features.wast31
4 files changed, 70 insertions, 0 deletions
diff --git a/src/wasm-stack.h b/src/wasm-stack.h
index 7f94573fa..5af9adbce 100644
--- a/src/wasm-stack.h
+++ b/src/wasm-stack.h
@@ -350,6 +350,8 @@ template<typename SubType> void BinaryenIRWriter<SubType>::visitTry(Try* curr) {
}
if (curr->isDelegate()) {
emitDelegate(curr);
+ // Note that when we emit a delegate we do not need to also emit a scope
+ // ending, as the delegate ends the scope.
} else {
emitScopeEnd(curr);
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index b6c0392ca..4c4e4e9d1 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1925,6 +1925,9 @@ void BinaryInstWriter::emitCatchAll(Try* curr) {
}
void BinaryInstWriter::emitDelegate(Try* curr) {
+ // The delegate ends the scope in effect, and pops the try's name. Note that
+ // the getBreakIndex is intentionally after that pop, as the delegate cannot
+ // target its own try.
assert(!breakStack.empty());
breakStack.pop_back();
o << int8_t(BinaryConsts::Delegate)
@@ -2333,6 +2336,8 @@ void StackIRToBinaryWriter::write() {
}
case StackInst::Delegate: {
writer.emitDelegate(inst->origin->cast<Try>());
+ // Delegates end the try, like a TryEnd.
+ catchIndexStack.pop_back();
break;
}
default:
diff --git a/test/passes/generate-stack-ir_roundtrip_all-features.txt b/test/passes/generate-stack-ir_roundtrip_all-features.txt
new file mode 100644
index 000000000..3d06adff1
--- /dev/null
+++ b/test/passes/generate-stack-ir_roundtrip_all-features.txt
@@ -0,0 +1,32 @@
+(module
+ (type $none_=>_none (func))
+ (type $i32_=>_none (func (param i32)))
+ (event $event$0 (attr 0) (param i32))
+ (func $delegate-child
+ (try $label$9
+ (do
+ (try $label$7
+ (do
+ (nop)
+ )
+ (catch $event$0
+ (drop
+ (pop i32)
+ )
+ (try $label$6
+ (do
+ (nop)
+ )
+ (delegate 2)
+ )
+ )
+ )
+ )
+ (catch $event$0
+ (drop
+ (pop i32)
+ )
+ )
+ )
+ )
+)
diff --git a/test/passes/generate-stack-ir_roundtrip_all-features.wast b/test/passes/generate-stack-ir_roundtrip_all-features.wast
new file mode 100644
index 000000000..dc6c68d67
--- /dev/null
+++ b/test/passes/generate-stack-ir_roundtrip_all-features.wast
@@ -0,0 +1,31 @@
+(module
+ (event $event (attr 0) (param i32))
+ (func $delegate-child
+ (try
+ (do
+ (try
+ (do)
+ (catch $event
+ (drop
+ (pop i32)
+ )
+ (try
+ (do)
+ ;; the binary writer must properly handle this delegate which is the
+ ;; child of other try's, and not get confused by their information on the
+ ;; stack (this is a regression test for us properly ending the scope with
+ ;; a delegate and popping the relevant stack).
+ (delegate 2)
+ )
+ )
+ )
+ )
+ (catch $event
+ (drop
+ (pop i32)
+ )
+ )
+ )
+ )
+)
+