From 7b7832d65ce28702bbac1b44b6de854029c1e0b1 Mon Sep 17 00:00:00 2001 From: 许鑫权 Date: Mon, 22 Apr 2024 05:14:13 +0800 Subject: DebugLocationPropagation: pass debuglocation from parent node to chil… (#6500) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR creates a pass to propagate debug location from parent node to child nodes which has no debug location with pre-order traversal. This is useful for compilers that use Binaryen API to generate WebAssembly modules. It behaves like `wasm-opt` read text format file: children are tagged with the debug info of the parent, if they have no annotation of their own. For compilers that use Binaryen API to generate WebAssembly modules, it is a bit redundant to add debugInfo for each expression, Especially when the compiler wrap expressions. With this pass, compilers just need to add debugInfo for the parent node, which is more convenient. For example: ``` (drop (call $voidFunc) ) ``` Without this pass, if the compiler only adds debugInfo for the wrapped expression `drop`, the `call` expression has no corresponding source code mapping in DevTools debugging, which is obviously not user-friendly. --- src/parser/wat-parser.cpp | 46 +--------------------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) (limited to 'src/parser/wat-parser.cpp') diff --git a/src/parser/wat-parser.cpp b/src/parser/wat-parser.cpp index 5503a8295..7f6dd2975 100644 --- a/src/parser/wat-parser.cpp +++ b/src/parser/wat-parser.cpp @@ -94,52 +94,8 @@ Result<> parseDefs(Ctx& ctx, 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.add("propagate-debug-locs"); runner.run(); } -- cgit v1.2.3