From b30ab74e349eed23f949ba92842ac474bd991607 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 13 Oct 2022 15:04:22 -0500 Subject: [Parser] Parse `local.get` (#5137) This requires parsing local indices and fixing a bug in `Function::setLocalName` where it only set up the mapping from index to name and not the mapping from name to index. --- src/wasm/wat-parser.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'src/wasm/wat-parser.cpp') diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 0928de094..bba751c71 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -554,12 +554,17 @@ struct NullInstrParserCtx { using InstrsT = Ok; using ExprT = Ok; + using LocalT = Ok; + InstrsT makeInstrs() { return Ok{}; } void appendInstr(InstrsT&, InstrT) {} InstrsT finishInstrs(InstrsT&) { return Ok{}; } ExprT makeExpr(InstrsT) { return Ok{}; } + LocalT getLocalFromIdx(uint32_t idx) { return Ok{}; } + LocalT getLocalFromName(Name name) { return Ok{}; } + InstrT makeUnreachable(Index pos) { return Ok{}; } InstrT makeNop(Index pos) { return Ok{}; } InstrT makeBinary(Index pos, BinaryOp op) { return Ok{}; } @@ -574,6 +579,8 @@ struct NullInstrParserCtx { InstrT makeF32Const(Index, float) { return Ok{}; } InstrT makeF64Const(Index, double) { return Ok{}; } + InstrT makeLocalGet(Index pos, LocalT local) { return Ok{}; } + template InstrT makeRefNull(Index, HeapTypeT) { return {}; } @@ -586,6 +593,8 @@ template struct InstrParserCtx : TypeParserCtx { using InstrsT = std::vector; using ExprT = Expression*; + using LocalT = Index; + Builder builder; // The stack of parsed expressions, used as the children of newly parsed @@ -756,7 +765,7 @@ template struct InstrParserCtx : TypeParserCtx { Result<> makeF64Const(Index pos, double c) { return push(pos, builder.makeConst(Literal(c))); } - Result<> makeRefNull(Index pos, typename TypeParserCtx::HeapTypeT type) { + Result<> makeRefNull(Index pos, HeapType type) { return push(pos, builder.makeRefNull(type)); } }; @@ -1097,7 +1106,6 @@ struct ParseModuleTypesCtx : TypeParserCtx, Builder::addVar(f.get(), l.name, l.type); } } - // TODO: local types and names. return Ok{}; } @@ -1150,6 +1158,17 @@ struct ParseDefsCtx : InstrParserCtx { return types[idx]; } + Index getLocalFromIdx(uint32_t idx) { return idx; } + Result getLocalFromName(Name name) { + if (!func) { + return in.err("cannot access locals outside of a function"); + } + if (!func->hasLocalIndex(name)) { + return in.err("local $" + name.toString() + " does not exist"); + } + return func->getLocalIndex(name); + } + Result makeTypeUse(Index pos, std::optional type, ParamsT* params, @@ -1228,6 +1247,14 @@ struct ParseDefsCtx : InstrParserCtx { Name name = Names::getValidLocalName(*func, "scratch"); return Builder::addVar(func, name, type); } + + Result<> makeLocalGet(Index pos, Index local) { + if (!func) { + return in.err(pos, "local.get must be inside a function"); + } + assert(local < func->getNumLocals()); + return push(pos, builder.makeLocalGet(local, func->getLocalType(local))); + } }; // ================ @@ -1406,6 +1433,7 @@ Result makeStringSliceIter(Ctx&, Index); // Modules template MaybeResult maybeTypeidx(Ctx& ctx); template Result typeidx(Ctx&); +template Result localidx(Ctx&); template Result typeuse(Ctx&); MaybeResult inlineImport(ParseInput&); Result> inlineExports(ParseInput&); @@ -1843,7 +1871,9 @@ Result makeMemoryGrow(Ctx& ctx, Index pos) { template Result makeLocalGet(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto local = localidx(ctx); + CHECK_ERR(local); + return ctx.makeLocalGet(pos, *local); } template @@ -2338,6 +2368,18 @@ template Result typeidx(Ctx& ctx) { return ctx.in.err("expected type index or identifier"); } +// localidx ::= x:u32 => x +// | v:id => x (if types[x] = v) +template Result localidx(Ctx& ctx) { + if (auto x = ctx.in.takeU32()) { + return ctx.getLocalFromIdx(*x); + } + if (auto id = ctx.in.takeID()) { + return ctx.getLocalFromName(*id); + } + return ctx.in.err("expected local index or identifier"); +} + // typeuse ::= '(' 'type' x:typeidx ')' => x, [] // (if typedefs[x] = [t1*] -> [t2*] // | '(' 'type' x:typeidx ')' ((t1,IDs):param)* (t2:result)* => x, IDs @@ -2364,7 +2406,6 @@ template Result typeuse(Ctx& ctx) { auto resultTypes = results(ctx); CHECK_ERR(resultTypes); - // TODO: Use `pos` for error reporting rather than `in`. return ctx.makeTypeUse(pos, type, namedParams.getPtr(), resultTypes.getPtr()); } -- cgit v1.2.3