diff options
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 1bc5ada94..88b967fdf 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -648,6 +648,16 @@ void WasmBinaryWriter::visitBreak(Break *curr) { if (curr->condition) recurse(curr->condition); o << int8_t(curr->condition ? BinaryConsts::BrIf : BinaryConsts::Br) << U32LEB(getBreakIndex(curr->name)); + if (curr->condition && curr->type == unreachable) { + // a br_if is normally none or emits a value. if it is unreachable, + // then either the condition or the value is unreachable, which is + // extremely rare, and may require us to make the stack polymorphic + // (if the block we branch to has a value, we may lack one as we + // are not a taken branch; the wasm spec on the other hand does + // presume the br_if emits a value of the right type, even if it + // popped unreachable) + o << int8_t(BinaryConsts::Unreachable); + } } void WasmBinaryWriter::visitSwitch(Switch *curr) { @@ -669,6 +679,9 @@ void WasmBinaryWriter::visitCall(Call *curr) { recurse(operand); } o << int8_t(BinaryConsts::CallFunction) << U32LEB(getFunctionIndex(curr->target)); + if (curr->type == unreachable) { + o << int8_t(BinaryConsts::Unreachable); + } } void WasmBinaryWriter::visitCallImport(CallImport *curr) { @@ -689,6 +702,9 @@ void WasmBinaryWriter::visitCallIndirect(CallIndirect *curr) { o << int8_t(BinaryConsts::CallIndirect) << U32LEB(getFunctionTypeIndex(curr->fullType)) << U32LEB(0); // Reserved flags field + if (curr->type == unreachable) { + o << int8_t(BinaryConsts::Unreachable); + } } void WasmBinaryWriter::visitGetLocal(GetLocal *curr) { @@ -700,6 +716,9 @@ void WasmBinaryWriter::visitSetLocal(SetLocal *curr) { if (debug) std::cerr << "zz node: Set|TeeLocal" << std::endl; recurse(curr->value); o << int8_t(curr->isTee() ? BinaryConsts::TeeLocal : BinaryConsts::SetLocal) << U32LEB(mappedLocals[curr->index]); + if (curr->type == unreachable) { + o << int8_t(BinaryConsts::Unreachable); + } } void WasmBinaryWriter::visitGetGlobal(GetGlobal *curr) { @@ -986,6 +1005,9 @@ void WasmBinaryWriter::visitUnary(Unary *curr) { case ReinterpretInt64: o << int8_t(BinaryConsts::F64ReinterpretI64); break; default: abort(); } + if (curr->type == unreachable) { + o << int8_t(BinaryConsts::Unreachable); + } } void WasmBinaryWriter::visitBinary(Binary *curr) { @@ -1075,6 +1097,9 @@ void WasmBinaryWriter::visitBinary(Binary *curr) { case GeFloat64: o << int8_t(BinaryConsts::F64Ge); break; default: abort(); } + if (curr->type == unreachable) { + o << int8_t(BinaryConsts::Unreachable); + } } void WasmBinaryWriter::visitSelect(Select *curr) { @@ -1083,6 +1108,9 @@ void WasmBinaryWriter::visitSelect(Select *curr) { recurse(curr->ifFalse); recurse(curr->condition); o << int8_t(BinaryConsts::Select); + if (curr->type == unreachable) { + o << int8_t(BinaryConsts::Unreachable); + } } void WasmBinaryWriter::visitReturn(Return *curr) { @@ -1771,7 +1799,11 @@ Expression* WasmBinaryBuilder::popExpression() { throw ParseException("attempted pop from empty stack"); } auto ret = expressionStack.back(); - expressionStack.pop_back(); + // to simulate the wasm polymorphic stack mode, leave a final + // unreachable, don't empty the stack in that case + if (!(expressionStack.size() == 1 && ret->type == unreachable)) { + expressionStack.pop_back(); + } return ret; } |