diff options
author | Thomas Lively <tlively@google.com> | 2023-11-08 02:04:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-07 17:04:41 -0800 |
commit | 3640f9c992746867c5cf4cead11077e36a51eb7c (patch) | |
tree | 5dd299ab8a2a64f18e0bb6cf651a9c96f1cac1eb /src | |
parent | 0167c65132dd41fde2df6b76149ffc91305abe30 (diff) | |
download | binaryen-3640f9c992746867c5cf4cead11077e36a51eb7c.tar.gz binaryen-3640f9c992746867c5cf4cead11077e36a51eb7c.tar.bz2 binaryen-3640f9c992746867c5cf4cead11077e36a51eb7c.zip |
[Parser] Parse `call` and `return_call` (#6086)
To support parsing calls, add support for parsing function indices and building
calls with IRBuilder.
Diffstat (limited to 'src')
-rw-r--r-- | src/parser/contexts.h | 23 | ||||
-rw-r--r-- | src/parser/parsers.h | 21 | ||||
-rw-r--r-- | src/wasm-ir-builder.h | 4 | ||||
-rw-r--r-- | src/wasm/wasm-ir-builder.cpp | 20 |
4 files changed, 63 insertions, 5 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h index eb47dd502..e360a7175 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -280,6 +280,7 @@ struct NullInstrParserCtx { using ExprT = Ok; using FieldIdxT = Ok; + using FuncIdxT = Ok; using LocalIdxT = Ok; using GlobalIdxT = Ok; using MemoryIdxT = Ok; @@ -296,6 +297,8 @@ struct NullInstrParserCtx { template<typename HeapTypeT> FieldIdxT getFieldFromName(HeapTypeT, Name) { return Ok{}; } + FuncIdxT getFuncFromIdx(uint32_t) { return Ok{}; } + FuncIdxT getFuncFromName(Name) { return Ok{}; } LocalIdxT getLocalFromIdx(uint32_t) { return Ok{}; } LocalIdxT getLocalFromName(Name) { return Ok{}; } GlobalIdxT getGlobalFromIdx(uint32_t) { return Ok{}; } @@ -378,6 +381,7 @@ struct NullInstrParserCtx { Result<> makeMemoryCopy(Index, MemoryIdxT*, MemoryIdxT*) { return Ok{}; } Result<> makeMemoryFill(Index, MemoryIdxT*) { return Ok{}; } + Result<> makeCall(Index, FuncIdxT, bool) { return Ok{}; } Result<> makeBreak(Index, LabelIdxT) { return Ok{}; } Result<> makeReturn(Index) { return Ok{}; } template<typename HeapTypeT> Result<> makeRefNull(Index, HeapTypeT) { @@ -802,6 +806,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> { using ExprT = Expression*; using FieldIdxT = Index; + using FuncIdxT = Name; using LocalIdxT = Index; using LabelIdxT = Index; using GlobalIdxT = Name; @@ -895,6 +900,20 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> { return idx; } + Result<Name> getFuncFromIdx(uint32_t idx) { + if (idx >= wasm.functions.size()) { + return in.err("function index out of bounds"); + } + return wasm.functions[idx]->name; + } + + Result<Name> getFuncFromName(Name name) { + if (!wasm.getFunctionOrNull(name)) { + return in.err("function $" + name.toString() + " does not exist"); + } + return name; + } + Result<Index> getLocalFromName(Name name) { if (!func) { return in.err("cannot access locals outside of a function"); @@ -1220,6 +1239,10 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> { return withLoc(pos, irBuilder.makeMemoryFill(*m)); } + Result<> makeCall(Index pos, Name func, bool isReturn) { + return withLoc(pos, irBuilder.makeCall(func, isReturn)); + } + Result<> makeBreak(Index pos, Index label) { return withLoc(pos, irBuilder.makeBreak(label)); } diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 3a4f9c212..7ac25def4 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -173,6 +173,7 @@ template<typename Ctx> MaybeResult<Index> maybeTypeidx(Ctx& ctx); template<typename Ctx> Result<typename Ctx::HeapTypeT> typeidx(Ctx&); template<typename Ctx> Result<typename Ctx::FieldIdxT> fieldidx(Ctx&, typename Ctx::HeapTypeT); +template<typename Ctx> Result<typename Ctx::FuncIdxT> funcidx(Ctx&); template<typename Ctx> MaybeResult<typename Ctx::MemoryIdxT> maybeMemidx(Ctx&); template<typename Ctx> Result<typename Ctx::MemoryIdxT> memidx(Ctx&); template<typename Ctx> MaybeResult<typename Ctx::MemoryIdxT> maybeMemuse(Ctx&); @@ -1205,7 +1206,9 @@ template<typename Ctx> Result<> makeLoop(Ctx& ctx, Index pos) { } template<typename Ctx> Result<> makeCall(Ctx& ctx, Index pos, bool isReturn) { - return ctx.in.err("unimplemented instruction"); + auto func = funcidx(ctx); + CHECK_ERR(func); + return ctx.makeCall(pos, *func, isReturn); } template<typename Ctx> @@ -1509,8 +1512,8 @@ template<typename Ctx> Result<typename Ctx::HeapTypeT> typeidx(Ctx& ctx) { return ctx.in.err("expected type index or identifier"); } -// fieldidx_t ::= x:u32 => x -// | v:id => x (if t.fields[x] = v) +// fieldidx ::= x:u32 => x +// | v:id => x (if t.fields[x] = v) template<typename Ctx> Result<typename Ctx::FieldIdxT> fieldidx(Ctx& ctx, typename Ctx::HeapTypeT type) { @@ -1523,6 +1526,18 @@ Result<typename Ctx::FieldIdxT> fieldidx(Ctx& ctx, return ctx.in.err("expected field index or identifier"); } +// funcidx ::= x:u32 => x +// | v:id => x (if t.funcs[x] = v) +template<typename Ctx> Result<typename Ctx::FuncIdxT> funcidx(Ctx& ctx) { + if (auto x = ctx.in.takeU32()) { + return ctx.getFuncFromIdx(*x); + } + if (auto id = ctx.in.takeID()) { + return ctx.getFuncFromName(*id); + } + return ctx.in.err("expected function index or identifier"); +} + // memidx ::= x:u32 => x // | v:id => x (if memories[x] = v) template<typename Ctx> diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index c0fce32c7..c249fbf60 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -74,7 +74,8 @@ public: [[nodiscard]] Result<> makeLoop(Name label, Type type); [[nodiscard]] Result<> makeBreak(Index label); // [[nodiscard]] Result<> makeSwitch(); - // [[nodiscard]] Result<> makeCall(); + // Unlike Builder::makeCall, this assumes the function already exists. + [[nodiscard]] Result<> makeCall(Name func, bool isReturn); // [[nodiscard]] Result<> makeCallIndirect(); [[nodiscard]] Result<> makeLocalGet(Index local); [[nodiscard]] Result<> makeLocalSet(Index local); @@ -187,6 +188,7 @@ public: [[nodiscard]] Result<> visitArrayNew(ArrayNew*); [[nodiscard]] Result<> visitBreak(Break*, std::optional<Index> label = std::nullopt); + [[nodiscard]] Result<> visitCall(Call*); private: Module& wasm; diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 4d1c3353d..255683fbc 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -313,6 +313,17 @@ Result<> IRBuilder::visitBreak(Break* curr, std::optional<Index> label) { return Ok{}; } +Result<> IRBuilder::visitCall(Call* curr) { + auto numArgs = wasm.getFunction(curr->target)->getNumParams(); + curr->operands.resize(numArgs); + for (size_t i = 0; i < numArgs; ++i) { + auto arg = pop(); + CHECK_ERR(arg); + curr->operands[numArgs - 1 - i] = *arg; + } + return Ok{}; +} + Result<> IRBuilder::visitFunctionStart(Function* func) { if (!scopeStack.empty()) { return Err{"unexpected start of function"}; @@ -546,7 +557,14 @@ Result<> IRBuilder::makeBreak(Index label) { // Result<> IRBuilder::makeSwitch() {} -// Result<> IRBuilder::makeCall() {} +Result<> IRBuilder::makeCall(Name func, bool isReturn) { + Call curr(wasm.allocator); + curr.target = func; + CHECK_ERR(visitCall(&curr)); + auto type = wasm.getFunction(func)->getResults(); + push(builder.makeCall(curr.target, curr.operands, type, isReturn)); + return Ok{}; +} // Result<> IRBuilder::makeCallIndirect() {} |