diff options
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 30 |
1 files changed, 24 insertions, 6 deletions
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) { |