diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 119 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 40 |
2 files changed, 97 insertions, 62 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 5f4ace91b..b643eaec8 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -565,14 +565,20 @@ void WasmBinaryWriter::writeUserSection(const UserSection& section) { finishSection(start); } +void WasmBinaryWriter::writeDebugLocation(const Function::DebugLocation& loc) { + if (loc == lastDebugLocation) { + return; + } + auto offset = o.size(); + sourceMapLocations.emplace_back(offset, &loc); + lastDebugLocation = loc; +} + void WasmBinaryWriter::writeDebugLocation(Expression* curr, Function* func) { auto& debugLocations = func->debugLocations; auto iter = debugLocations.find(curr); - if (iter != debugLocations.end() && iter->second != lastDebugLocation) { - auto offset = o.size(); - auto& loc = iter->second; - sourceMapLocations.emplace_back(offset, &loc); - lastDebugLocation = loc; + if (iter != debugLocations.end()) { + writeDebugLocation(iter->second); } } @@ -1058,11 +1064,19 @@ void WasmBinaryBuilder::readFunctions() { throwError("empty function size"); } endOfFunction = pos + size; + + Function *func = new Function; + func->name = Name::fromInt(i); + currFunction = func; + + readNextDebugLocation(); + auto type = functionTypes[i]; if (debug) std::cerr << "reading " << i << std::endl; - std::vector<Type> params, vars; + func->type = type->name; + func->result = type->result; for (size_t j = 0; j < type->params.size(); j++) { - params.emplace_back(type->params[j]); + func->params.emplace_back(type->params[j]); } size_t numLocalTypes = getU32LEB(); for (size_t t = 0; t < numLocalTypes; t++) { @@ -1077,23 +1091,16 @@ void WasmBinaryBuilder::readFunctions() { throwError("too many locals, wasm VMs would not accept this binary"); } while (num > 0) { - vars.emplace_back(type); + func->vars.push_back(type); num--; } } - auto func = Builder(wasm).makeFunction( - Name::fromInt(i), - std::move(params), - type->result, - std::move(vars) - ); - func->type = type->name; - currFunction = func; + std::swap(func->prologLocation, debugLocation); { // process the function body if (debug) std::cerr << "processing function: " << i << std::endl; nextLabel = 0; - useDebugLocation = false; + debugLocation.clear(); willBeIgnored = false; // process body assert(breakTargetNames.size() == 0); @@ -1111,8 +1118,9 @@ void WasmBinaryBuilder::readFunctions() { throwError("binary offset at function exit not at expected location"); } } + std::swap(func->epilogLocation, debugLocation); currFunction = nullptr; - useDebugLocation = false; + debugLocation.clear(); functions.push_back(func); } if (debug) std::cerr << " end function bodies" << std::endl; @@ -1268,26 +1276,38 @@ void WasmBinaryBuilder::readSourceMapHeader() { void WasmBinaryBuilder::readNextDebugLocation() { if (!sourceMap) return; - char ch; - *sourceMap >> ch; - if (ch == '\"') { // end of records - nextDebugLocation.first = 0; - return; - } - if (ch != ',') { - throw MapParseException("Unexpected delimiter"); - } + while (nextDebugLocation.first && nextDebugLocation.first <= pos) { + if (nextDebugLocation.first < pos) { + std::cerr << "skipping debug location info for 0x"; + std::cerr << std::hex << nextDebugLocation.first << std::dec << std::endl; + } + debugLocation.clear(); + // use debugLocation only for function expressions + if (currFunction) { + debugLocation.insert(nextDebugLocation.second); + } - int32_t positionDelta = readBase64VLQ(*sourceMap); - uint32_t position = nextDebugLocation.first + positionDelta; - int32_t fileIndexDelta = readBase64VLQ(*sourceMap); - uint32_t fileIndex = nextDebugLocation.second.fileIndex + fileIndexDelta; - int32_t lineNumberDelta = readBase64VLQ(*sourceMap); - uint32_t lineNumber = nextDebugLocation.second.lineNumber + lineNumberDelta; - int32_t columnNumberDelta = readBase64VLQ(*sourceMap); - uint32_t columnNumber = nextDebugLocation.second.columnNumber + columnNumberDelta; + char ch; + *sourceMap >> ch; + if (ch == '\"') { // end of records + nextDebugLocation.first = 0; + break; + } + if (ch != ',') { + throw MapParseException("Unexpected delimiter"); + } - nextDebugLocation = { position, { fileIndex, lineNumber, columnNumber } }; + int32_t positionDelta = readBase64VLQ(*sourceMap); + uint32_t position = nextDebugLocation.first + positionDelta; + int32_t fileIndexDelta = readBase64VLQ(*sourceMap); + uint32_t fileIndex = nextDebugLocation.second.fileIndex + fileIndexDelta; + int32_t lineNumberDelta = readBase64VLQ(*sourceMap); + uint32_t lineNumber = nextDebugLocation.second.lineNumber + lineNumberDelta; + int32_t columnNumberDelta = readBase64VLQ(*sourceMap); + uint32_t columnNumber = nextDebugLocation.second.columnNumber + columnNumberDelta; + + nextDebugLocation = { position, { fileIndex, lineNumber, columnNumber } }; + } } Expression* WasmBinaryBuilder::readExpression() { @@ -1345,6 +1365,7 @@ void WasmBinaryBuilder::processExpressions() { auto peek = input[pos]; if (peek == BinaryConsts::End || peek == BinaryConsts::Else) { if (debug) std::cerr << "== processExpressions finished with unreachable" << std::endl; + readNextDebugLocation(); lastSeparator = BinaryConsts::ASTNodes(peek); pos++; return; @@ -1654,15 +1675,10 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { throwError("Reached function end without seeing End opcode"); } if (debug) std::cerr << "zz recurse into " << ++depth << " at " << pos << std::endl; - if (nextDebugLocation.first) { - while (nextDebugLocation.first && nextDebugLocation.first <= pos) { - if (nextDebugLocation.first < pos) { - std::cerr << "skipping debug location info for " << nextDebugLocation.first << std::endl; - } - debugLocation = nextDebugLocation.second; - useDebugLocation = currFunction != NULL; // using only for function expressions - readNextDebugLocation(); - } + readNextDebugLocation(); + std::set<Function::DebugLocation> currDebugLocation; + if (debugLocation.size()) { + currDebugLocation.insert(*debugLocation.begin()); } uint8_t code = getInt8(); if (debug) std::cerr << "readExpression seeing " << (int)code << std::endl; @@ -1710,8 +1726,8 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { break; } } - if (useDebugLocation && curr) { - currFunction->debugLocations[curr] = debugLocation; + if (curr && currDebugLocation.size()) { + currFunction->debugLocations[curr] = *currDebugLocation.begin(); } if (debug) std::cerr << "zz recurse from " << depth-- << " at " << pos << std::endl; return BinaryConsts::ASTNodes(code); @@ -1764,13 +1780,18 @@ void WasmBinaryBuilder::visitBlock(Block* curr) { curr->name = getNextLabel(); breakStack.push_back({curr->name, curr->type != none}); stack.push_back(curr); - if (getInt8() == BinaryConsts::Block) { + auto peek = input[pos]; + if (peek == BinaryConsts::Block) { // a recursion + readNextDebugLocation(); curr = allocator.alloc<Block>(); + pos++; + if (debugLocation.size()) { + currFunction->debugLocations[curr] = *debugLocation.begin(); + } continue; } else { // end of recursion - ungetInt8(); break; } } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index a25d3491b..e4c171b5c 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -80,10 +80,10 @@ Element* Element::setString(IString str__, bool dollared__, bool quoted__) { return this; } -Element* Element::setMetadata(size_t line_, size_t col_, SourceLocation* loc_) { +Element* Element::setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_) { line = line_; col = col_; - loc = loc_; + startLoc = startLoc_; return this; } @@ -127,6 +127,7 @@ Element* SExpressionParser::parse() { assert(stack.size() == stackLocs.size()); } else if (input[0] == ')') { input++; + curr->endLoc = loc; auto last = curr; if (stack.empty()) { throw ParseException("s-expr stack empty"); @@ -608,6 +609,12 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { if (currFunction->result != result) throw ParseException("bad func declaration", s.line, s.col); currFunction->body = body; currFunction->type = type; + if (s.startLoc) { + currFunction->prologLocation.insert(getDebugLocation(*s.startLoc)); + } + if (s.endLoc) { + currFunction->epilogLocation.insert(getDebugLocation(*s.endLoc)); + } if (wasm.getFunctionOrNull(currFunction->name)) throw ParseException("duplicate function", s.line, s.col); wasm.addFunction(currFunction.release()); currLocalTypes.clear(); @@ -627,19 +634,23 @@ Type SExpressionWasmBuilder::stringToType(const char* str, bool allowError, bool throw ParseException("invalid wasm type"); } +Function::DebugLocation SExpressionWasmBuilder::getDebugLocation(const SourceLocation& loc) { + IString file = loc.filename; + auto& debugInfoFileNames = wasm.debugInfoFileNames; + auto iter = debugInfoFileIndices.find(file); + if (iter == debugInfoFileIndices.end()) { + Index index = debugInfoFileNames.size(); + debugInfoFileNames.push_back(file.c_str()); + debugInfoFileIndices[file] = index; + } + uint32_t fileIndex = debugInfoFileIndices[file]; + return {fileIndex, loc.line, loc.column}; +} + Expression* SExpressionWasmBuilder::parseExpression(Element& s) { Expression* result = makeExpression(s); - if (s.loc) { - IString file = s.loc->filename; - auto& debugInfoFileNames = wasm.debugInfoFileNames; - auto iter = debugInfoFileIndices.find(file); - if (iter == debugInfoFileIndices.end()) { - Index index = debugInfoFileNames.size(); - debugInfoFileNames.push_back(file.c_str()); - debugInfoFileIndices[file] = index; - } - uint32_t fileIndex = debugInfoFileIndices[file]; - currFunction->debugLocations[result] = {fileIndex, s.loc->line, s.loc->column}; + if (s.startLoc) { + currFunction->debugLocations[result] = getDebugLocation(*s.startLoc); } return result; } @@ -1079,6 +1090,9 @@ Expression* SExpressionWasmBuilder::makeBlock(Element& s) { if (first[0]->str() == BLOCK) { // recurse curr = allocator.alloc<Block>(); + if (first.startLoc) { + currFunction->debugLocations[curr] = getDebugLocation(*first.startLoc); + } sp = &first; continue; } |