summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
authorAlon Zakai (kripken) <alonzakai@gmail.com>2017-07-31 15:11:11 -0700
committerAlon Zakai (kripken) <alonzakai@gmail.com>2017-07-31 15:11:11 -0700
commit5f2dd574d6ed53acc96443b9cf3f7a6d806986c3 (patch)
treedb08a3d19472f9f1650c991ad70a5a6093493192 /src/wasm/wasm-binary.cpp
parentbfdbc0c3f6a835231b218a60ddd6b52f7e9affed (diff)
parent76751bf1f9df4eb2ee6c216744af9ed1e097132e (diff)
downloadbinaryen-5f2dd574d6ed53acc96443b9cf3f7a6d806986c3.tar.gz
binaryen-5f2dd574d6ed53acc96443b9cf3f7a6d806986c3.tar.bz2
binaryen-5f2dd574d6ed53acc96443b9cf3f7a6d806986c3.zip
Merge remote-tracking branch 'origin/master' into fuzz
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r--src/wasm/wasm-binary.cpp34
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;
}