diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-binary.h | 3 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 68 |
2 files changed, 49 insertions, 22 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 1edd3fa12..bc4a225df 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -704,6 +704,7 @@ public: void processExpressions(); Expression* popExpression(); + Expression* popNonVoidExpression(); std::map<Index, Name> mappedGlobals; // index of the Global => name. first imported globals, then internal globals @@ -736,7 +737,7 @@ public: auto num = type->params.size(); call->operands.resize(num); for (size_t i = 0; i < num; i++) { - call->operands[num - i - 1] = popExpression(); + call->operands[num - i - 1] = popNonVoidExpression(); } call->type = type->result; } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index ebbc5a8ee..55f85b4b5 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1319,6 +1319,32 @@ Expression* WasmBinaryBuilder::popExpression() { return ret; } +Expression* WasmBinaryBuilder::popNonVoidExpression() { + auto* ret = popExpression(); + if (ret->type != none) return ret; + // we found a void, so this is stacky code that we must handle carefully + Builder builder(wasm); + // add elements until we find a non-void + std::vector<Expression*> expressions; + expressions.push_back(ret); + while (1) { + auto* curr = popExpression(); + expressions.push_back(curr); + if (curr->type != none) break; + } + auto* block = builder.makeBlock(); + while (!expressions.empty()) { + block->list.push_back(expressions.back()); + expressions.pop_back(); + } + auto type = block->list[0]->type; + auto local = builder.addVar(currFunction, type); + block->list[0] = builder.makeSetLocal(local, block->list[0]); + block->list.push_back(builder.makeGetLocal(local, type)); + block->finalize(); + return block; +} + Name WasmBinaryBuilder::getGlobalName(Index index) { if (!mappedGlobals.size()) { // Create name => index mapping. @@ -1562,7 +1588,7 @@ Expression* WasmBinaryBuilder::getBlock(WasmType type) { void WasmBinaryBuilder::visitIf(If *curr) { if (debug) std::cerr << "zz node: If" << std::endl; curr->type = getWasmType(); - curr->condition = popExpression(); + curr->condition = popNonVoidExpression(); curr->ifTrue = getBlock(curr->type); if (lastSeparator == BinaryConsts::Else) { curr->ifFalse = getBlock(curr->type); @@ -1592,14 +1618,14 @@ void WasmBinaryBuilder::visitBreak(Break *curr, uint8_t code) { if (debug) std::cerr << "zz node: Break, code "<< int32_t(code) << std::endl; BreakTarget target = getBreakTarget(getU32LEB()); curr->name = target.name; - if (code == BinaryConsts::BrIf) curr->condition = popExpression(); - if (target.arity) curr->value = popExpression(); + if (code == BinaryConsts::BrIf) curr->condition = popNonVoidExpression(); + if (target.arity) curr->value = popNonVoidExpression(); curr->finalize(); } void WasmBinaryBuilder::visitSwitch(Switch *curr) { if (debug) std::cerr << "zz node: Switch" << std::endl; - curr->condition = popExpression(); + curr->condition = popNonVoidExpression(); auto numTargets = getU32LEB(); if (debug) std::cerr << "targets: "<< numTargets<<std::endl; @@ -1609,7 +1635,7 @@ void WasmBinaryBuilder::visitSwitch(Switch *curr) { auto defaultTarget = getBreakTarget(getU32LEB()); curr->default_ = defaultTarget.name; if (debug) std::cerr << "default: "<< curr->default_<<std::endl; - if (defaultTarget.arity) curr->value = popExpression(); + if (defaultTarget.arity) curr->value = popNonVoidExpression(); } Expression* WasmBinaryBuilder::visitCall() { @@ -1646,9 +1672,9 @@ void WasmBinaryBuilder::visitCallIndirect(CallIndirect *curr) { curr->fullType = fullType->name; auto num = fullType->params.size(); curr->operands.resize(num); - curr->target = popExpression(); + curr->target = popNonVoidExpression(); for (size_t i = 0; i < num; i++) { - curr->operands[num - i - 1] = popExpression(); + curr->operands[num - i - 1] = popNonVoidExpression(); } curr->type = fullType->result; } @@ -1664,7 +1690,7 @@ void WasmBinaryBuilder::visitSetLocal(SetLocal *curr, uint8_t code) { if (debug) std::cerr << "zz node: Set|TeeLocal" << std::endl; curr->index = getU32LEB(); assert(curr->index < currFunction->getNumLocals()); - curr->value = popExpression(); + curr->value = popNonVoidExpression(); curr->type = curr->value->type; curr->setTee(code == BinaryConsts::TeeLocal); } @@ -1690,7 +1716,7 @@ void WasmBinaryBuilder::visitSetGlobal(SetGlobal *curr) { if (debug) std::cerr << "zz node: SetGlobal" << std::endl; auto index = getU32LEB(); curr->name = getGlobalName(index); - curr->value = popExpression(); + curr->value = popNonVoidExpression(); } void WasmBinaryBuilder::readMemoryAccess(Address& alignment, size_t bytes, Address& offset) { @@ -1719,7 +1745,7 @@ bool WasmBinaryBuilder::maybeVisitLoad(Expression*& out, uint8_t code) { } if (debug) std::cerr << "zz node: Load" << std::endl; readMemoryAccess(curr->align, curr->bytes, curr->offset); - curr->ptr = popExpression(); + curr->ptr = popNonVoidExpression(); out = curr; return true; } @@ -1740,8 +1766,8 @@ bool WasmBinaryBuilder::maybeVisitStore(Expression*& out, uint8_t code) { } if (debug) std::cerr << "zz node: Store" << std::endl; readMemoryAccess(curr->align, curr->bytes, curr->offset); - curr->value = popExpression(); - curr->ptr = popExpression(); + curr->value = popNonVoidExpression(); + curr->ptr = popNonVoidExpression(); curr->finalize(); out = curr; return true; @@ -1821,7 +1847,7 @@ bool WasmBinaryBuilder::maybeVisitUnary(Expression*& out, uint8_t code) { default: return false; } if (debug) std::cerr << "zz node: Unary" << std::endl; - curr->value = popExpression(); + curr->value = popNonVoidExpression(); out = curr; return true; } @@ -1878,8 +1904,8 @@ bool WasmBinaryBuilder::maybeVisitBinary(Expression*& out, uint8_t code) { default: return false; } if (debug) std::cerr << "zz node: Binary" << std::endl; - curr->right = popExpression(); - curr->left = popExpression(); + curr->right = popNonVoidExpression(); + curr->left = popNonVoidExpression(); curr->finalize(); out = curr; return true; @@ -1890,16 +1916,16 @@ bool WasmBinaryBuilder::maybeVisitBinary(Expression*& out, uint8_t code) { void WasmBinaryBuilder::visitSelect(Select *curr) { if (debug) std::cerr << "zz node: Select" << std::endl; - curr->condition = popExpression(); - curr->ifFalse = popExpression(); - curr->ifTrue = popExpression(); + curr->condition = popNonVoidExpression(); + curr->ifFalse = popNonVoidExpression(); + curr->ifTrue = popNonVoidExpression(); curr->finalize(); } void WasmBinaryBuilder::visitReturn(Return *curr) { if (debug) std::cerr << "zz node: Return" << std::endl; if (currFunction->result != none) { - curr->value = popExpression(); + curr->value = popNonVoidExpression(); } } @@ -1916,7 +1942,7 @@ bool WasmBinaryBuilder::maybeVisitHost(Expression*& out, uint8_t code) { curr = allocator.alloc<Host>(); curr->op = GrowMemory; curr->operands.resize(1); - curr->operands[0] = popExpression(); + curr->operands[0] = popNonVoidExpression(); break; } default: return false; @@ -1939,7 +1965,7 @@ void WasmBinaryBuilder::visitUnreachable(Unreachable *curr) { void WasmBinaryBuilder::visitDrop(Drop *curr) { if (debug) std::cerr << "zz node: Drop" << std::endl; - curr->value = popExpression(); + curr->value = popNonVoidExpression(); } } // namespace wasm |