Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@ struct NullInstrParserCtx {
Result<> makeTableCopy(Index, TableIdxT*, TableIdxT*) { return Ok{}; }
Result<> makeThrow(Index, TagIdxT) { return Ok{}; }
Result<> makeRethrow(Index, LabelIdxT) { return Ok{}; }
Result<> makeTupleMake(Index, uint32_t) { return Ok{}; }
Result<> makeTupleExtract(Index, uint32_t, uint32_t) { return Ok{}; }
Result<> makeTupleDrop(Index, uint32_t) { return Ok{}; }
template<typename HeapTypeT> Result<> makeCallRef(Index, HeapTypeT, bool) {
return Ok{};
}
Expand Down Expand Up @@ -1624,6 +1627,18 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return withLoc(pos, irBuilder.makeRethrow(label));
}

Result<> makeTupleMake(Index pos, uint32_t arity) {
return withLoc(pos, irBuilder.makeTupleMake(arity));
}

Result<> makeTupleExtract(Index pos, uint32_t arity, uint32_t index) {
return withLoc(pos, irBuilder.makeTupleExtract(arity, index));
}

Result<> makeTupleDrop(Index pos, uint32_t arity) {
return withLoc(pos, irBuilder.makeTupleDrop(arity));
}

Result<> makeCallRef(Index pos, HeapType type, bool isReturn) {
return withLoc(pos, irBuilder.makeCallRef(type, isReturn));
}
Expand Down
29 changes: 26 additions & 3 deletions src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ template<typename Ctx> Result<typename Ctx::LimitsT> limits64(Ctx&);
template<typename Ctx> Result<typename Ctx::MemTypeT> memtype(Ctx&);
template<typename Ctx> Result<typename Ctx::TableTypeT> tabletype(Ctx&);
template<typename Ctx> Result<typename Ctx::GlobalTypeT> globaltype(Ctx&);
template<typename Ctx> Result<uint32_t> tupleArity(Ctx&);

// Instructions
template<typename Ctx> MaybeResult<> foldedBlockinstr(Ctx&);
Expand Down Expand Up @@ -605,6 +606,18 @@ template<typename Ctx> Result<typename Ctx::GlobalTypeT> globaltype(Ctx& ctx) {
return ctx.makeGlobalType(mutability, *type);
}

// arity ::= x:u32 (if x >=2 )
template<typename Ctx> Result<uint32_t> tupleArity(Ctx& ctx) {
auto arity = ctx.in.takeU32();
if (!arity) {
return ctx.in.err("expected tuple arity");
}
if (*arity < 2) {
return ctx.in.err("tuple arity must be at least 2");
}
return *arity;
}

// ============
// Instructions
// ============
Expand Down Expand Up @@ -1512,15 +1525,25 @@ template<typename Ctx> Result<> makeRethrow(Ctx& ctx, Index pos) {
}

template<typename Ctx> Result<> makeTupleMake(Ctx& ctx, Index pos) {
return ctx.in.err("unimplemented instruction");
auto arity = tupleArity(ctx);
CHECK_ERR(arity);
return ctx.makeTupleMake(pos, *arity);
}

template<typename Ctx> Result<> makeTupleExtract(Ctx& ctx, Index pos) {
return ctx.in.err("unimplemented instruction");
auto arity = tupleArity(ctx);
CHECK_ERR(arity);
auto index = ctx.in.takeU32();
if (!index) {
return ctx.in.err("expected tuple index");
}
return ctx.makeTupleExtract(pos, *arity, *index);
}

template<typename Ctx> Result<> makeTupleDrop(Ctx& ctx, Index pos) {
return ctx.in.err("unimplemented instruction");
auto arity = tupleArity(ctx);
CHECK_ERR(arity);
return ctx.makeTupleDrop(pos, *arity);
}

template<typename Ctx>
Expand Down
9 changes: 7 additions & 2 deletions src/wasm-ir-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
[[nodiscard]] Result<> makeTry(Name label, Type type);
[[nodiscard]] Result<> makeThrow(Name tag);
[[nodiscard]] Result<> makeRethrow(Index label);
// [[nodiscard]] Result<> makeTupleMake();
// [[nodiscard]] Result<> makeTupleExtract();
[[nodiscard]] Result<> makeTupleMake(uint32_t arity);
[[nodiscard]] Result<> makeTupleExtract(uint32_t arity, uint32_t index);
[[nodiscard]] Result<> makeTupleDrop(uint32_t arity);
[[nodiscard]] Result<> makeRefI31();
[[nodiscard]] Result<> makeI31Get(bool signed_);
[[nodiscard]] Result<> makeCallRef(HeapType type, bool isReturn);
Expand Down Expand Up @@ -217,6 +218,10 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
[[nodiscard]] Result<> visitThrow(Throw*);
[[nodiscard]] Result<> visitStringNew(StringNew*);
[[nodiscard]] Result<> visitStringEncode(StringEncode*);
[[nodiscard]] Result<> visitTupleMake(TupleMake*);
[[nodiscard]] Result<>
visitTupleExtract(TupleExtract*,
std::optional<uint32_t> arity = std::nullopt);

