summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-ir-builder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-ir-builder.cpp')
-rw-r--r--src/wasm/wasm-ir-builder.cpp44
1 files changed, 37 insertions, 7 deletions
diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp
index d3f48b1c0..fbb116aa9 100644
--- a/src/wasm/wasm-ir-builder.cpp
+++ b/src/wasm/wasm-ir-builder.cpp
@@ -90,7 +90,8 @@ MaybeResult<IRBuilder::HoistedVal> IRBuilder::hoistLastValue() {
return HoistedVal{Index(index), get};
}
-Result<> IRBuilder::packageHoistedValue(const HoistedVal& hoisted) {
+Result<> IRBuilder::packageHoistedValue(const HoistedVal& hoisted,
+ size_t sizeHint) {
auto& scope = getScope();
assert(!scope.exprStack.empty());
@@ -106,7 +107,7 @@ Result<> IRBuilder::packageHoistedValue(const HoistedVal& hoisted) {
auto type = scope.exprStack.back()->type;
- if (!type.isTuple()) {
+ if (type.size() == sizeHint) {
if (hoisted.get) {
packageAsBlock(type);
}
@@ -158,7 +159,8 @@ void IRBuilder::push(Expression* expr) {
DBG(dump());
}
-Result<Expression*> IRBuilder::pop() {
+Result<Expression*> IRBuilder::pop(size_t size) {
+ assert(size >= 1);
auto& scope = getScope();
// Find the suffix of expressions that do not produce values.
@@ -173,11 +175,25 @@ Result<Expression*> IRBuilder::pop() {
return Err{"popping from empty stack"};
}
- CHECK_ERR(packageHoistedValue(*hoisted));
+ CHECK_ERR(packageHoistedValue(*hoisted, size));
auto* ret = scope.exprStack.back();
- scope.exprStack.pop_back();
- return ret;
+ if (ret->type.size() == size) {
+ scope.exprStack.pop_back();
+ return ret;
+ }
+
+ // The last value-producing expression did not produce exactly the right
+ // number of values, so we need to construct a tuple piecewise instead.
+ assert(size > 1);
+ std::vector<Expression*> elems;
+ elems.resize(size);
+ for (int i = size - 1; i >= 0; --i) {
+ auto elem = pop();
+ CHECK_ERR(elem);
+ elems[i] = *elem;
+ }
+ return builder.makeTupleMake(elems);
}
Result<Expression*> IRBuilder::build() {
@@ -319,6 +335,20 @@ Result<> IRBuilder::visitExpression(Expression* curr) {
return Ok{};
}
+Result<> IRBuilder::visitDrop(Drop* curr, std::optional<uint32_t> arity) {
+ // Multivalue drops must remain multivalue drops.
+ if (!arity) {
+ arity = curr->value->type.size();
+ }
+ if (*arity >= 2) {
+ auto val = pop(*arity);
+ CHECK_ERR(val);
+ curr->value = *val;
+ return Ok{};
+ }
+ return visitExpression(curr);
+}
+
Result<> IRBuilder::visitIf(If* curr) {
// Only the condition is popped from the stack. The ifTrue and ifFalse are
// self-contained so we do not modify them.
@@ -1183,7 +1213,7 @@ Result<> IRBuilder::makeSelect(std::optional<Type> type) {
Result<> IRBuilder::makeDrop() {
Drop curr;
- CHECK_ERR(visitDrop(&curr));
+ CHECK_ERR(visitDrop(&curr, 1));
push(builder.makeDrop(curr.value));
return Ok{};
}