[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-03 Thread Jeremy Morse via llvm-branch-commits


@@ -59,6 +65,52 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.

jmorse wrote:

I feel the term "instance of LLVM" could be more precise: can we us the word 
"process" here? All other ambiguities and difficulties of fixed addresses are 
brought to mind with the word process.

https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-03 Thread Jeremy Morse via llvm-branch-commits


@@ -59,6 +65,52 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static SymbolizedAddressMap SymbolizedAddrs;
+static AddressSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+unsigned VirtualFrameNo = 0;
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
+OS << right_justify(formatv("#{0}", VirtualFrameNo++).str(), 
std::log10(Depth) + 2)
+  << ' ' << SymbolizedFrame << '\n';
+  }
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();

jmorse wrote:

Major nit; would we be able to name the type here rather than `auto`? It'll 
make the resulting code a lot easier to localise and dissect for future 
readers. (The next `auto` makes sense of course).

https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-03 Thread Jeremy Morse via llvm-branch-commits

https://github.com/jmorse commented:

Tentative LGTM, noting that you're planning on updating docs in this PR too. 
I've no familiarity with the python modified alas.

https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-03 Thread Jeremy Morse via llvm-branch-commits

https://github.com/jmorse edited 
https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-02 Thread Stephen Tozer via llvm-branch-commits

SLTozer wrote:

> Are you planning to extend documentation

Yes, and it probably is best if the documentation lands in this patch!

https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-02 Thread Djordje Todorovic via llvm-branch-commits

https://github.com/djtodoro edited 
https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-02 Thread Djordje Todorovic via llvm-branch-commits


@@ -59,6 +65,52 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static SymbolizedAddressMap SymbolizedAddrs;
+static AddressSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+unsigned VirtualFrameNo = 0;
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
+OS << right_justify(formatv("#{0}", VirtualFrameNo++).str(), 
std::log10(Depth) + 2)

djtodoro wrote:

Please run `clang-format`.

https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-02 Thread Djordje Todorovic via llvm-branch-commits

https://github.com/djtodoro commented:

@SLTozer thanks for doing this!

Are you planning to extend documentation, e.g. 
https://llvm.org/docs/HowToUpdateDebugInfo.html#how-to-automatically-convert-tests-into-debug-info-tests?


https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-02 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer edited 
https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-02 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer edited 
https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-01 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From e2ff01bc95a78c4372bdf538f0433dc882c070f8 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 83 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 +++---
 2 files changed, 88 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 5f70bc442d2f0..e8ed55a99546e 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,52 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap> SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+unsigned VirtualFrameNo = 0;
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
+OS << right_justify(formatv("#{0}", VirtualFrameNo++).str(), 
std::log10(Depth) + 2)
+  << ' ' << SymbolizedFrame << '\n';
+  }
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -375,6 +429,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -450,14 +506,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << N

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-07-01 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From e2ff01bc95a78c4372bdf538f0433dc882c070f8 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 83 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 +++---
 2 files changed, 88 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 5f70bc442d2f0..e8ed55a99546e 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,52 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap> SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+unsigned VirtualFrameNo = 0;
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
+OS << right_justify(formatv("#{0}", VirtualFrameNo++).str(), 
std::log10(Depth) + 2)
+  << ' ' << SymbolizedFrame << '\n';
+  }
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -375,6 +429,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -450,14 +506,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << N

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-20 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From afeb26be5f099d384115a55b19707bbb2a730245 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 83 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 +++---
 2 files changed, 88 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index c2dbdc57eb3b5..460b5e50e42d7 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,52 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap> SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+unsigned VirtualFrameNo = 0;
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
+OS << right_justify(formatv("#{0}", VirtualFrameNo++).str(), 
std::log10(Depth) + 2)
+  << ' ' << SymbolizedFrame << '\n';
+  }
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -373,6 +427,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -448,14 +504,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << N

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-20 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From afeb26be5f099d384115a55b19707bbb2a730245 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 83 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 +++---
 2 files changed, 88 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index c2dbdc57eb3b5..460b5e50e42d7 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,52 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap> SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+unsigned VirtualFrameNo = 0;
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
+OS << right_justify(formatv("#{0}", VirtualFrameNo++).str(), 
std::log10(Depth) + 2)
+  << ' ' << SymbolizedFrame << '\n';
+  }
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -373,6 +427,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -448,14 +504,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << N

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-12 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From ef6ccda96703764bbed694f910d56d8a3af27730 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 80 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 ---
 2 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 729813a92f516..01ed9de51c0b2 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,49 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2)
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -454,14 +507,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << NameOfWrappedPass
   << " did not generate DILocation for " << *Instr
