diff options
author | Thomas Lively <tlively@google.com> | 2024-03-05 12:27:52 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-05 12:27:52 -0800 |
commit | 6896d05ce48b63b34b6c0904eb694618ee7ac619 (patch) | |
tree | 1c942b6c2b0d9ccf7327b177b7df964e06488960 /src/parser/wat-parser.cpp | |
parent | 00ed4115fb89a0fac3231eba07f5f737cf721acd (diff) | |
download | binaryen-6896d05ce48b63b34b6c0904eb694618ee7ac619.tar.gz binaryen-6896d05ce48b63b34b6c0904eb694618ee7ac619.tar.bz2 binaryen-6896d05ce48b63b34b6c0904eb694618ee7ac619.zip |
[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.
Diffstat (limited to 'src/parser/wat-parser.cpp')
-rw-r--r-- | src/parser/wat-parser.cpp | 55 |
1 files changed, 55 insertions, 0 deletions
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<ExpressionStackWalker<Propagator>> { + using Super = WalkerPass<ExpressionStackWalker<Propagator>>; + 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<Expression*, Function::DebugLocation> 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<Pass> create() override { + return std::make_unique<Propagator>(); + } + }; + PassRunner runner(&wasm); + runner.add(std::make_unique<Propagator>()); + runner.run(); +} + // ================ // Parser Functions // ================ @@ -212,6 +265,8 @@ Result<> parseModule(Module& wasm, std::string_view input) { } } + propagateDebugLocations(wasm); + return Ok{}; } |