summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-01-10 13:07:37 -0800
committerGitHub <noreply@github.com>2017-01-10 13:07:37 -0800
commit9ccea0e0f97538c8c2349144e83c20bbc6c8c413 (patch)
treeed533995a225aded7a373edada7d643aa268d07a
parent90e06072f321507e61120bed891642f191c63547 (diff)
parent9be46c626ce03d2967c817a3f8f2ffce0bc06a26 (diff)
downloadbinaryen-9ccea0e0f97538c8c2349144e83c20bbc6c8c413.tar.gz
binaryen-9ccea0e0f97538c8c2349144e83c20bbc6c8c413.tar.bz2
binaryen-9ccea0e0f97538c8c2349144e83c20bbc6c8c413.zip
Merge pull request #865 from WebAssembly/fix-ab
Fix AngryBots parsing
-rw-r--r--src/wasm-binary.h7
-rw-r--r--src/wasm/wasm-binary.cpp30
-rw-r--r--test/break-to-return.wasmbin0 -> 51 bytes
-rw-r--r--test/break-to-return.wasm.fromBinary16
4 files changed, 46 insertions, 7 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index e681f30e8..75733a6b5 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -696,8 +696,13 @@ public:
Expression* readExpression();
void readGlobals();
- struct BreakTarget { Name name; int arity;};
+ struct BreakTarget {
+ Name name;
+ int arity;
+ BreakTarget(Name name, int arity) : name(name), arity(arity) {}
+ };
std::vector<BreakTarget> breakStack;
+ bool breaksToReturn; // whether a break is done to the function scope, which is in effect a return
std::vector<Expression*> expressionStack;
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index e6b33dbb0..6b5878904 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() {
@@ -906,7 +909,7 @@ void WasmBinaryBuilder::read() {
// imports can read global imports, so we run getGlobalName and create the mapping
// but after we read globals, we need to add the internal globals too, so do that here
mappedGlobals.clear(); // wipe the mapping
- getGlobalName(0); // force rebuild
+ getGlobalName(-1); // force rebuild
break;
}
case BinaryConsts::Section::Data: readDataSegments(); break;
@@ -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);
@@ -1359,6 +1369,7 @@ Name WasmBinaryBuilder::getGlobalName(Index index) {
mappedGlobals[index] = wasm.globals[i]->name;
}
}
+ if (index == Index(-1)) return Name("null"); // just a force-rebuild
assert(mappedGlobals.count(index));
return mappedGlobals[index];
}
@@ -1609,10 +1620,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) {
diff --git a/test/break-to-return.wasm b/test/break-to-return.wasm
new file mode 100644
index 000000000..233b993bb
--- /dev/null
+++ b/test/break-to-return.wasm
Binary files differ
diff --git a/test/break-to-return.wasm.fromBinary b/test/break-to-return.wasm.fromBinary
new file mode 100644
index 000000000..cf5d2461d
--- /dev/null
+++ b/test/break-to-return.wasm.fromBinary
@@ -0,0 +1,16 @@
+(module
+ (type $0 (func (param i32 i32) (result i32)))
+ (memory $0 256 256)
+ (export "add" (func $0))
+ (func $0 (type $0) (param $var$0 i32) (param $var$1 i32) (result i32)
+ (block $binaryen|break-to-return i32
+ (br $binaryen|break-to-return
+ (i32.add
+ (get_local $var$0)
+ (get_local $var$1)
+ )
+ )
+ )
+ )
+)
+