diff options
author | Alon Zakai <alonzakai@gmail.com> | 2017-01-10 13:07:37 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-10 13:07:37 -0800 |
commit | 9ccea0e0f97538c8c2349144e83c20bbc6c8c413 (patch) | |
tree | ed533995a225aded7a373edada7d643aa268d07a | |
parent | 90e06072f321507e61120bed891642f191c63547 (diff) | |
parent | 9be46c626ce03d2967c817a3f8f2ffce0bc06a26 (diff) | |
download | binaryen-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.h | 7 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 30 | ||||
-rw-r--r-- | test/break-to-return.wasm | bin | 0 -> 51 bytes | |||
-rw-r--r-- | test/break-to-return.wasm.fromBinary | 16 |
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 Binary files differnew file mode 100644 index 000000000..233b993bb --- /dev/null +++ b/test/break-to-return.wasm 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) + ) + ) + ) + ) +) + |