summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
authorAlon Zakai (kripken) <alonzakai@gmail.com>2017-01-01 16:21:19 -0800
committerAlon Zakai (kripken) <alonzakai@gmail.com>2017-01-04 17:33:52 -0800
commit9be46c626ce03d2967c817a3f8f2ffce0bc06a26 (patch)
tree5e398ad8273fbc6aa7983a3db1e170ff20dd0cea /src/wasm/wasm-binary.cpp
parent649bbfc66fff32bf2bb34eec2106e28a4adef585 (diff)
downloadbinaryen-9be46c626ce03d2967c817a3f8f2ffce0bc06a26.tar.gz
binaryen-9be46c626ce03d2967c817a3f8f2ffce0bc06a26.tar.bz2
binaryen-9be46c626ce03d2967c817a3f8f2ffce0bc06a26.zip
handle a binary that breaks to return
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r--src/wasm/wasm-binary.cpp27
1 files changed, 22 insertions, 5 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 26da1487f..65bf0a268 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -879,6 +879,9 @@ void WasmBinaryWriter::visitDrop(Drop *curr) {
o << int8_t(BinaryConsts::Drop);
}
+// reader
+
+static Name RETURN_BREAK("binaryen|break-to-return");
void WasmBinaryBuilder::read() {
@@ -1244,15 +1247,22 @@ void WasmBinaryBuilder::readFunctions() {
// process the function body
if (debug) std::cerr << "processing function: " << i << std::endl;
nextLabel = 0;
+ breaksToReturn = false;
// process body
assert(breakStack.empty());
+ breakStack.emplace_back(RETURN_BREAK, func->result != none); // the break target for the function scope
assert(expressionStack.empty());
assert(depth == 0);
func->body = getMaybeBlock(func->result);
assert(depth == 0);
- assert(breakStack.empty());
+ assert(breakStack.size() == 1);
+ breakStack.pop_back();
assert(expressionStack.empty());
assert(pos == endOfFunction);
+ if (breaksToReturn) {
+ // we broke to return, so we need an outer block to break to
+ func->body = Builder(wasm).blockifyWithName(func->body, RETURN_BREAK);
+ }
}
currFunction = nullptr;
functions.push_back(func);
@@ -1609,10 +1619,17 @@ void WasmBinaryBuilder::visitLoop(Loop *curr) {
}
WasmBinaryBuilder::BreakTarget WasmBinaryBuilder::getBreakTarget(int32_t offset) {
- if (debug) std::cerr << "getBreakTarget "<<offset<<std::endl;
- assert(breakStack.size() - 1 - offset < breakStack.size());
- if (debug) std::cerr <<"breaktarget "<< breakStack[breakStack.size() - 1 - offset].name<< " arity "<<breakStack[breakStack.size() - 1 - offset].arity<< std::endl;
- return breakStack[breakStack.size() - 1 - offset];
+ if (debug) std::cerr << "getBreakTarget " << offset << std::endl;
+ size_t index = breakStack.size() - 1 - offset;
+ assert(index < breakStack.size());
+ if (index == 0) {
+ // trying to access the topmost element means we break out
+ // to the function scope, doing in effect a return, we'll
+ // need to create a block for that.
+ breaksToReturn = true;
+ }
+ if (debug) std::cerr << "breaktarget "<< breakStack[index].name << " arity " << breakStack[index].arity << std::endl;
+ return breakStack[index];
}
void WasmBinaryBuilder::visitBreak(Break *curr, uint8_t code) {