diff options
author | Thomas Lively <tlively@google.com> | 2022-10-20 11:00:33 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-20 09:00:33 -0700 |
commit | 33dc51d3d7bc49b0633819550d81abe05a434cd9 (patch) | |
tree | e330e3d18caf2fd1b2abf648b2254786b2da2614 /src/wasm/wat-parser.cpp | |
parent | 3b6744c5195584bd18a7a9cec559755dbfbe6968 (diff) | |
download | binaryen-33dc51d3d7bc49b0633819550d81abe05a434cd9.tar.gz binaryen-33dc51d3d7bc49b0633819550d81abe05a434cd9.tar.bz2 binaryen-33dc51d3d7bc49b0633819550d81abe05a434cd9.zip |
[Parser] Parse `memory.size` and `memory.grow` (#5165)
Also add the ability to parse memory indexes to correctly handle the
multi-memory versions of these instructions. Add and use a conversion from
`Result` to `MaybeResult` as well.
Diffstat (limited to 'src/wasm/wat-parser.cpp')
-rw-r--r-- | src/wasm/wat-parser.cpp | 84 |
1 files changed, 76 insertions, 8 deletions
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 9a9acd7a2..8d85e4f45 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -611,6 +611,7 @@ struct NullInstrParserCtx { using LocalT = Ok; using GlobalT = Ok; + using MemoryT = Ok; InstrsT makeInstrs() { return Ok{}; } void appendInstr(InstrsT&, InstrT) {} @@ -622,6 +623,8 @@ struct NullInstrParserCtx { LocalT getLocalFromName(Name) { return Ok{}; } GlobalT getGlobalFromIdx(uint32_t) { return Ok{}; } GlobalT getGlobalFromName(Name) { return Ok{}; } + MemoryT getMemoryFromIdx(uint32_t) { return Ok{}; } + MemoryT getMemoryFromName(Name) { return Ok{}; } InstrT makeUnreachable(Index) { return Ok{}; } InstrT makeNop(Index) { return Ok{}; } @@ -631,18 +634,19 @@ struct NullInstrParserCtx { return Ok{}; } InstrT makeDrop(Index) { return Ok{}; } + InstrT makeMemorySize(Index, MemoryT*) { return Ok{}; } + InstrT makeMemoryGrow(Index, MemoryT*) { return Ok{}; } + InstrT makeLocalGet(Index, LocalT) { return Ok{}; } + InstrT makeLocalTee(Index, LocalT) { return Ok{}; } + InstrT makeLocalSet(Index, LocalT) { return Ok{}; } + InstrT makeGlobalGet(Index, GlobalT) { return Ok{}; } + InstrT makeGlobalSet(Index, GlobalT) { return Ok{}; } InstrT makeI32Const(Index, uint32_t) { return Ok{}; } InstrT makeI64Const(Index, uint64_t) { return Ok{}; } InstrT makeF32Const(Index, float) { return Ok{}; } InstrT makeF64Const(Index, double) { return Ok{}; } - InstrT makeLocalGet(Index, LocalT) { return Ok{}; } - InstrT makeLocalTee(Index, LocalT) { return Ok{}; } - InstrT makeLocalSet(Index, LocalT) { return Ok{}; } - - InstrT makeGlobalGet(Index, GlobalT) { return Ok{}; } - InstrT makeGlobalSet(Index, GlobalT) { return Ok{}; } InstrT makeSIMDExtract(Index, SIMDExtractOp, uint8_t) { return Ok{}; } InstrT makeSIMDReplace(Index, SIMDReplaceOp, uint8_t) { return Ok{}; } InstrT makeSIMDShuffle(Index, const std::array<uint8_t, 16>&) { return Ok{}; } @@ -663,6 +667,7 @@ template<typename Ctx> struct InstrParserCtx : TypeParserCtx<Ctx> { using LocalT = Index; using GlobalT = Name; + using MemoryT = Name; Builder builder; @@ -825,6 +830,18 @@ template<typename Ctx> struct InstrParserCtx : TypeParserCtx<Ctx> { CHECK_ERR(val); return push(pos, builder.makeDrop(*val)); } + Result<> makeMemorySize(Index pos, Name* mem) { + auto m = self().getMemory(pos, mem); + CHECK_ERR(m); + return push(pos, builder.makeMemorySize(*m)); + } + Result<> makeMemoryGrow(Index pos, Name* mem) { + auto m = self().getMemory(pos, mem); + CHECK_ERR(m); + auto val = pop(pos); + CHECK_ERR(val); + return push(pos, builder.makeMemoryGrow(*val, *m)); + } Result<> makeI32Const(Index pos, uint32_t c) { return push(pos, builder.makeConst(Literal(c))); @@ -1306,6 +1323,20 @@ struct ParseDefsCtx : InstrParserCtx<ParseDefsCtx> { return name; } + Result<Name> getMemoryFromIdx(uint32_t idx) { + if (idx >= wasm.memories.size()) { + return in.err("memory index out of bounds"); + } + return wasm.memories[idx]->name; + } + + Result<Name> getMemoryFromName(Name name) { + if (!wasm.getMemoryOrNull(name)) { + return in.err("memory $" + name.toString() + " does not exist"); + } + return name; + } + Result<TypeUseT> makeTypeUse(Index pos, std::optional<HeapTypeT> type, ParamsT* params, @@ -1385,6 +1416,16 @@ struct ParseDefsCtx : InstrParserCtx<ParseDefsCtx> { return Builder::addVar(func, name, type); } + Result<Name> getMemory(Index pos, Name* mem) { + if (mem) { + return *mem; + } + if (wasm.memories.empty()) { + return in.err(pos, "memory required, but there is no memory"); + } + return wasm.memories[0]->name; + } + Result<> makeLocalGet(Index pos, Index local) { if (!func) { return in.err(pos, "local.get must be inside a function"); @@ -1646,6 +1687,8 @@ Result<typename Ctx::InstrT> makeStringSliceIter(Ctx&, Index); // Modules template<typename Ctx> MaybeResult<Index> maybeTypeidx(Ctx& ctx); template<typename Ctx> Result<typename Ctx::HeapTypeT> typeidx(Ctx&); +template<typename Ctx> MaybeResult<typename Ctx::MemoryT> maybeMemidx(Ctx&); +template<typename Ctx> Result<typename Ctx::MemoryT> memidx(Ctx&); template<typename Ctx> Result<typename Ctx::GlobalT> globalidx(Ctx&); template<typename Ctx> Result<typename Ctx::LocalT> localidx(Ctx&); template<typename Ctx> Result<typename Ctx::TypeUseT> typeuse(Ctx&); @@ -2110,12 +2153,16 @@ Result<typename Ctx::InstrT> makeDrop(Ctx& ctx, Index pos) { template<typename Ctx> Result<typename Ctx::InstrT> makeMemorySize(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto mem = maybeMemidx(ctx); + CHECK_ERR(mem); + return ctx.makeMemorySize(pos, mem.getPtr()); } template<typename Ctx> Result<typename Ctx::InstrT> makeMemoryGrow(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto mem = maybeMemidx(ctx); + CHECK_ERR(mem); + return ctx.makeMemoryGrow(pos, mem.getPtr()); } template<typename Ctx> @@ -2636,6 +2683,27 @@ template<typename Ctx> Result<typename Ctx::HeapTypeT> typeidx(Ctx& ctx) { return ctx.in.err("expected type index or identifier"); } +// memidx ::= x:u32 => x +// | v:id => x (if memories[x] = v) +template<typename Ctx> +MaybeResult<typename Ctx::MemoryT> maybeMemidx(Ctx& ctx) { + if (auto x = ctx.in.takeU32()) { + return ctx.getMemoryFromIdx(*x); + } + if (auto id = ctx.in.takeID()) { + return ctx.getMemoryFromName(*id); + } + return {}; +} + +template<typename Ctx> Result<typename Ctx::MemoryT> memidx(Ctx& ctx) { + if (auto idx = maybeMemidx(ctx)) { + CHECK_ERR(idx); + return *idx; + } + return ctx.in.err("expected memory index or identifier"); +} + // globalidx ::= x:u32 => x // | v:id => x (if globals[x] = v) template<typename Ctx> Result<typename Ctx::GlobalT> globalidx(Ctx& ctx) { |