Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/parser/wat-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "ir/names.h"
#include "lexer.h"
#include "parsers.h"
#include "pass.h"
#include "wasm-type.h"
#include "wasm.h"

Expand Down Expand Up @@ -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
// ================
Expand Down Expand Up @@ -212,6 +265,8 @@ Result<> parseModule(Module& wasm, std::string_view input) {
}
}

propagateDebugLocations(wasm);

return Ok{};
}

Expand Down
26 changes: 26 additions & 0 deletions test/lit/wat-kitchen-sink.wast
Original file line number Diff line number Diff line change
Expand Up @@ -5192,6 +5192,32 @@
end
)

;; CHECK: (func $source-map-propagation (type $void)
;; CHECK-NEXT: ;;@ src.cpp:20:1
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: ;;@ src.cpp:10:1
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: ;;@ src.cpp:10:1
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: ;;@ src.cpp:20:1
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 2)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $source-map-propagation
;;@ src.cpp:10:1
i32.const 0
i32.const 1
i32.add
;;@ src.cpp:20:1
drop
i32.const 2
drop
)

;; 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))
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
Expand Down