@@ -474,11 +536,7 @@ static bool checkInstructi

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-12 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From ef6ccda96703764bbed694f910d56d8a3af27730 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 80 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 ---
 2 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 729813a92f516..01ed9de51c0b2 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,49 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2)
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -454,14 +507,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << NameOfWrappedPass
   << " did not generate DILocation for " << *Instr
@@ -474,11 +536,7 @@ static bool checkInstructi

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-11 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From e46273bec027d0accfbe6d3de9880c29977c6858 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 80 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 ---
 2 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 729813a92f516..01ed9de51c0b2 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,49 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2)
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -454,14 +507,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << NameOfWrappedPass
   << " did not generate DILocation for " << *Instr
@@ -474,11 +536,7 @@ static bool checkInstructi

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-11 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From e46273bec027d0accfbe6d3de9880c29977c6858 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 80 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 ---
 2 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 729813a92f516..01ed9de51c0b2 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,49 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2)
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -454,14 +507,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << NameOfWrappedPass
   << " did not generate DILocation for " << *Instr
@@ -474,11 +536,7 @@ static bool checkInstructi

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-11 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From 4bbd28b23847c069445d9babe9aa8a8aac5036c1 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 80 ++---
 llvm/utils/llvm-original-di-preservation.py | 24 ---
 2 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 729813a92f516..01ed9de51c0b2 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,49 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2)
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -454,14 +507,23 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+  {"metadata", "DILocation"},
+  {"fn-name", FnName.str()},
+  {"bb-name", BBName.str()},
+  {"instr", InstName},
+  {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+  {"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << NameOfWrappedPass
   << " did not generate DILocation for " << *Instr
@@ -474,11 +536,7 @@ static bool checkInstructi

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-11 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer ready_for_review 
https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-11 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer edited 
https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-11 Thread via llvm-branch-commits

github-actions[bot] wrote:




:warning: undef deprecator found issues in your code. :warning:



You can test this locally with the following command:


``bash
git diff -U0 --pickaxe-regex -S 
'([^a-zA-Z0-9#_-]undef[^a-zA-Z0-9_-]|UndefValue::get)' 'HEAD~1' HEAD 
clang/test/CIR/CodeGen/ctor.cpp clang/test/CodeGen/X86/cygwin-varargs.c 
clang/test/OpenMP/for_private_reduction_codegen.cpp 
flang-rt/include/flang-rt/runtime/work-queue.h 
flang-rt/lib/runtime/work-queue.cpp 
libcxx/test/std/time/time.point/time.point.arithmetic/op_++.pass.cpp 
libcxx/test/std/time/time.point/time.point.arithmetic/op_++int.pass.cpp 
libcxx/test/std/time/time.point/time.point.arithmetic/op_--.pass.cpp 
libcxx/test/std/time/time.point/time.point.arithmetic/op_--int.pass.cpp 
llvm/test/CodeGen/AMDGPU/move-to-valu-pseudo-scalar-trans-f16-fake16.ll 
llvm/test/CodeGen/AMDGPU/move-to-valu-pseudo-scalar-trans-f16-true16.ll 
llvm/test/CodeGen/RISCV/select-cond.ll llvm/test/CodeGen/X86/bsf.ll 
llvm/test/CodeGen/X86/bsr.ll llvm/test/Transforms/IndVarSimplify/iv-cmp-sext.ll 
llvm/test/Transforms/LoopUnroll/peel-last-iteration-minmax.ll 
llvm/test/Transforms/LowerMatrixIntrinsics/unary.ll 
openmp/runtime/test/worksharing/for/omp_for_private_reduction.cpp 
bolt/include/bolt/Core/BinaryFunction.h bolt/include/bolt/Profile/DataReader.h 
bolt/include/bolt/Profile/ProfileYAMLMapping.h bolt/lib/Core/BinaryFunction.cpp 
bolt/lib/Passes/ProfileQualityStats.cpp bolt/lib/Profile/DataAggregator.cpp 
bolt/lib/Profile/DataReader.cpp bolt/lib/Profile/YAMLProfileReader.cpp 
bolt/lib/Profile/YAMLProfileWriter.cpp 
clang-tools-extra/clang-tidy/abseil/AbseilTidyModule.cpp 
clang-tools-extra/clang-tidy/abseil/CleanupCtadCheck.cpp 
clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp 
clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp 
clang-tools-extra/clang-tidy/altera/AlteraTidyModule.cpp 
clang-tools-extra/clang-tidy/android/AndroidTidyModule.cpp 
clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp 
clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/MultipleNewInOneExpressionCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/StringviewNullptrCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp 
clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp 
clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp 
clang-tools-extra/clang-tidy/concurrency/ConcurrencyTidyModule.cpp 
clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp 
clang-tools-extra/clang-tidy/cppcoreguidelines/VirtualClassDestructorCheck.cpp 
clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp 
clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp 
clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp 
clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp 
clang-tools-extra/clang-tidy/linuxkernel/LinuxKernelTidyModule.cpp 
clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp 
clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp 
clang-tools-extra/clang-tidy/llvmlibc/CalleeNamespaceCheck.cpp 
clang-tools-extra/clang-tidy/llvmlibc/LLVMLibcTidyModule.cpp 
clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp 
clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp 
clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp 
clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp 
clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp 
clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp 
clang-tools-extra/clang-tidy/modernize/UseStartsEndsWithCheck.cpp 
clang-tools-extra/clang-tidy/mpi/MPITidyModule.cpp 
clang-tools-extra/clang-tidy/objc/NSDateFormatterCheck.cpp 
clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp 
clang-tools-extra/clang-tidy/openmp/OpenMPTidyModule.cpp 
clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp 
clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp 
clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp 
clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp 
clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.cpp 
clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp 
clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp 
clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp 
clang-tools-extra/clang-tidy/readability/RedundantInlineSpecifierC

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-11 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer edited 
https://github.com/llvm/llvm-project/pull/143594
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-10 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From c973e73b792cc1440af7c9001a0ddcfef94a9e21 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 77 ++---
 llvm/utils/llvm-original-di-preservation.py | 22 +++---
 2 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 729813a92f516..a9a66baf5571f 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,49 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2)
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -454,14 +507,20 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+{"metadata", "DILocation"}, {"fn-name", FnName.str()},
+{"bb-name", BBName.str()}, {"instr", InstName}, {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+{"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << NameOfWrappedPass
   << " did not generate DILocation for " << *Instr
@@ -474,11 +533,7 @@ static bool checkInstructions(const DebugInstMap 
&DILocsB

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-10 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/143594

>From c973e73b792cc1440af7c9001a0ddcfef94a9e21 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 77 ++---
 llvm/utils/llvm-original-di-preservation.py | 22 +++---
 2 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 729813a92f516..a9a66baf5571f 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,49 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2)
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -454,14 +507,20 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+{"metadata", "DILocation"}, {"fn-name", FnName.str()},
+{"bb-name", BBName.str()}, {"instr", InstName}, {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+{"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << NameOfWrappedPass
   << " did not generate DILocation for " << *Instr
@@ -474,11 +533,7 @@ static bool checkInstructions(const DebugInstMap 
&DILocsB

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Add debugify support (PR #143594)

2025-06-10 Thread Stephen Tozer via llvm-branch-commits

https://github.com/SLTozer created 
https://github.com/llvm/llvm-project/pull/143594

None

>From 4786afd40d73ade22952ca43af1164c6f9545679 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:02:36 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Add debugify support

---
 llvm/lib/Transforms/Utils/Debugify.cpp  | 77 ++---
 llvm/utils/llvm-original-di-preservation.py | 22 +++---
 2 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp 
b/llvm/lib/Transforms/Utils/Debugify.cpp
index 729813a92f516..a9a66baf5571f 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -15,7 +15,10 @@
 
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/InstIterator.h"
@@ -28,6 +31,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/JSON.h"
 #include 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// We need the Signals header to operate on stacktraces if we're using DebugLoc
+// origin-tracking.
+#include "llvm/Support/Signals.h"
+#endif
 
 #define DEBUG_TYPE "debugify"
 
@@ -59,6 +67,49 @@ cl::opt DebugifyLevel(
 
 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+// These maps refer to addresses in this instance of LLVM, so we can reuse them
+// everywhere - therefore, we store them at file scope.
+static DenseMap SymbolizedAddrs;
+static DenseSet UnsymbolizedAddrs;
+
+std::string symbolizeStackTrace(const Instruction *I) {
+  // We flush the set of unsymbolized addresses at the latest possible moment,
+  // i.e. now.
+  if (!UnsymbolizedAddrs.empty()) {
+sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
+UnsymbolizedAddrs.clear();
+  }
+  auto OriginStackTraces = I->getDebugLoc().getOriginStackTraces();
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
+if (TraceIdx != 0)
+  OS << "\n";
+auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
+ "Expected each address to have been symbolized.");
+  OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2)
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
+}
+  }
+  return Result;
+}
+void collectStackAddresses(Instruction &I) {
+  auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();
+  for (auto &[Depth, StackTrace] : OriginStackTraces) {
+for (int Frame = 0; Frame < Depth; ++Frame) {
+  void *Addr = StackTrace[Frame];
+  if (!SymbolizedAddrs.contains(Addr))
+UnsymbolizedAddrs.insert(Addr);
+}
+  }
+}
+#else
+void collectStackAddresses(Instruction &I) {}
+#endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+
 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
 }
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
 LLVM_DEBUG(dbgs() << "  Collecting info for inst: " << I << '\n');
 DebugInfoBeforePass.InstToDelete.insert({&I, &I});
 
+// Track the addresses to symbolize, if the feature is enabled.
+collectStackAddresses(I);
 DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)});
   }
 }
@@ -454,14 +507,20 @@ static bool checkInstructions(const DebugInstMap 
&DILocsBefore,
 auto BBName = BB->hasName() ? BB->getName() : "no-name";
 auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
 
+auto CreateJSONBugEntry = [&](const char *Action) {
+  Bugs.push_back(llvm::json::Object({
+{"metadata", "DILocation"}, {"fn-name", FnName.str()},
+{"bb-name", BBName.str()}, {"instr", InstName}, {"action", Action},
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+{"origin", symbolizeStackTrace(Instr)},
+#endif
+  }));
+};
+
 auto InstrIt = DILocsBefore.find(Instr);
 if (InstrIt == DILocsBefore.end()) {
   if (ShouldWriteIntoJSON)
-Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
-   {"fn-name", FnName.str()},
-   {"bb-name", BBName.str()},
-   {"instr", InstName},
-   {"action", "not-generate"}}));
+CreateJSONBugEntry("not-generate");
   else
 dbg() << "WARNING: " << NameOfWrappedPass
   << " did not generate DILocation for " << *Instr
@@ -474,11 +533,7 @@ static bool checkInstructions(const DebugInstMap 
&D