summaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2023-10-02 16:09:05 -0700
committerGitHub <noreply@github.com>2023-10-02 16:09:05 -0700
commit0fe08192d866f72d0f4e680c862bb7af48dec1ac (patch)
treea37b814de2ab85a64612ea112b6303776a44bfa7 /src/parser
parent77f36789aac707d1d5daed20e6e7612c9a9af51b (diff)
downloadbinaryen-0fe08192d866f72d0f4e680c862bb7af48dec1ac.tar.gz
binaryen-0fe08192d866f72d0f4e680c862bb7af48dec1ac.tar.bz2
binaryen-0fe08192d866f72d0f4e680c862bb7af48dec1ac.zip
[Parser] Parse labels and br (#5970)
The parser previously parsed labels and could attach them to control flow structures, but did not maintain the context necessary to correctly parse branches. Support parsing labels as both names and indices in IRBuilder, handling shadowing correctly, and use that support to implement parsing of br.
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/contexts.h16
-rw-r--r--src/parser/parsers.h17
2 files changed, 31 insertions, 2 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h
index 7eedcccc2..862d9772d 100644
--- a/src/parser/contexts.h
+++ b/src/parser/contexts.h
@@ -279,6 +279,7 @@ struct NullInstrParserCtx {
using GlobalIdxT = Ok;
using MemoryIdxT = Ok;
using DataIdxT = Ok;
+ using LabelIdxT = Ok;
using MemargT = Ok;
@@ -298,6 +299,8 @@ struct NullInstrParserCtx {
MemoryIdxT getMemoryFromName(Name) { return Ok{}; }
DataIdxT getDataFromIdx(uint32_t) { return Ok{}; }
DataIdxT getDataFromName(Name) { return Ok{}; }
+ LabelIdxT getLabelFromIdx(uint32_t) { return Ok{}; }
+ LabelIdxT getLabelFromName(Name) { return Ok{}; }
MemargT getMemarg(uint64_t, uint32_t) { return Ok{}; }
@@ -370,7 +373,7 @@ struct NullInstrParserCtx {
Result<> makeMemoryCopy(Index, MemoryIdxT*, MemoryIdxT*) { return Ok{}; }
Result<> makeMemoryFill(Index, MemoryIdxT*) { return Ok{}; }
-
+ Result<> makeBreak(Index, LabelIdxT) { return Ok{}; }
Result<> makeReturn(Index) { return Ok{}; }
template<typename HeapTypeT> Result<> makeRefNull(Index, HeapTypeT) {
return Ok{};
@@ -793,6 +796,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
using FieldIdxT = Index;
using LocalIdxT = Index;
+ using LabelIdxT = Index;
using GlobalIdxT = Name;
using MemoryIdxT = Name;
using DataIdxT = Name;
@@ -936,6 +940,12 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return name;
}
+ Result<Index> getLabelFromIdx(uint32_t idx) { return idx; }
+
+ Result<Index> getLabelFromName(Name name) {
+ return irBuilder.getLabelIndex(name);
+ }
+
Result<TypeUseT> makeTypeUse(Index pos,
std::optional<HeapTypeT> type,
ParamsT* params,
@@ -1203,6 +1213,10 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return withLoc(pos, irBuilder.makeMemoryFill(*m));
}
+ Result<> makeBreak(Index pos, Index label) {
+ return withLoc(pos, irBuilder.makeBreak(label));
+ }
+
Result<> makeReturn(Index pos) {
return withLoc(pos, irBuilder.makeReturn());
}
diff --git a/src/parser/parsers.h b/src/parser/parsers.h
index 38005253f..32f6709df 100644
--- a/src/parser/parsers.h
+++ b/src/parser/parsers.h
@@ -177,6 +177,7 @@ template<typename Ctx> Result<typename Ctx::MemoryIdxT> memidx(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::MemoryIdxT> maybeMemuse(Ctx&);
template<typename Ctx> Result<typename Ctx::GlobalIdxT> globalidx(Ctx&);
template<typename Ctx> Result<typename Ctx::LocalIdxT> localidx(Ctx&);
+template<typename Ctx> Result<typename Ctx::LabelIdxT> labelidx(Ctx&);
template<typename Ctx> Result<typename Ctx::TypeUseT> typeuse(Ctx&);
MaybeResult<ImportNames> inlineImport(ParseInput&);
Result<std::vector<Name>> inlineExports(ParseInput&);
@@ -1195,7 +1196,9 @@ Result<> makeCallIndirect(Ctx& ctx, Index pos, bool isReturn) {
}
template<typename Ctx> Result<> makeBreak(Ctx& ctx, Index pos) {
- return ctx.in.err("unimplemented instruction");
+ auto label = labelidx(ctx);
+ CHECK_ERR(label);
+ return ctx.makeBreak(pos, *label);
}
template<typename Ctx> Result<> makeBreakTable(Ctx& ctx, Index pos) {
@@ -1569,6 +1572,18 @@ template<typename Ctx> Result<typename Ctx::LocalIdxT> localidx(Ctx& ctx) {
return ctx.in.err("expected local index or identifier");
}
+// labelidx ::= x:u32 => x
+// | v:id => x (if labels[x] = v)
+template<typename Ctx> Result<typename Ctx::LabelIdxT> labelidx(Ctx& ctx) {
+ if (auto x = ctx.in.takeU32()) {
+ return ctx.getLabelFromIdx(*x);
+ }
+ if (auto id = ctx.in.takeID()) {
+ return ctx.getLabelFromName(*id);
+ }
+ return ctx.in.err("expected label index or identifier");
+}
+
// typeuse ::= '(' 'type' x:typeidx ')' => x, []
// (if typedefs[x] = [t1*] -> [t2*]
// | '(' 'type' x:typeidx ')' ((t1,IDs):param)* (t2:result)* => x, IDs