summaryrefslogtreecommitdiff
path: root/src/parser/parsers.h
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-01-25 12:32:34 -0800
committerGitHub <noreply@github.com>2024-01-25 12:32:34 -0800
commitc0e688ed0963605e062dfb00d681602bd8dc96d2 (patch)
tree84f6717df74db8dec8671947b64e060566e01df5 /src/parser/parsers.h
parent6453fd55a312779c2f0d9451d325646522a85470 (diff)
downloadbinaryen-c0e688ed0963605e062dfb00d681602bd8dc96d2.tar.gz
binaryen-c0e688ed0963605e062dfb00d681602bd8dc96d2.tar.bz2
binaryen-c0e688ed0963605e062dfb00d681602bd8dc96d2.zip
[Parser] Parse try_table (#6237)
Diffstat (limited to 'src/parser/parsers.h')
-rw-r--r--src/parser/parsers.h87
1 files changed, 84 insertions, 3 deletions
diff --git a/src/parser/parsers.h b/src/parser/parsers.h
index 10894a7cf..73a7d0035 100644
--- a/src/parser/parsers.h
+++ b/src/parser/parsers.h
@@ -60,6 +60,8 @@ template<typename Ctx> MaybeResult<> block(Ctx&, bool);
template<typename Ctx> MaybeResult<> ifelse(Ctx&, bool);
template<typename Ctx> MaybeResult<> loop(Ctx&, bool);
template<typename Ctx> MaybeResult<> trycatch(Ctx&, bool);
+template<typename Ctx> MaybeResult<typename Ctx::CatchT> catchinstr(Ctx&);
+template<typename Ctx> MaybeResult<> trytable(Ctx&, bool);
template<typename Ctx> Result<> makeUnreachable(Ctx&, Index);
template<typename Ctx> Result<> makeNop(Ctx&, Index);
template<typename Ctx> Result<> makeBinary(Ctx&, Index, BinaryOp op);
@@ -657,7 +659,7 @@ template<typename Ctx> Result<uint32_t> tupleArity(Ctx& ctx) {
// Instructions
// ============
-// blockinstr ::= block | loop | if-else | try-catch
+// blockinstr ::= block | loop | if-else | try-catch | try_table
template<typename Ctx> MaybeResult<> foldedBlockinstr(Ctx& ctx) {
if (auto i = block(ctx, true)) {
return i;
@@ -671,7 +673,9 @@ template<typename Ctx> MaybeResult<> foldedBlockinstr(Ctx& ctx) {
if (auto i = trycatch(ctx, true)) {
return i;
}
- // TODO: Other block instructions
+ if (auto i = trytable(ctx, true)) {
+ return i;
+ }
return {};
}
@@ -688,7 +692,9 @@ template<typename Ctx> MaybeResult<> unfoldedBlockinstr(Ctx& ctx) {
if (auto i = trycatch(ctx, false)) {
return i;
}
- // TODO: Other block instructions
+ if (auto i = trytable(ctx, false)) {
+ return i;
+ }
return {};
}
@@ -1159,6 +1165,81 @@ template<typename Ctx> MaybeResult<> trycatch(Ctx& ctx, bool folded) {
return ctx.visitEnd();
}
+template<typename Ctx> MaybeResult<typename Ctx::CatchT> catchinstr(Ctx& ctx) {
+ typename Ctx::CatchT result;
+ if (ctx.in.takeSExprStart("catch"sv)) {
+ auto tag = tagidx(ctx);
+ CHECK_ERR(tag);
+ auto label = labelidx(ctx);
+ CHECK_ERR(label);
+ result = ctx.makeCatch(*tag, *label);
+ } else if (ctx.in.takeSExprStart("catch_ref"sv)) {
+ auto tag = tagidx(ctx);
+ CHECK_ERR(tag);
+ auto label = labelidx(ctx);
+ CHECK_ERR(label);
+ result = ctx.makeCatchRef(*tag, *label);
+ } else if (ctx.in.takeSExprStart("catch_all"sv)) {
+ auto label = labelidx(ctx);
+ CHECK_ERR(label);
+ result = ctx.makeCatchAll(*label);
+ } else if (ctx.in.takeSExprStart("catch_all_ref"sv)) {
+ auto label = labelidx(ctx);
+ CHECK_ERR(label);
+ result = ctx.makeCatchAllRef(*label);
+ } else {
+ return {};
+ }
+
+ if (!ctx.in.takeRParen()) {
+ return ctx.in.err("expected ')' at end of catch clause");
+ }
+
+ return result;
+}
+
+// trytable ::= 'try_table' label blocktype catchinstr* instr* end id?
+// | '(' 'try_table' label blocktype catchinstr* instr* ')'
+template<typename Ctx> MaybeResult<> trytable(Ctx& ctx, bool folded) {
+ auto pos = ctx.in.getPos();
+
+ if ((folded && !ctx.in.takeSExprStart("try_table"sv)) ||
+ (!folded && !ctx.in.takeKeyword("try_table"sv))) {
+ return {};
+ }
+
+ auto label = ctx.in.takeID();
+
+ auto type = blocktype(ctx);
+ CHECK_ERR(type);
+
+ auto catches = ctx.makeCatchList();
+ while (auto c = catchinstr(ctx)) {
+ CHECK_ERR(c);
+ ctx.appendCatch(catches, *c);
+ }
+
+ CHECK_ERR(ctx.makeTryTable(pos, label, *type, catches));
+
+ CHECK_ERR(instrs(ctx));
+
+ if (folded) {
+ if (!ctx.in.takeRParen()) {
+ return ctx.in.err("expected ')' at end of try_table");
+ }
+ } else {
+ if (!ctx.in.takeKeyword("end"sv)) {
+ return ctx.in.err("expected 'end' at end of try_table");
+ }
+
+ auto id = ctx.in.takeID();
+ if (id && id != label) {
+ return ctx.in.err("end label does not match try_table label");
+ }
+ }
+ return ctx.visitEnd();
+}
+
template<typename Ctx> Result<> makeUnreachable(Ctx& ctx, Index pos) {
return ctx.makeUnreachable(pos);
}