[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Core implementation (PR #143592)

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

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

>From 6ade803aa6c7e0137e4e572d379238a9d1fc202e Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:00:51 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Core implementation

---
 llvm/include/llvm/IR/DebugLoc.h | 49 -
 llvm/lib/IR/DebugLoc.cpp| 22 ++-
 2 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h
index c3d0fb80354a4..1930199607204 100644
--- a/llvm/include/llvm/IR/DebugLoc.h
+++ b/llvm/include/llvm/IR/DebugLoc.h
@@ -27,6 +27,21 @@ namespace llvm {
   class Function;
 
 #if LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+  struct DbgLocOrigin {
+static constexpr unsigned long MaxDepth = 16;
+using StackTracesTy =
+SmallVector>, 0>;
+StackTracesTy StackTraces;
+DbgLocOrigin(bool ShouldCollectTrace);
+void addTrace();
+const StackTracesTy &getOriginStackTraces() const { return StackTraces; };
+  };
+#else
+  struct DbgLocOrigin {
+DbgLocOrigin(bool) {}
+  };
+#endif
   // Used to represent different "kinds" of DebugLoc, expressing that the
   // instruction it is part of is either normal and should contain a valid
   // DILocation, or otherwise describing the reason why the instruction does
@@ -55,22 +70,29 @@ namespace llvm {
 Temporary
   };
 
-  // Extends TrackingMDNodeRef to also store a DebugLocKind, allowing Debugify
-  // to ignore intentionally-empty DebugLocs.
-  class DILocAndCoverageTracking : public TrackingMDNodeRef {
+  // Extends TrackingMDNodeRef to also store a DebugLocKind and Origin,
+  // allowing Debugify to ignore intentionally-empty DebugLocs and display the
+  // code responsible for generating unintentionally-empty DebugLocs.
+  // Currently we only need to track the Origin of this DILoc when using a
+  // DebugLoc that is not annotated (i.e. has DebugLocKind::Normal) and has a
+  // null DILocation, so only collect the origin stacktrace in those cases.
+  class DILocAndCoverageTracking : public TrackingMDNodeRef,
+   public DbgLocOrigin {
   public:
 DebugLocKind Kind;
 // Default constructor for empty DebugLocs.
 DILocAndCoverageTracking()
-: TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal) {}
-// Valid or nullptr MDNode*, normal DebugLocKind.
+: TrackingMDNodeRef(nullptr), DbgLocOrigin(true),
+  Kind(DebugLocKind::Normal) {}
+// Valid or nullptr MDNode*, no annotative DebugLocKind.
 DILocAndCoverageTracking(const MDNode *Loc)
-: TrackingMDNodeRef(const_cast(Loc)),
+: TrackingMDNodeRef(const_cast(Loc)), DbgLocOrigin(!Loc),
   Kind(DebugLocKind::Normal) {}
 LLVM_ABI DILocAndCoverageTracking(const DILocation *Loc);
 // Explicit DebugLocKind, which always means a nullptr MDNode*.
 DILocAndCoverageTracking(DebugLocKind Kind)
-: TrackingMDNodeRef(nullptr), Kind(Kind) {}
+: TrackingMDNodeRef(nullptr),
+  DbgLocOrigin(Kind == DebugLocKind::Normal), Kind(Kind) {}
   };
   template <> struct simplify_type {
 using SimpleType = MDNode *;
@@ -142,6 +164,19 @@ namespace llvm {
 static inline DebugLoc getDropped() { return DebugLoc(); }
 #endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+const DbgLocOrigin::StackTracesTy &getOriginStackTraces() const {
+  return Loc.getOriginStackTraces();
+}
+DebugLoc getCopied() const {
+  DebugLoc NewDL = *this;
+  NewDL.Loc.addTrace();
+  return NewDL;
+}
+#else
+DebugLoc getCopied() const { return *this; }
+#endif
+
 /// Get the underlying \a DILocation.
 ///
 /// \pre !*this or \c isa(getAsMDNode()).
diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp
index 0e65ddcec8934..05aad5d393547 100644
--- a/llvm/lib/IR/DebugLoc.cpp
+++ b/llvm/lib/IR/DebugLoc.cpp
@@ -9,11 +9,31 @@
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/DebugInfo.h"
+
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+#include "llvm/Support/Signals.h"
+
+namespace llvm {
+DbgLocOrigin::DbgLocOrigin(bool ShouldCollectTrace) {
+  if (ShouldCollectTrace) {
+auto &[Depth, StackTrace] = StackTraces.emplace_back();
+Depth = sys::getStackTrace(StackTrace);
+  }
+}
+void DbgLocOrigin::addTrace() {
+  if (StackTraces.empty())
+return;
+  auto &[Depth, StackTrace] = StackTraces.emplace_back();
+  Depth = sys::getStackTrace(StackTrace);
+}
+} // namespace llvm
+#endif
+
 using namespace llvm;
 
 #if LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
 DILocAndCoverageTracking::DILocAndCoverageTracking(const DILocation *L)
-: TrackingMDNodeRef(const_cast(L)),
+: TrackingMDNodeRef(const_cast(L)), DbgLocOrigin(!L),
   Kind(DebugLocKind::Normal) {}
 #endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Core implementation (PR #143592)

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

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

>From 6ade803aa6c7e0137e4e572d379238a9d1fc202e Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:00:51 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Core implementation

---
 llvm/include/llvm/IR/DebugLoc.h | 49 -
 llvm/lib/IR/DebugLoc.cpp| 22 ++-
 2 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h
index c3d0fb80354a4..1930199607204 100644
--- a/llvm/include/llvm/IR/DebugLoc.h
+++ b/llvm/include/llvm/IR/DebugLoc.h
@@ -27,6 +27,21 @@ namespace llvm {
   class Function;
 
 #if LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+  struct DbgLocOrigin {
+static constexpr unsigned long MaxDepth = 16;
+using StackTracesTy =
+SmallVector>, 0>;
+StackTracesTy StackTraces;
+DbgLocOrigin(bool ShouldCollectTrace);
+void addTrace();
+const StackTracesTy &getOriginStackTraces() const { return StackTraces; };
+  };
+#else
+  struct DbgLocOrigin {
+DbgLocOrigin(bool) {}
+  };
+#endif
   // Used to represent different "kinds" of DebugLoc, expressing that the
   // instruction it is part of is either normal and should contain a valid
   // DILocation, or otherwise describing the reason why the instruction does
@@ -55,22 +70,29 @@ namespace llvm {
 Temporary
   };
 
-  // Extends TrackingMDNodeRef to also store a DebugLocKind, allowing Debugify
-  // to ignore intentionally-empty DebugLocs.
-  class DILocAndCoverageTracking : public TrackingMDNodeRef {
+  // Extends TrackingMDNodeRef to also store a DebugLocKind and Origin,
+  // allowing Debugify to ignore intentionally-empty DebugLocs and display the
+  // code responsible for generating unintentionally-empty DebugLocs.
+  // Currently we only need to track the Origin of this DILoc when using a
+  // DebugLoc that is not annotated (i.e. has DebugLocKind::Normal) and has a
+  // null DILocation, so only collect the origin stacktrace in those cases.
+  class DILocAndCoverageTracking : public TrackingMDNodeRef,
+   public DbgLocOrigin {
   public:
 DebugLocKind Kind;
 // Default constructor for empty DebugLocs.
 DILocAndCoverageTracking()
-: TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal) {}
-// Valid or nullptr MDNode*, normal DebugLocKind.
+: TrackingMDNodeRef(nullptr), DbgLocOrigin(true),
+  Kind(DebugLocKind::Normal) {}
+// Valid or nullptr MDNode*, no annotative DebugLocKind.
 DILocAndCoverageTracking(const MDNode *Loc)
-: TrackingMDNodeRef(const_cast(Loc)),
+: TrackingMDNodeRef(const_cast(Loc)), DbgLocOrigin(!Loc),
   Kind(DebugLocKind::Normal) {}
 LLVM_ABI DILocAndCoverageTracking(const DILocation *Loc);
 // Explicit DebugLocKind, which always means a nullptr MDNode*.
 DILocAndCoverageTracking(DebugLocKind Kind)
-: TrackingMDNodeRef(nullptr), Kind(Kind) {}
+: TrackingMDNodeRef(nullptr),
+  DbgLocOrigin(Kind == DebugLocKind::Normal), Kind(Kind) {}
   };
   template <> struct simplify_type {
 using SimpleType = MDNode *;
@@ -142,6 +164,19 @@ namespace llvm {
 static inline DebugLoc getDropped() { return DebugLoc(); }
 #endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
 
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+const DbgLocOrigin::StackTracesTy &getOriginStackTraces() const {
+  return Loc.getOriginStackTraces();
+}
+DebugLoc getCopied() const {
+  DebugLoc NewDL = *this;
+  NewDL.Loc.addTrace();
+  return NewDL;
+}
+#else
+DebugLoc getCopied() const { return *this; }
+#endif
+
 /// Get the underlying \a DILocation.
 ///
 /// \pre !*this or \c isa(getAsMDNode()).
diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp
index 0e65ddcec8934..05aad5d393547 100644
--- a/llvm/lib/IR/DebugLoc.cpp
+++ b/llvm/lib/IR/DebugLoc.cpp
@@ -9,11 +9,31 @@
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/DebugInfo.h"
+
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+#include "llvm/Support/Signals.h"
+
+namespace llvm {
+DbgLocOrigin::DbgLocOrigin(bool ShouldCollectTrace) {
+  if (ShouldCollectTrace) {
+auto &[Depth, StackTrace] = StackTraces.emplace_back();
+Depth = sys::getStackTrace(StackTrace);
+  }
+}
+void DbgLocOrigin::addTrace() {
+  if (StackTraces.empty())
+return;
+  auto &[Depth, StackTrace] = StackTraces.emplace_back();
+  Depth = sys::getStackTrace(StackTrace);
+}
+} // namespace llvm
+#endif
+
 using namespace llvm;
 
 #if LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
 DILocAndCoverageTracking::DILocAndCoverageTracking(const DILocation *L)
-: TrackingMDNodeRef(const_cast(L)),
+: TrackingMDNodeRef(const_cast(L)), DbgLocOrigin(!L),
   Kind(DebugLocKind::Normal) {}
 #endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING

[llvm-branch-commits] [llvm] [DLCov] Origin-Tracking: Core implementation (PR #143592)

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

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

None

>From 8ff21d6e7630b0407931712eb652e0416ce661d8 Mon Sep 17 00:00:00 2001
From: Stephen Tozer 
Date: Tue, 10 Jun 2025 20:00:51 +0100
Subject: [PATCH] [DLCov] Origin-Tracking: Core implementation

---
 llvm/include/llvm/IR/DebugLoc.h | 62 +
 llvm/lib/IR/DebugLoc.cpp| 22 +++-
 2 files changed, 76 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h
index c3d0fb80354a4..bc890dd671a81 100644
--- a/llvm/include/llvm/IR/DebugLoc.h
+++ b/llvm/include/llvm/IR/DebugLoc.h
@@ -27,6 +27,21 @@ namespace llvm {
   class Function;
 
 #if LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+  struct DbgLocOrigin {
+static constexpr unsigned long MaxDepth = 16;
+using StackTracesTy =
+SmallVector>, 0>;
+StackTracesTy StackTraces;
+DbgLocOrigin(bool ShouldCollectTrace);
+void addTrace();
+const StackTracesTy &getOriginStackTraces() const { return StackTraces; };
+  };
+#else
+  struct DbgLocOrigin {
+DbgLocOrigin(bool) {}
+  };
+#endif
   // Used to represent different "kinds" of DebugLoc, expressing that the
   // instruction it is part of is either normal and should contain a valid
   // DILocation, or otherwise describing the reason why the instruction does
@@ -55,22 +70,29 @@ namespace llvm {
 Temporary
   };
 
-  // Extends TrackingMDNodeRef to also store a DebugLocKind, allowing Debugify
-  // to ignore intentionally-empty DebugLocs.
-  class DILocAndCoverageTracking : public TrackingMDNodeRef {
+  // Extends TrackingMDNodeRef to also store a DebugLocKind and Origin,
+  // allowing Debugify to ignore intentionally-empty DebugLocs and display the
+  // code responsible for generating unintentionally-empty DebugLocs.
+  // Currently we only need to track the Origin of this DILoc when using a
+  // DebugLoc that is not annotated (i.e. has DebugLocKind::Normal) and has a
+  // null DILocation, so only collect the origin stacktrace in those cases.
+  class DILocAndCoverageTracking : public TrackingMDNodeRef,
+   public DbgLocOrigin {
   public:
 DebugLocKind Kind;
 // Default constructor for empty DebugLocs.
 DILocAndCoverageTracking()
-: TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal) {}
-// Valid or nullptr MDNode*, normal DebugLocKind.
+: TrackingMDNodeRef(nullptr), DbgLocOrigin(true),
+  Kind(DebugLocKind::Normal) {}
+// Valid or nullptr MDNode*, no annotative DebugLocKind.
 DILocAndCoverageTracking(const MDNode *Loc)
-: TrackingMDNodeRef(const_cast(Loc)),
+: TrackingMDNodeRef(const_cast(Loc)), DbgLocOrigin(!Loc),
   Kind(DebugLocKind::Normal) {}
 LLVM_ABI DILocAndCoverageTracking(const DILocation *Loc);
 // Explicit DebugLocKind, which always means a nullptr MDNode*.
 DILocAndCoverageTracking(DebugLocKind Kind)
-: TrackingMDNodeRef(nullptr), Kind(Kind) {}
+: TrackingMDNodeRef(nullptr),
+  DbgLocOrigin(Kind == DebugLocKind::Normal), Kind(Kind) {}
   };
   template <> struct simplify_type {
 using SimpleType = MDNode *;
@@ -142,6 +164,32 @@ namespace llvm {
 static inline DebugLoc getDropped() { return DebugLoc(); }
 #endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
 
+#if LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
+DebugLoc(DebugLocKind Kind) : Loc(Kind) {}
+DebugLocKind getKind() const { return Loc.Kind; }
+#endif
+
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+#if !LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
+#error Cannot enable DebugLoc origin-tracking without coverage-tracking!
+#endif
+
+const DbgLocOrigin::StackTracesTy &getOriginStackTraces() const {
+  return Loc.getOriginStackTraces();
+}
+DebugLoc getCopied() const {
+  DebugLoc NewDL = *this;
+  NewDL.Loc.addTrace();
+  return NewDL;
+}
+#else
+DebugLoc getCopied() const { return *this; }
+#endif
+
+static DebugLoc getTemporary();
+static DebugLoc getUnknown();
+static DebugLoc getLineZero();
+
 /// Get the underlying \a DILocation.
 ///
 /// \pre !*this or \c isa(getAsMDNode()).
diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp
index 0e65ddcec8934..05aad5d393547 100644
--- a/llvm/lib/IR/DebugLoc.cpp
+++ b/llvm/lib/IR/DebugLoc.cpp
@@ -9,11 +9,31 @@
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/DebugInfo.h"
+
+#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
+#include "llvm/Support/Signals.h"
+
+namespace llvm {
+DbgLocOrigin::DbgLocOrigin(bool ShouldCollectTrace) {
+  if (ShouldCollectTrace) {
+auto &[Depth, StackTrace] = StackTraces.emplace_back();
+Depth = sys::getStackTrace(StackTrace);
+  }
+}
+void DbgLocOrigin::addTrace() {
+  if (StackTraces.empty())
+return;
+  auto &[Depth, StackTrace] = StackTraces.emplace_back();
+  Dept