Skip to content

Commit 4f047bc

Browse files
authored
[DLCov] Origin-Tracking: Collect stack traces in DebugLoc (#146678)
This patch is part of a series that adds origin-tracking to the debugify source location coverage checks, allowing us to report symbolized stack traces of the point where missing source locations appear. This patch adds the logic for collecting stack traces in DebugLoc instances. We do not symbolize the stack traces in this patch - that only happens when we decide to actually print them, which will be the responsibility of debugify. The collection happens in the constructor of a DebugLoc that has neither a valid location nor an annotation; we also collect an extra stack trace every time we call setDebugLoc, as sometimes the more interesting point is not where the DebugLoc was constructed, but where it was applied to an instruction. This takes the form of a getCopied() method on DebugLoc, which is the identity function in normal builds, but adds an extra stack trace in origin-tracking builds.
1 parent 30eb97c commit 4f047bc

File tree

4 files changed

+75
-9
lines changed

4 files changed

+75
-9
lines changed

llvm/include/llvm/IR/DebugLoc.h

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ namespace llvm {
2727
class Function;
2828

2929
#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
30+
#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
31+
struct DbgLocOrigin {
32+
static constexpr unsigned long MaxDepth = 16;
33+
using StackTracesTy =
34+
SmallVector<std::pair<int, std::array<void *, MaxDepth>>, 0>;
35+
StackTracesTy StackTraces;
36+
DbgLocOrigin(bool ShouldCollectTrace);
37+
void addTrace();
38+
const StackTracesTy &getOriginStackTraces() const { return StackTraces; };
39+
};
40+
#else
41+
struct DbgLocOrigin {
42+
DbgLocOrigin(bool) {}
43+
};
44+
#endif
3045
// Used to represent different "kinds" of DebugLoc, expressing that the
3146
// instruction it is part of is either normal and should contain a valid
3247
// DILocation, or otherwise describing the reason why the instruction does
@@ -55,22 +70,29 @@ namespace llvm {
5570
Temporary
5671
};
5772

58-
// Extends TrackingMDNodeRef to also store a DebugLocKind, allowing Debugify
59-
// to ignore intentionally-empty DebugLocs.
60-
class DILocAndCoverageTracking : public TrackingMDNodeRef {
73+
// Extends TrackingMDNodeRef to also store a DebugLocKind and Origin,
74+
// allowing Debugify to ignore intentionally-empty DebugLocs and display the
75+
// code responsible for generating unintentionally-empty DebugLocs.
76+
// Currently we only need to track the Origin of this DILoc when using a
77+
// DebugLoc that is not annotated (i.e. has DebugLocKind::Normal) and has a
78+
// null DILocation, so only collect the origin stacktrace in those cases.
79+
class DILocAndCoverageTracking : public TrackingMDNodeRef,
80+
public DbgLocOrigin {
6181
public:
6282
DebugLocKind Kind;
6383
// Default constructor for empty DebugLocs.
6484
DILocAndCoverageTracking()
65-
: TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal) {}
66-
// Valid or nullptr MDNode*, normal DebugLocKind.
85+
: TrackingMDNodeRef(nullptr), DbgLocOrigin(true),
86+
Kind(DebugLocKind::Normal) {}
87+
// Valid or nullptr MDNode*, no annotative DebugLocKind.
6788
DILocAndCoverageTracking(const MDNode *Loc)
68-
: TrackingMDNodeRef(const_cast<MDNode *>(Loc)),
89+
: TrackingMDNodeRef(const_cast<MDNode *>(Loc)), DbgLocOrigin(!Loc),
6990
Kind(DebugLocKind::Normal) {}
7091
LLVM_ABI DILocAndCoverageTracking(const DILocation *Loc);
7192
// Explicit DebugLocKind, which always means a nullptr MDNode*.
7293
DILocAndCoverageTracking(DebugLocKind Kind)
73-
: TrackingMDNodeRef(nullptr), Kind(Kind) {}
94+
: TrackingMDNodeRef(nullptr),
95+
DbgLocOrigin(Kind == DebugLocKind::Normal), Kind(Kind) {}
7496
};
7597
template <> struct simplify_type<DILocAndCoverageTracking> {
7698
using SimpleType = MDNode *;
@@ -187,6 +209,19 @@ namespace llvm {
187209
#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
188210
}
189211

212+
#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
213+
const DbgLocOrigin::StackTracesTy &getOriginStackTraces() const {
214+
return Loc.getOriginStackTraces();
215+
}
216+
DebugLoc getCopied() const {
217+
DebugLoc NewDL = *this;
218+
NewDL.Loc.addTrace();
219+
return NewDL;
220+
}
221+
#else
222+
DebugLoc getCopied() const { return *this; }
223+
#endif
224+
190225
/// Get the underlying \a DILocation.
191226
///
192227
/// \pre !*this or \c isa<DILocation>(getAsMDNode()).

llvm/include/llvm/IR/Instruction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ class Instruction : public User,
507507
LLVM_ABI bool extractProfTotalWeight(uint64_t &TotalVal) const;
508508

509509
/// Set the debug location information for this instruction.
510-
void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); }
510+
void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc).getCopied(); }
511511

