summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-s-parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-s-parser.cpp')
-rw-r--r--src/wasm/wasm-s-parser.cpp51
1 files changed, 41 insertions, 10 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index d76a3c49a..84576fde7 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1947,13 +1947,20 @@ Expression* SExpressionWasmBuilder::makeRefEq(Element& s) {
// try-catch-end is written in the folded wast format as
// (try
-// ...
+// (do
+// ...
+// )
// (catch
// ...
// )
+// ...
+// (catch_all
+// ...
+// )
// )
-// The parenthesis wrapping 'catch' is just a syntax and does not affect nested
-// depths of instructions within.
+// Any number of catch blocks can exist, including none. Zero or one catch_all
+// block can exist, and if it does, it should be at the end. There should be at
+// least one catch or catch_all body per try.
Expression* SExpressionWasmBuilder::makeTry(Element& s) {
auto ret = allocator.alloc<Try>();
Index i = 1;
@@ -1966,15 +1973,38 @@ Expression* SExpressionWasmBuilder::makeTry(Element& s) {
}
auto label = nameMapper.pushLabelName(sName);
Type type = parseOptionalResultType(s, i); // signature
+
if (!elementStartsWith(*s[i], "do")) {
throw ParseException(
"try body should start with 'do'", s[i]->line, s[i]->col);
}
- ret->body = makeTryOrCatchBody(*s[i++], type, true);
- if (!elementStartsWith(*s[i], "catch")) {
- throw ParseException("catch clause does not exist", s[i]->line, s[i]->col);
+ ret->body = makeMaybeBlock(*s[i++], 1, type);
+
+ while (i < s.size() && elementStartsWith(*s[i], "catch")) {
+ Element& inner = *s[i++];
+ if (inner.size() < 3) {
+ throw ParseException("invalid catch block", inner.line, inner.col);
+ }
+ Name event = getEventName(*inner[1]);
+ if (!wasm.getEventOrNull(event)) {
+ throw ParseException("bad event name", inner[1]->line, inner[1]->col);
+ }
+ ret->catchEvents.push_back(getEventName(*inner[1]));
+ ret->catchBodies.push_back(makeMaybeBlock(inner, 2, type));
+ }
+
+ if (i < s.size() && elementStartsWith(*s[i], "catch_all")) {
+ ret->catchBodies.push_back(makeMaybeBlock(*s[i++], 1, type));
+ }
+
+ if (i != s.size()) {
+ throw ParseException(
+ "there should be at most one catch_all block at the end", s.line, s.col);
+ }
+ if (ret->catchBodies.empty()) {
+ throw ParseException("no catch bodies", s.line, s.col);
}
- ret->catchBody = makeTryOrCatchBody(*s[i++], type, false);
+
ret->finalize(type);
nameMapper.popLabelName(label);
// create a break target if we must
@@ -1993,10 +2023,11 @@ SExpressionWasmBuilder::makeTryOrCatchBody(Element& s, Type type, bool isTry) {
if (isTry && !elementStartsWith(s, "do")) {
throw ParseException("invalid try do clause", s.line, s.col);
}
- if (!isTry && !elementStartsWith(s, "catch")) {
+ if (!isTry && !elementStartsWith(s, "catch") &&
+ !elementStartsWith(s, "catch_all")) {
throw ParseException("invalid catch clause", s.line, s.col);
}
- if (s.size() == 1) { // (do) or (catch) without instructions
+ if (s.size() == 1) { // (do) / (catch) / (catch_all) without instructions
return makeNop();
}
auto ret = allocator.alloc<Block>();
@@ -2027,7 +2058,7 @@ Expression* SExpressionWasmBuilder::makeThrow(Element& s) {
Expression* SExpressionWasmBuilder::makeRethrow(Element& s) {
auto ret = allocator.alloc<Rethrow>();
- ret->exnref = parseExpression(*s[1]);
+ ret->depth = atoi(s[1]->str().c_str());
ret->finalize();
return ret;
}