Skip to content

Commit

Permalink
[Parser] Parse call and return_call (#6086)
Browse files Browse the repository at this point in the history
To support parsing calls, add support for parsing function indices and building
calls with IRBuilder.
  • Loading branch information
tlively authored Nov 8, 2023
1 parent 0167c65 commit 3640f9c
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 71 deletions.
23 changes: 23 additions & 0 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ struct NullInstrParserCtx {
using ExprT = Ok;

using FieldIdxT = Ok;
using FuncIdxT = Ok;
using LocalIdxT = Ok;
using GlobalIdxT = Ok;
using MemoryIdxT = Ok;
Expand All @@ -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{}; }
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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));
}
Expand Down
21 changes: 18 additions & 3 deletions src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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&);
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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) {
Expand All @@ -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>
Expand Down
4 changes: 3 additions & 1 deletion src/wasm-ir-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
[[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);
Expand Down Expand Up @@ -187,6 +188,7 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
[[nodiscard]] Result<> visitArrayNew(ArrayNew*);
[[nodiscard]] Result<> visitBreak(Break*,
std::optional<Index> label = std::nullopt);
[[nodiscard]] Result<> visitCall(Call*);

private:
Module& wasm;
Expand Down
20 changes: 19 additions & 1 deletion src/wasm/wasm-ir-builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"};
Expand Down Expand Up @@ -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() {}

Expand Down
Loading

0 comments on commit 3640f9c

Please sign in to comment.