diff options
author | Jérôme Vouillon <jerome.vouillon@gmail.com> | 2024-05-02 14:09:15 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-02 11:09:15 -0700 |
commit | d58c54643eb97e5c35f8c14a38f3bf549aee92f4 (patch) | |
tree | a5a2888446708bc6a4da1ef53f13b15bbe2a291d /src | |
parent | 58753f40d9ee51bbe5c3acb7656e0d4ab73d0f36 (diff) | |
download | binaryen-d58c54643eb97e5c35f8c14a38f3bf549aee92f4.tar.gz binaryen-d58c54643eb97e5c35f8c14a38f3bf549aee92f4.tar.bz2 binaryen-d58c54643eb97e5c35f8c14a38f3bf549aee92f4.zip |
Source map fixes (#6550)
* Keep debug locations at function start
The `fn_prolog_epilog.debugInfo` test is failing otherwise, since there
was debug information associated to the nop instruction at the beginning
of the function.
* Do not clear the debug information when reaching the end of the source map
The last segment should extend to the end of the function.
* Propagate debug location from the function prolog to its first instruction
* Fix printing of epilogue location
The text parser no longer propagates locations to the epilogue, so we
should always print the location if there is one.
* Fix debug location smearing
The debug location of the last instruction should not smear into the
function epilogue, and a debug location from a previous function should
not smear into the prologue of the current function.
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/DebugLocationPropagation.cpp | 4 | ||||
-rw-r--r-- | src/passes/Print.cpp | 3 | ||||
-rw-r--r-- | src/wasm-binary.h | 1 | ||||
-rw-r--r-- | src/wasm-stack.h | 5 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 51 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 5 |
6 files changed, 44 insertions, 25 deletions
diff --git a/src/passes/DebugLocationPropagation.cpp b/src/passes/DebugLocationPropagation.cpp index 07ae53faa..e2d1ac50f 100644 --- a/src/passes/DebugLocationPropagation.cpp +++ b/src/passes/DebugLocationPropagation.cpp @@ -64,6 +64,10 @@ struct DebugLocationPropagation if (auto it = locs.find(previous); it != locs.end()) { locs[curr] = it->second; } + } else if (self->getFunction()->prologLocation.size()) { + // Instructions may inherit their locations from the function + // prolog. + locs[curr] = *self->getFunction()->prologLocation.begin(); } } expressionStack.push_back(curr); diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index b30a1180d..1ecf382d9 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3025,8 +3025,7 @@ void PrintSExpression::visitDefinedFunction(Function* curr) { // Print the stack IR. printStackIR(curr->stackIR.get(), *this); } - if (currFunction->epilogLocation.size() && - lastPrintedLocation != *currFunction->epilogLocation.begin()) { + if (currFunction->epilogLocation.size()) { // Print last debug location: mix of decIndent and printDebugLocation // logic. doIndent(o, indent); diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 6fd082f79..6c1230b7b 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1348,6 +1348,7 @@ public: void writeSourceMapProlog(); void writeSourceMapEpilog(); void writeDebugLocation(const Function::DebugLocation& loc); + void writeNoDebugLocation(); void writeDebugLocation(Expression* curr, Function* func); void writeDebugLocationEnd(Expression* curr, Function* func); void writeExtraDebugLocation(Expression* curr, Function* func, size_t id); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 0b72774b6..5858d6f88 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -443,8 +443,13 @@ public: void emitDelegate(Try* curr) { writer.emitDelegate(curr); } void emitScopeEnd(Expression* curr) { writer.emitScopeEnd(curr); } void emitFunctionEnd() { + // Indicate the debug location corresponding to the end opcode + // that terminates the function code. if (func->epilogLocation.size()) { parent.writeDebugLocation(*func->epilogLocation.begin()); + } else { + // The end opcode has no debug location. + parent.writeNoDebugLocation(); } writer.emitFunctionEnd(); } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index d7c052a9f..d4fda5915 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -398,8 +398,10 @@ void WasmBinaryWriter::writeFunctions() { bool DWARF = Debug::hasDWARFSections(*getModule()); ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) { assert(binaryLocationTrackedExpressionsForFunc.empty()); - size_t sourceMapLocationsSizeAtFunctionStart = sourceMapLocations.size(); BYN_TRACE("write one at" << o.size() << std::endl); + // Do not smear any debug location from the previous function. + writeNoDebugLocation(); + size_t sourceMapLocationsSizeAtFunctionStart = sourceMapLocations.size(); size_t sizePos = writeU32LEBPlaceholder(); size_t start = o.size(); BYN_TRACE("writing" << func->name << std::endl); @@ -1373,6 +1375,28 @@ void WasmBinaryWriter::writeDebugLocation(const Function::DebugLocation& loc) { lastDebugLocation = loc; } +void WasmBinaryWriter::writeNoDebugLocation() { + // Emit an indication that there is no debug location there (so that + // we do not get "smeared" with debug info from anything before or + // after us). + // + // We don't need to write repeated "no debug info" indications, as a + // single one is enough to make it clear that the debug information + // before us is valid no longer. We also don't need to write one if + // there is nothing before us. + if (!sourceMapLocations.empty() && + sourceMapLocations.back().second != nullptr) { + sourceMapLocations.emplace_back(o.size(), nullptr); + + // Initialize the state of debug info to indicate there is no current + // debug info relevant. This sets |lastDebugLocation| to a dummy value, + // so that later places with debug info can see that they differ from + // it (without this, if we had some debug info, then a nullptr for none, + // and then the same debug info, we could get confused). + initializeDebugInfo(); + } +} + void WasmBinaryWriter::writeDebugLocation(Expression* curr, Function* func) { if (sourceMap) { auto& debugLocations = func->debugLocations; @@ -1381,25 +1405,8 @@ void WasmBinaryWriter::writeDebugLocation(Expression* curr, Function* func) { // There is debug information here, write it out. writeDebugLocation(iter->second); } else { - // This expression has no debug location. We need to emit an indication - // of that (so that we do not get "smeared" with debug info from anything - // before or after us). - // - // We don't need to write repeated "no debug info" indications, as a - // single one is enough to make it clear that the debug information before - // us is valid no longer. We also don't need to write one if there is - // nothing before us. - if (!sourceMapLocations.empty() && - sourceMapLocations.back().second != nullptr) { - sourceMapLocations.emplace_back(o.size(), nullptr); - - // Initialize the state of debug info to indicate there is no current - // debug info relevant. This sets |lastDebugLocation| to a dummy value, - // so that later places with debug info can see that they differ from - // it (without this, if we had some debug info, then a nullptr for none, - // and then the same debug info, we could get confused). - initializeDebugInfo(); - } + // This expression has no debug location. + writeNoDebugLocation(); } } // If this is an instruction in a function, and if the original wasm had @@ -2687,12 +2694,11 @@ void WasmBinaryReader::readFunctions() { readVars(); - std::swap(func->prologLocation, debugLocation); + func->prologLocation = debugLocation; { // process the function body BYN_TRACE("processing function: " << i << std::endl); nextLabel = 0; - debugLocation.clear(); willBeIgnored = false; // process body assert(breakStack.empty()); @@ -2931,7 +2937,6 @@ void WasmBinaryReader::readNextDebugLocation() { if (nextDebugPos == 0) { // We reached the end of the source map; nothing left to read. - debugLocation.clear(); return; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 99aaf517e..dda47ffa6 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2839,8 +2839,13 @@ void StackIRToBinaryWriter::write() { WASM_UNREACHABLE("unexpected op"); } } + // Indicate the debug location corresponding to the end opcode that + // terminates the function code. if (func->epilogLocation.size()) { parent.writeDebugLocation(*func->epilogLocation.begin()); + } else { + // The end opcode has no debug location. + parent.writeNoDebugLocation(); } writer.emitFunctionEnd(); } |