summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser/wat-parser.cpp55
-rw-r--r--test/lit/wat-kitchen-sink.wast26
2 files changed, 81 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{};
}
diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast
index 55bd87f2e..33f570702 100644
--- a/test/lit/wat-kitchen-sink.wast
+++ b/test/lit/wat-kitchen-sink.wast
@@ -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: )