512512
/// Return the debug location for this node as a DebugLoc.
513513
const DebugLoc &getDebugLoc() const { return DbgLoc; }

llvm/lib/CodeGen/BranchFolding.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "llvm/CodeGen/TargetPassConfig.h"
4343
#include "llvm/CodeGen/TargetRegisterInfo.h"
4444
#include "llvm/CodeGen/TargetSubtargetInfo.h"
45+
#include "llvm/Config/llvm-config.h"
4546
#include "llvm/IR/DebugInfoMetadata.h"
4647
#include "llvm/IR/DebugLoc.h"
4748
#include "llvm/IR/Function.h"
@@ -933,7 +934,13 @@ bool BranchFolder::TryTailMergeBlocks(MachineBasicBlock *SuccBB,
933934

934935
// Sort by hash value so that blocks with identical end sequences sort
935936
// together.
937+
#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
938+
// If origin-tracking is enabled then MergePotentialElt is no longer a POD
939+
// type, so we need std::sort instead.
940+
std::sort(MergePotentials.begin(), MergePotentials.end());
941+
#else
936942
array_pod_sort(MergePotentials.begin(), MergePotentials.end());
943+
#endif
937944

938945
// Walk through equivalence sets looking for actual exact matches.
939946
while (MergePotentials.size() > 1) {

llvm/lib/IR/DebugLoc.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,35 @@
99
#include "llvm/IR/DebugLoc.h"
1010
#include "llvm/Config/llvm-config.h"
1111
#include "llvm/IR/DebugInfo.h"
12+
13+
#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
14+
#include "llvm/Support/Signals.h"
15+
16+
namespace llvm {
17+
DbgLocOrigin::DbgLocOrigin(bool ShouldCollectTrace) {
18+
if (!ShouldCollectTrace)
19+
return;
20+
auto &[Depth, StackTrace] = StackTraces.emplace_back();
21+
Depth = sys::getStackTrace(StackTrace);
22+
}
23+
void DbgLocOrigin::addTrace() {
24+
// We only want to add new stacktraces if we already have one: addTrace exists
25+
// to provide more context to how missing DebugLocs have propagated through
26+
// the program, but by design if there is no existing stacktrace then we have
27+
// decided not to track this DebugLoc as being "missing".
28+
if (StackTraces.empty())
29+
return;
30+
auto &[Depth, StackTrace] = StackTraces.emplace_back();
31+
Depth = sys::getStackTrace(StackTrace);
32+
}
33+
} // namespace llvm
34+
#endif
35+
1236
using namespace llvm;
1337

1438
#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
1539
DILocAndCoverageTracking::DILocAndCoverageTracking(const DILocation *L)
16-
: TrackingMDNodeRef(const_cast<DILocation *>(L)),
40+
: TrackingMDNodeRef(const_cast<DILocation *>(L)), DbgLocOrigin(!L),
1741
Kind(DebugLocKind::Normal) {}
1842
#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
1943

0 commit comments

Comments
 (0)