|
19 | 19 | #include "ir/names.h"
|
20 | 20 | #include "lexer.h"
|
21 | 21 | #include "parsers.h"
|
| 22 | +#include "pass.h" |
22 | 23 | #include "wasm-type.h"
|
23 | 24 | #include "wasm.h"
|
24 | 25 |
|
@@ -90,6 +91,58 @@ Result<> parseDefs(Ctx& ctx,
|
90 | 91 | return Ok{};
|
91 | 92 | }
|
92 | 93 |
|
| 94 | +void propagateDebugLocations(Module& wasm) { |
| 95 | + // Copy debug locations from parents or previous siblings to expressions that |
| 96 | + // do not already have their own debug locations. |
| 97 | + struct Propagator : WalkerPass<ExpressionStackWalker<Propagator>> { |
| 98 | + using Super = WalkerPass<ExpressionStackWalker<Propagator>>; |
| 99 | + bool isFunctionParallel() override { return true; } |
| 100 | + bool modifiesBinaryenIR() override { return false; } |
| 101 | + bool requiresNonNullableLocalFixups() override { return false; } |
| 102 | + void runOnFunction(Module* module, Function* func) override { |
| 103 | + if (!func->debugLocations.empty()) { |
| 104 | + Super::runOnFunction(module, func); |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + // Unannotated instructions inherit either their previous sibling's location |
| 109 | + // or their parent's location. Look up whichever is current for a given |
| 110 | + // parent. |
| 111 | + std::unordered_map<Expression*, Function::DebugLocation> parentDefaults; |
| 112 | + |
| 113 | + static void doPreVisit(Propagator* self, Expression** currp) { |
| 114 | + Super::doPreVisit(self, currp); |
| 115 | + auto* curr = *currp; |
| 116 | + auto& locs = self->getFunction()->debugLocations; |
| 117 | + auto& parentDefaults = self->parentDefaults; |
| 118 | + if (auto it = locs.find(curr); it != locs.end()) { |
| 119 | + // Children will inherit this location. |
| 120 | + parentDefaults[curr] = it->second; |
| 121 | + if (auto* parent = self->getParent()) { |
| 122 | + // Subsequent siblings will inherit this location. |
| 123 | + parentDefaults[parent] = it->second; |
| 124 | + } |
| 125 | + } else { |
| 126 | + // No annotation, see if we should inherit one. |
| 127 | + if (auto* parent = self->getParent()) { |
| 128 | + if (auto defaultIt = parentDefaults.find(parent); |
| 129 | + defaultIt != parentDefaults.end()) { |
| 130 | + // We have a default to inherit. Our children will inherit it, too. |
| 131 | + locs[curr] = parentDefaults[curr] = defaultIt->second; |
| 132 | + } |
| 133 | + } |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + std::unique_ptr<Pass> create() override { |
| 138 | + return std::make_unique<Propagator>(); |
| 139 | + } |
| 140 | + }; |
| 141 | + PassRunner runner(&wasm); |
| 142 | + runner.add(std::make_unique<Propagator>()); |
| 143 | + runner.run(); |
| 144 | +} |
| 145 | + |
93 | 146 | // ================
|
94 | 147 | // Parser Functions
|
95 | 148 | // ================
|
@@ -212,6 +265,8 @@ Result<> parseModule(Module& wasm, std::string_view input) {
|
212 | 265 | }
|
213 | 266 | }
|
214 | 267 |
|
| 268 | + propagateDebugLocations(wasm); |
| 269 | + |
215 | 270 | return Ok{};
|
216 | 271 | }
|
217 | 272 |
|
|
0 commit comments