private:
Module& wasm;
Expand Down
1 change: 1 addition & 0 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,7 @@ class TupleMake : public SpecificExpression<Expression::TupleMakeId> {

class TupleExtract : public SpecificExpression<Expression::TupleExtractId> {
public:
TupleExtract() = default;
TupleExtract(MixedArena& allocator) {}

Expression* tuple;
Expand Down
67 changes: 54 additions & 13 deletions src/wasm/wasm-ir-builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,17 @@ Result<> IRBuilder::packageHoistedValue(const HoistedVal& hoisted,

auto type = scope.exprStack.back()->type;

if (type.size() == sizeHint) {
if (type.size() == sizeHint || type.size() <= 1) {
if (hoisted.get) {
packageAsBlock(type);
}
return Ok{};
}

// We need to break up the hoisted tuple. Create and push a block setting the
// tuple to a local and returning its first element, then push additional gets
// of each of its subsequent elements. Reuse the scratch local we used for
// hoisting, if it exists.
// We need to break up the hoisted tuple. Create and push an expression
// setting the tuple to a local and returning its first element, then push
// additional gets of each of its subsequent elements. Reuse the scratch local
// we used for hoisting, if it exists.
Index scratchIdx;
if (hoisted.get) {
// Update the get on top of the stack to just return the first element.
Expand All @@ -127,12 +127,8 @@ Result<> IRBuilder::packageHoistedValue(const HoistedVal& hoisted,
} else {
auto scratch = addScratchLocal(type);
CHECK_ERR(scratch);
auto* block = builder.makeSequence(
builder.makeLocalSet(*scratch, scope.exprStack.back()),
builder.makeTupleExtract(builder.makeLocalGet(*scratch, type), 0),
type[0]);
scope.exprStack.pop_back();
push(block);
scope.exprStack.back() = builder.makeTupleExtract(
builder.makeLocalTee(*scratch, scope.exprStack.back(), type), 0);
scratchIdx = *scratch;
}
for (Index i = 1, size = type.size(); i < size; ++i) {
Expand Down Expand Up @@ -560,6 +556,33 @@ Result<> IRBuilder::visitStringEncode(StringEncode* curr) {
WASM_UNREACHABLE("unexpected op");
}

Result<> IRBuilder::visitTupleMake(TupleMake* curr) {
assert(curr->operands.size() >= 2);
for (size_t i = 0, size = curr->operands.size(); i < size; ++i) {
auto elem = pop();
CHECK_ERR(elem);
curr->operands[size - 1 - i] = *elem;
}
return Ok{};
}

Result<> IRBuilder::visitTupleExtract(TupleExtract* curr,
std::optional<uint32_t> arity) {
if (!arity) {
if (curr->tuple->type == Type::unreachable) {
// Fallback to an arbitrary valid arity.
arity = 2;
} else {
arity = curr->tuple->type.size();
}
}
assert(*arity >= 2);
auto tuple = pop(*arity);
CHECK_ERR(tuple);
curr->tuple = *tuple;
return Ok{};
}

Result<> IRBuilder::visitFunctionStart(Function* func) {
if (!scopeStack.empty()) {
return Err{"unexpected start of function"};
Expand Down Expand Up @@ -1332,9 +1355,27 @@ Result<> IRBuilder::makeRethrow(Index label) {
return Ok{};
}

// Result<> IRBuilder::makeTupleMake() {}
Result<> IRBuilder::makeTupleMake(uint32_t arity) {
TupleMake curr(wasm.allocator);
curr.operands.resize(arity);
CHECK_ERR(visitTupleMake(&curr));
push(builder.makeTupleMake(curr.operands));
return Ok{};
}

Result<> IRBuilder::makeTupleExtract(uint32_t arity, uint32_t index) {
TupleExtract curr;
CHECK_ERR(visitTupleExtract(&curr, arity));
push(builder.makeTupleExtract(curr.tuple, index));
return Ok{};
}

// Result<> IRBuilder::makeTupleExtract() {}
Result<> IRBuilder::makeTupleDrop(uint32_t arity) {
Drop curr;
CHECK_ERR(visitDrop(&curr, arity));
push(builder.makeDrop(curr.value));
return Ok{};
}

Result<> IRBuilder::makeRefI31() {
RefI31 curr;
Expand Down
14 changes: 4 additions & 10 deletions test/lit/passes/outlining.wast
Original file line number Diff line number Diff line change
Expand Up @@ -645,13 +645,10 @@
;; CHECK-NEXT: (local $scratch_1 (i32 i32))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (local.set $scratch
;; CHECK-NEXT: (tuple.extract 2 0
;; CHECK-NEXT: (local.tee $scratch
;; CHECK-NEXT: (call $outline$)
;; CHECK-NEXT: )
;; CHECK-NEXT: (tuple.extract 2 0
;; CHECK-NEXT: (local.get $scratch)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (tuple.extract 2 1
;; CHECK-NEXT: (local.get $scratch)
Expand All @@ -660,13 +657,10 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.mul
;; CHECK-NEXT: (block (result i32)
;; CHECK-NEXT: (local.set $scratch_1
;; CHECK-NEXT: (tuple.extract 2 0
;; CHECK-NEXT: (local.tee $scratch_1
;; CHECK-NEXT: (call $outline$)
;; CHECK-NEXT: )
;; CHECK-NEXT: (tuple.extract 2 0
;; CHECK-NEXT: (local.get $scratch_1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (tuple.extract 2 1
;; CHECK-NEXT: (local.get $scratch_1)
Expand Down
Loading