Skip to content

[DLCov 3/5] Implement DebugLoc origin-tracking #107369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions llvm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,8 @@ endif()
option(LLVM_ENABLE_CRASH_DUMPS "Turn on memory dumps on crashes. Currently only implemented on Windows." OFF)

set(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING "DISABLED" CACHE STRING
"Enhance Debugify's line number coverage tracking; enabling this is ABI-breaking. Can be DISABLED, or COVERAGE.")
set_property(CACHE LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING PROPERTY STRINGS DISABLED COVERAGE)
"Enhance debugify's line number coverage tracking; enabling this is abi-breaking. Can be DISABLED, COVERAGE, or COVERAGE_AND_ORIGIN.")
set_property(CACHE LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING PROPERTY STRINGS DISABLED COVERAGE COVERAGE_AND_ORIGIN)

option(LLVM_EXPERIMENTAL_KEY_INSTRUCTIONS
"Add additional fields to DILocations to support Key Instructions" OFF)
Expand Down
3 changes: 3 additions & 0 deletions llvm/cmake/modules/HandleLLVMOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ string(TOUPPER "${LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING}" uppercase_LLVM_ENABLE

if( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "COVERAGE" )
set( LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING 1 )
elseif( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "COVERAGE_AND_ORIGIN" )
set( ENABLE_DEBUGLOC_COVERAGE_TRACKING 1 )
set( LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING 1 )
elseif( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "DISABLED" OR NOT DEFINED LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING )
# The DISABLED setting is default and requires no additional defines.
else()
Expand Down
13 changes: 8 additions & 5 deletions llvm/docs/CMake.rst
Original file line number Diff line number Diff line change
Expand Up @@ -482,11 +482,14 @@ enabled sub-projects. Nearly all of these variable names begin with
**LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING**:STRING
Enhances Debugify's ability to detect line number errors by storing extra
information inside Instructions, removing false positives from Debugify's
results at the cost of performance. Allowed values are `DISABLED` (default)
and `COVERAGE`. `COVERAGE` tracks whether and why a line number was
intentionally dropped or not generated for an instruction, allowing Debugify
to avoid reporting these as errors; this comes with a small performance cost
of ~0.1%. `COVERAGE` is an ABI-breaking option.
results at the cost of performance. Allowed values are `DISABLED` (default),
`COVERAGE`, and `COVERAGE_AND_ORIGIN`. `COVERAGE` tracks whether and why a
line number was intentionally dropped or not generated for an instruction,
allowing Debugify to avoid reporting these as errors; this comes with a small
performance cost of ~0.1%. `COVERAGE_AND_ORIGIN` additionally stores a
stacktrace of the point where each DebugLoc is unintentionally dropped,
allowing for much easier bug triaging at the cost of a ~10x performance
slowdown. `COVERAGE` and `COVERAGE_AND_ORIGIN` are ABI-breaking options.

**LLVM_ENABLE_DIA_SDK**:BOOL
Enable building with MSVC DIA SDK for PDB debugging support. Available
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/Config/config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@
/* Define to 1 to enable crash memory dumps, and to 0 otherwise. */
#cmakedefine01 LLVM_ENABLE_CRASH_DUMPS

/* Define to 1 to enable expensive checks for debug location coverage checking,
and to 0 otherwise. */
#cmakedefine01 ENABLE_DEBUGLOC_COVERAGE_TRACKING

/* Define to 1 to enable expensive tracking of the origin of debug location
coverage bugs, and to 0 otherwise. */
#cmakedefine01 LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING

/* Define to 1 to prefer forward slashes on Windows, and to 0 prefer
backslashes. */
#cmakedefine01 LLVM_WINDOWS_PREFER_FORWARD_SLASH
Expand Down
62 changes: 55 additions & 7 deletions llvm/include/llvm/IR/DebugLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::pair<int, std::array<void *, MaxDepth>>, 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
Expand Down Expand Up @@ -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<MDNode *>(Loc)),
: TrackingMDNodeRef(const_cast<MDNode *>(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<DILocAndCoverageTracking> {
using SimpleType = MDNode *;
Expand Down Expand Up @@ -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<DILocation>(getAsMDNode()).
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/IR/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ class Instruction : public User,
LLVM_ABI bool extractProfTotalWeight(uint64_t &TotalVal) const;

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

/// Return the debug location for this node as a DebugLoc.
const DebugLoc &getDebugLoc() const { return DbgLoc; }
Expand Down
40 changes: 40 additions & 0 deletions llvm/include/llvm/Support/Signals.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,32 @@
#ifndef LLVM_SUPPORT_SIGNALS_H
#define LLVM_SUPPORT_SIGNALS_H

#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Compiler.h"
#include <array>
#include <cstdint>
#include <string>

namespace llvm {
class StringRef;
class raw_ostream;

#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
// Typedefs that are convenient but only used by the stack-trace-collection code
// added if DebugLoc origin-tracking is enabled.
template <typename T, typename Enable> struct DenseMapInfo;
template <typename ValueT, typename ValueInfoT> class DenseSet;
namespace detail {
template <typename KeyT, typename ValueT> struct DenseMapPair;
}
template <typename KeyT, typename ValueT, typename KeyInfoT, typename BucketT>
class DenseMap;
using AddressSet = DenseSet<void *, DenseMapInfo<void *, void>>;
using SymbolizedAddressMap =
DenseMap<void *, std::string, DenseMapInfo<void *, void>,
detail::DenseMapPair<void *, std::string>>;
#endif

namespace sys {

/// This function runs all the registered interrupt handlers, including the
Expand Down Expand Up @@ -57,6 +75,28 @@ LLVM_ABI void DisableSystemDialogsOnCrash();
/// specified, the entire frame is printed.
LLVM_ABI void PrintStackTrace(raw_ostream &OS, int Depth = 0);

#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
#ifdef NDEBUG
#error DebugLoc origin-tracking should not be enabled in Release builds.
#endif
/// Populates the given array with a stack trace of the current program, up to
/// MaxDepth frames. Returns the number of frames returned, which will be
/// inserted into \p StackTrace from index 0. All entries after the returned
/// depth will be unmodified. NB: This is only intended to be used for
/// introspection of LLVM by Debugify, will not be enabled in release builds,
/// and should not be relied on for other purposes.
template <unsigned long MaxDepth>
int getStackTrace(std::array<void *, MaxDepth> &StackTrace);

/// Takes a set of \p Addresses, symbolizes them and stores the result in the
/// provided \p SymbolizedAddresses map.
/// NB: This is only intended to be used for introspection of LLVM by
/// Debugify, will not be enabled in release builds, and should not be relied
/// on for other purposes.
void symbolizeAddresses(AddressSet &Addresses,
SymbolizedAddressMap &SymbolizedAddresses);
#endif

// Run all registered signal handlers.
LLVM_ABI void RunSignalHandlers();

Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/CodeGen/BranchFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
Expand Down Expand Up @@ -933,7 +934,13 @@ bool BranchFolder::TryTailMergeBlocks(MachineBasicBlock *SuccBB,

// Sort by hash value so that blocks with identical end sequences sort
// together.
#if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
// If origin-tracking is enabled then MergePotentialElt is no longer a POD
// type, so we need std::sort instead.
std::sort(MergePotentials.begin(), MergePotentials.end());
#else
array_pod_sort(MergePotentials.begin(), MergePotentials.end());
#endif

// Walk through equivalence sets looking for actual exact matches.
while (MergePotentials.size() > 1) {
Expand Down
22 changes: 21 additions & 1 deletion llvm/lib/IR/DebugLoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<DILocation *>(L)),
: TrackingMDNodeRef(const_cast<DILocation *>(L)), DbgLocOrigin(!L),
Kind(DebugLocKind::Normal) {}
#endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/Instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1393,5 +1393,6 @@ Instruction *Instruction::clone() const {

New->SubclassOptionalData = SubclassOptionalData;
New->copyMetadata(*this);
New->setDebugLoc(getDebugLoc().getCopied());
return New;
}
Loading
Loading