diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/Print.cpp | 43 | ||||
-rw-r--r-- | src/wasm-binary.h | 6 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 10 | ||||
-rw-r--r-- | src/wasm-stack.h | 6 | ||||
-rw-r--r-- | src/wasm.h | 8 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 119 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 40 |
7 files changed, 154 insertions, 78 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 87fa62b95..77562af4b 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -437,20 +437,29 @@ struct PrintSExpression : public Visitor<PrintSExpression> { if (!full) full = isFullForced(); } - void visit(Expression* curr) { + void printDebugLocation(const Function::DebugLocation &location) { + if (lastPrintedLocation == location) { + return; + } + lastPrintedLocation = location; + auto fileName = currModule->debugInfoFileNames[location.fileIndex]; + o << ";;@ " << fileName << ":" << location.lineNumber << ":" << location.columnNumber << '\n'; + doIndent(o, indent); + } + + void printDebugLocation(Expression* curr) { if (currFunction) { // show an annotation, if there is one auto& debugLocations = currFunction->debugLocations; auto iter = debugLocations.find(curr); if (iter != debugLocations.end()) { - auto fileName = currModule->debugInfoFileNames[iter->second.fileIndex]; - if (lastPrintedLocation != iter->second) { - lastPrintedLocation = iter->second; - o << ";;@ " << fileName << ":" << iter->second.lineNumber << ":" << iter->second.columnNumber << '\n'; - doIndent(o, indent); - } + printDebugLocation(iter->second); } } + } + + void visit(Expression* curr) { + printDebugLocation(curr); Visitor<PrintSExpression>::visit(curr); } @@ -487,7 +496,10 @@ struct PrintSExpression : public Visitor<PrintSExpression> { // special-case Block, because Block nesting (in their first element) can be incredibly deep std::vector<Block*> stack; while (1) { - if (stack.size() > 0) doIndent(o, indent); + if (stack.size() > 0) { + doIndent(o, indent); + printDebugLocation(curr); + } stack.push_back(curr); if (full) { o << "[" << printType(curr->type) << "] "; @@ -849,6 +861,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { void visitFunction(Function* curr) { currFunction = curr; lastPrintedLocation = { 0, 0, 0 }; + if (currFunction->prologLocation.size()) { + printDebugLocation(*currFunction->prologLocation.begin()); + } o << '('; printMajor(o, "func "); printName(curr->name, o); @@ -901,7 +916,17 @@ struct PrintSExpression : public Visitor<PrintSExpression> { // Print the stack IR. WasmPrinter::printStackIR(curr->stackIR.get(), o, curr); } - decIndent(); + if (currFunction->epilogLocation.size() && lastPrintedLocation != *currFunction->epilogLocation.begin()) { + // Print last debug location: mix of decIndent and printDebugLocation logic. + doIndent(o, indent); + if (!minify) { + indent--; + } + printDebugLocation(*currFunction->epilogLocation.begin()); + o << ')'; + } else { + decIndent(); + } } void printTableHeader(Table* curr) { o << '('; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 85e3ae166..05c883acb 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -722,6 +722,7 @@ public: void writeSourceMapProlog(); void writeSourceMapEpilog(); + void writeDebugLocation(const Function::DebugLocation& loc); void writeDebugLocation(Expression* curr, Function* func); // helpers @@ -775,7 +776,7 @@ class WasmBinaryBuilder { size_t pos = 0; Index startIndex = -1; - bool useDebugLocation; + std::set<Function::DebugLocation> debugLocation; std::set<BinaryConsts::Section> seenSections; @@ -787,7 +788,7 @@ public: debug(debug), sourceMap(nullptr), nextDebugLocation(0, { 0, 0, 0 }), - useDebugLocation(false) {} + debugLocation() {} void read(); void readUserSection(size_t payloadLen); @@ -903,7 +904,6 @@ public: void setDebugLocations(std::istream* sourceMap_) { sourceMap = sourceMap_; } - Function::DebugLocation debugLocation; std::unordered_map<std::string, Index> debugInfoFileIndices; void readNextDebugLocation(); void readSourceMapHeader(); diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 02a20b651..d492d0c3c 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -51,7 +51,7 @@ class Element { bool quoted_; public: - Element(MixedArena& allocator) : isList_(true), list_(allocator), line(-1), col(-1), loc(nullptr) {} + Element(MixedArena& allocator) : isList_(true), list_(allocator), line(-1), col(-1), startLoc(nullptr), endLoc(nullptr) {} bool isList() const { return isList_; } bool isStr() const { return !isList_; } @@ -59,7 +59,9 @@ public: bool quoted() const { return isStr() && quoted_; } size_t line, col; - SourceLocation* loc; + // original locations at the start/end of the S-Expression list + SourceLocation* startLoc; + SourceLocation* endLoc; // list methods List& list(); @@ -72,7 +74,7 @@ public: cashew::IString str() const; const char* c_str() const; Element* setString(cashew::IString str__, bool dollared__, bool quoted__); - Element* setMetadata(size_t line_, size_t col_, SourceLocation* loc_); + Element* setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_); // printing friend std::ostream& operator<<(std::ostream& o, Element& e); @@ -218,6 +220,8 @@ private: void parseElem(Element& s); void parseInnerElem(Element& s, Index i = 1, Expression* offset = nullptr); void parseType(Element& s); + + Function::DebugLocation getDebugLocation(const SourceLocation& loc); }; } // namespace wasm diff --git a/src/wasm-stack.h b/src/wasm-stack.h index fffc0ce45..91ea3f3be 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -257,6 +257,9 @@ public: template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::mapLocalsAndEmitHeader() { + if (func->prologLocation.size()) { + parent.writeDebugLocation(*func->prologLocation.begin()); + } // Map them for (Index i = 0; i < func->getNumParams(); i++) { size_t curr = mappedLocals.size(); @@ -1166,6 +1169,9 @@ bool StackWriter<Mode, Parent>::justAddToStack(Expression* curr) { template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::finishFunctionBody() { + if (func->epilogLocation.size()) { + parent.writeDebugLocation(*func->epilogLocation.begin()); + } o << int8_t(BinaryConsts::End); } diff --git a/src/wasm.h b/src/wasm.h index 6d1f67972..09c81e500 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -618,10 +618,16 @@ public: uint32_t fileIndex, lineNumber, columnNumber; bool operator==(const DebugLocation& other) const { return fileIndex == other.fileIndex && lineNumber == other.lineNumber && columnNumber == other.columnNumber; } bool operator!=(const DebugLocation& other) const { return !(*this == other); } + bool operator<(const DebugLocation& other) const { + return fileIndex != other.fileIndex ? fileIndex < other.fileIndex : + lineNumber != other.lineNumber ? lineNumber < other.lineNumber : columnNumber < other.columnNumber; + } }; std::unordered_map<Expression*, DebugLocation> debugLocations; + std::set<DebugLocation> prologLocation; + std::set<DebugLocation> epilogLocation; - Function() : result(none) {} + Function() : result(none), prologLocation(), epilogLocation() {} size_t getNumParams(); size_t getNumVars(); 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; } |