summaryrefslogtreecommitdiff
path: root/src/parser/wat-parser.cpp
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-03-05 12:27:52 -0800
committerGitHub <noreply@github.com>2024-03-05 12:27:52 -0800
commit6896d05ce48b63b34b6c0904eb694618ee7ac619 (patch)
tree1c942b6c2b0d9ccf7327b177b7df964e06488960 /src/parser/wat-parser.cpp
parent00ed4115fb89a0fac3231eba07f5f737cf721acd (diff)
downloadbinaryen-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.cpp55
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{};
}