Skip to content

Commit c37dad5

Browse files
committed
[Parser] Propagate debug locations like the old parser
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.
1 parent 00ed411 commit c37dad5

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/parser/wat-parser.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "ir/names.h"
2020
#include "lexer.h"
2121
#include "parsers.h"
22+
#include "pass.h"
2223
#include "wasm-type.h"
2324
#include "wasm.h"
2425

@@ -90,6 +91,57 @@ Result<> parseDefs(Ctx& ctx,
9091
return Ok{};
9192
}
9293

94+
void propagateDebugLocations(Module& wasm) {
95+
// Copy debug locations from parents to children that do not already have
96+
// 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& locs = self->getFunction()->debugLocations;
116+
auto& parentDefaults = self->parentDefaults;
117+
if (auto it = locs.find(*currp); it != locs.end()) {
118+
// Children will inherit this location.
119+
parentDefaults[*currp] = it->second;
120+
if (auto* parent = self->getParent()) {
121+
// Subsequent siblings will inherit this location.
122+
parentDefaults[parent] = it->second;
123+
}
124+
} else {
125+
// No annotation, see if we should inherit one.
126+
if (auto* parent = self->getParent()) {
127+
if (auto defaultIt = parentDefaults.find(parent);
128+
defaultIt != parentDefaults.end()) {
129+
// We have a default to inherit. Our children will inherit it, too.
130+
locs[*currp] = parentDefaults[*currp] = defaultIt->second;
131+
}
132+
}
133+
}
134+
}
135+
136+
std::unique_ptr<Pass> create() override {
137+
return std::make_unique<Propagator>();
138+
}
139+
};
140+
PassRunner runner(&wasm);
141+
runner.add(std::make_unique<Propagator>());
142+
runner.run();
143+
}
144+
93145
// ================
94146
// Parser Functions
95147
// ================
@@ -212,6 +264,8 @@ Result<> parseModule(Module& wasm, std::string_view input) {
212264
}
213265
}
214266

267+
propagateDebugLocations(wasm);
268+
215269
return Ok{};
216270
}
217271

test/lit/wat-kitchen-sink.wast

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5192,6 +5192,32 @@
51925192
end
51935193
)
51945194

5195+
;; CHECK: (func $source-map-propagation (type $void)
5196+
;; CHECK-NEXT: ;;@ src.cpp:20:1
5197+
;; CHECK-NEXT: (drop
5198+
;; CHECK-NEXT: (i32.add
5199+
;; CHECK-NEXT: ;;@ src.cpp:10:1
5200+
;; CHECK-NEXT: (i32.const 0)
5201+
;; CHECK-NEXT: ;;@ src.cpp:10:1
5202+
;; CHECK-NEXT: (i32.const 1)
5203+
;; CHECK-NEXT: )
5204+
;; CHECK-NEXT: )
5205+
;; CHECK-NEXT: ;;@ src.cpp:20:1
5206+
;; CHECK-NEXT: (drop
5207+
;; CHECK-NEXT: (i32.const 2)
5208+
;; CHECK-NEXT: )
5209+
;; CHECK-NEXT: )
5210+
(func $source-map-propagation
5211+
;;@ src.cpp:10:1
5212+
i32.const 0
5213+
i32.const 1
5214+
i32.add
5215+
;;@ src.cpp:20:1
5216+
drop
5217+
i32.const 2
5218+
drop
5219+
)
5220+
51955221
;; CHECK: (func $use-types (type $104) (param $0 (ref $s0)) (param $1 (ref $s1)) (param $2 (ref $s2)) (param $3 (ref $s3)) (param $4 (ref $s4)) (param $5 (ref $s5)) (param $6 (ref $s6)) (param $7 (ref $s7)) (param $8 (ref $s8)) (param $9 (ref $a0)) (param $10 (ref $a1)) (param $11 (ref $a2)) (param $12 (ref $a3)) (param $13 (ref $subvoid)) (param $14 (ref $submany)) (param $15 (ref $all-types))
51965222
;; CHECK-NEXT: (nop)
51975223
;; CHECK-NEXT: )

0 commit comments

Comments
 (0)