From 79e032ac1124f82729bb21684f370044612c7124 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 25 Oct 2022 09:09:26 -0500 Subject: [Parser] Parse `return` (#5181) Unlike in the legacy parser, we cannot depend on the folded text format to determine how many values to return, so we determine that solely based on the current function context. To handle multivalue return correctly, fix a bug in which we could synthesize new `unreachable`s and place them before existing unreachable instructions (like returns) at the end of instruction sequences. --- src/wasm/wat-parser.cpp | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'src/wasm/wat-parser.cpp') diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 82f8368af..abcff8c43 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -725,6 +725,7 @@ struct NullInstrParserCtx { InstrT makeMemoryCopy(Index, MemoryT*, MemoryT*) { return Ok{}; } InstrT makeMemoryFill(Index, MemoryT*) { return Ok{}; } + InstrT makeReturn(Index) { return Ok{}; } template InstrT makeRefNull(Index, HeapTypeT) { return {}; } @@ -1253,12 +1254,23 @@ struct ParseDefsCtx : TypeParserCtx { // instructions and reset the context for the next sequence. if (type.isTuple()) { std::vector elems(type.size()); + bool hadUnreachableElem = false; for (size_t i = 0; i < elems.size(); ++i) { auto elem = pop(self().in.getPos()); CHECK_ERR(elem); elems[elems.size() - 1 - i] = *elem; + if ((*elem)->type == Type::unreachable) { + // We don't want to pop back past an unreachable here. Push the + // unreachable back and throw away any post-unreachable values we have + // popped. + exprStack.push_back(*elem); + hadUnreachableElem = true; + break; + } + } + if (!hadUnreachableElem) { + exprStack.push_back(builder.makeTupleMake(std::move(elems))); } - exprStack.push_back(builder.makeTupleMake(std::move(elems))); } else if (type != Type::none) { // Ensure the last expression produces the value. auto expr = pop(self().in.getPos()); @@ -1727,6 +1739,28 @@ struct ParseDefsCtx : TypeParserCtx { return push(pos, builder.makeMemoryFill(*dest, *val, *size, *m)); } + Result<> makeReturn(Index pos) { + if (!func) { + return in.err("cannot return outside of a function"); + } + size_t n = func->getResults().size(); + if (n == 0) { + return push(pos, builder.makeReturn()); + } + if (n == 1) { + auto val = pop(pos); + CHECK_ERR(val); + return push(pos, builder.makeReturn(*val)); + } + std::vector vals(n); + for (size_t i = 0; i < n; ++i) { + auto val = pop(pos); + CHECK_ERR(val); + vals[n - i - 1] = *val; + } + return push(pos, builder.makeReturn(builder.makeTupleMake(vals))); + } + Result<> makeRefNull(Index pos, HeapType type) { return push(pos, builder.makeRefNull(type)); } @@ -2709,7 +2743,7 @@ Result makeBreakTable(Ctx& ctx, Index pos) { template Result makeReturn(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + return ctx.makeReturn(pos); } template -- cgit v1.2.3