From 6896d05ce48b63b34b6c0904eb694618ee7ac619 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 5 Mar 2024 12:27:52 -0800 Subject: [Parser] Propagate debug locations like the old parser (#6377) Add a pass that propagates debug locations to unannotated child and sibling expressions after parsing. The new parser on its own only attaches debug locations to directly annotated instructions, but this pass, which we run unconditionally, emulates the behavior of the previous parser for compatibility with existing programs. It does unintuitive things to programs using the non-nested format because it runs on nested Binaryen IR, so we may want to rethink this at some point. --- src/parser/wat-parser.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src/parser/wat-parser.cpp') diff --git a/src/parser/wat-parser.cpp b/src/parser/wat-parser.cpp index 8675f4e36..5503a8295 100644 --- a/src/parser/wat-parser.cpp +++ b/src/parser/wat-parser.cpp @@ -19,6 +19,7 @@ #include "ir/names.h" #include "lexer.h" #include "parsers.h" +#include "pass.h" #include "wasm-type.h" #include "wasm.h" @@ -90,6 +91,58 @@ Result<> parseDefs(Ctx& ctx, return Ok{}; } +void propagateDebugLocations(Module& wasm) { + // Copy debug locations from parents or previous siblings to expressions that + // do not already have their own debug locations. + struct Propagator : WalkerPass> { + using Super = WalkerPass>; + bool isFunctionParallel() override { return true; } + bool modifiesBinaryenIR() override { return false; } + bool requiresNonNullableLocalFixups() override { return false; } + void runOnFunction(Module* module, Function* func) override { + if (!func->debugLocations.empty()) { + Super::runOnFunction(module, func); + } + } + + // Unannotated instructions inherit either their previous sibling's location + // or their parent's location. Look up whichever is current for a given + // parent. + std::unordered_map parentDefaults; + + static void doPreVisit(Propagator* self, Expression** currp) { + Super::doPreVisit(self, currp); + auto* curr = *currp; + auto& locs = self->getFunction()->debugLocations; + auto& parentDefaults = self->parentDefaults; + if (auto it = locs.find(curr); it != locs.end()) { + // Children will inherit this location. + parentDefaults[curr] = it->second; + if (auto* parent = self->getParent()) { + // Subsequent siblings will inherit this location. + parentDefaults[parent] = it->second; + } + } else { + // No annotation, see if we should inherit one. + if (auto* parent = self->getParent()) { + if (auto defaultIt = parentDefaults.find(parent); + defaultIt != parentDefaults.end()) { + // We have a default to inherit. Our children will inherit it, too. + locs[curr] = parentDefaults[curr] = defaultIt->second; + } + } + } + } + + std::unique_ptr create() override { + return std::make_unique(); + } + }; + PassRunner runner(&wasm); + runner.add(std::make_unique()); + runner.run(); +} + // ================ // Parser Functions // ================ @@ -212,6 +265,8 @@ Result<> parseModule(Module& wasm, std::string_view input) { } } + propagateDebugLocations(wasm); + return Ok{}; } -- cgit v1.2.3