[llvm] [llvm-dwarfdump][LineCov 2/3] Add coverage baseline comparison and line table coverage in isolation (PR #183790)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 7 07:09:58 PDT 2026
https://github.com/unexpectedlydefined updated https://github.com/llvm/llvm-project/pull/183790
>From c531d9ac8a49a546bf503a4a35c03ad172069be1 Mon Sep 17 00:00:00 2001
From: unexpectedlydefined <unexpectedlydefined at gmail.com>
Date: Tue, 4 Nov 2025 13:21:21 +0000
Subject: [PATCH 1/7] Add coverage baseline comparison and line table coverage
in isolation
---
llvm/docs/CommandGuide/llvm-dwarfdump.rst | 18 +++-
.../tools/llvm-dwarfdump/X86/coverage.test | 12 +++
llvm/tools/llvm-dwarfdump/Coverage.cpp | 92 +++++++++++++++++--
llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 27 +++++-
llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h | 4 +-
5 files changed, 140 insertions(+), 13 deletions(-)
diff --git a/llvm/docs/CommandGuide/llvm-dwarfdump.rst b/llvm/docs/CommandGuide/llvm-dwarfdump.rst
index 86bdfd6f5224e..a9dab58fc37ab 100644
--- a/llvm/docs/CommandGuide/llvm-dwarfdump.rst
+++ b/llvm/docs/CommandGuide/llvm-dwarfdump.rst
@@ -198,6 +198,11 @@ OPTIONS
Show per-variable coverage metrics. The output format is described
in the section below (:ref:`variable-coverage-format`).
+.. option:: --coverage-baseline
+
+ File to use as the baseline for variable coverage statistics
+ (implies :option:`--show-variable-coverage`)
+
.. option:: --combine-inline-variable-instances
Use with :option:`--show-variable-coverage` to average variable
@@ -280,7 +285,18 @@ a tab-separated table containing the following columns:
declaration
- `LinesCovered` ==> Number of source lines covered by the variable's
debug information in the input file
-
+ - `Baseline` (empty if :option:`--coverage-baseline` is not specified)
+ ==> Number of source lines covered by the variable's debug information
+ in the baseline
+ - `CoveredRatio` (empty if :option:`--coverage-baseline` is not
+ specified) ==> Ratio of the coverage compared to the baseline
+ (calculated as `LinesCovered/Baseline`)
+ - `LT` (empty if :option:`--coverage-baseline` is not specified) ==>
+ Number of source lines covered in the variable's baseline debug
+ information that are also present in the input file's line table
+ - `LTRatio` (empty if :option:`--coverage-baseline` is not specified) ==>
+ Ratio of the line table coverage compared to the baseline (calculated
+ as `LT/Baseline`)
EXIT STATUS
-----------
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/coverage.test b/llvm/test/tools/llvm-dwarfdump/X86/coverage.test
index 15762a38ef7bd..20cc6b8d38dac 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/coverage.test
+++ b/llvm/test/tools/llvm-dwarfdump/X86/coverage.test
@@ -24,3 +24,15 @@ COMBINE-NEXT: fn1 1 u test.c:4 1
COMBINE-NEXT: fn1 1 v test.c:13 0
COMBINE-NEXT: fn1 1 x test.c:3 7
COMBINE-NEXT: fn1 1 y test.c:3 7
+
+RUN: llvm-dwarfdump --show-variable-coverage --coverage-baseline=%t.o %t-opt.o | FileCheck %s --check-prefix=BASELINE
+
+BASELINE: Variable coverage statistics:
+BASELINE-NEXT: Function InlChain Variable Decl LinesCovered Baseline CoveredRatio LT LTRatio
+BASELINE-NEXT: f k test.c:20 5 5 1 5 1
+BASELINE-NEXT: f l test.c:20 5 5 1 5 1
+BASELINE-NEXT: fn1 a test.c:11 5 14 0.357 7 0.5
+BASELINE-NEXT: fn1 u test.c:4 1 14 0.0714 7 0.5
+BASELINE-NEXT: fn1 v test.c:13 0 14 0 7 0.5
+BASELINE-NEXT: fn1 x test.c:3 7 14 0.5 7 0.5
+BASELINE-NEXT: fn1 y test.c:3 7 14 0.5 7 0.5
diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp
index 26708b855be1e..1ca29319d9dec 100644
--- a/llvm/tools/llvm-dwarfdump/Coverage.cpp
+++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp
@@ -25,6 +25,7 @@
using namespace llvm;
using namespace llvm::dwarf;
+using namespace llvm::dwarfdump;
using namespace llvm::object;
/// Pair of file index and line number representing a source location.
@@ -35,7 +36,8 @@ typedef std::pair<uint16_t, size_t> SourceLocation;
/// scope's address ranges.
static DenseSet<SourceLocation>
computeVariableCoverage(DWARFContext &DICtx, DWARFDie VariableDIE,
- const DWARFDebugLine::LineTable *const LineTable) {
+ const DWARFDebugLine::LineTable *const LineTable,
+ bool LTCov) {
/// Adds source locations to the set that correspond to an address range.
auto addLines = [](const DWARFDebugLine::LineTable *LineTable,
DenseSet<SourceLocation> &Lines, DWARFAddressRange Range) {
@@ -71,15 +73,17 @@ computeVariableCoverage(DWARFContext &DICtx, DWARFDie VariableDIE,
}
}
} else {
+ consumeError(Locations.takeError());
// If the variable is optimized out and has no DW_AT_location, return an
// empty set instead of falling back to the parent scope's address ranges.
- consumeError(Locations.takeError());
- return {};
+ if (!LTCov)
+ return {};
}
// DW_AT_location attribute may contain overly broad address ranges, or none
// at all, so we also consider the parent scope's address ranges if present.
- auto ParentRanges = VariableDIE.getParent().getAddressRanges();
+ auto ParentRanges = LTCov ? VariableDIE.getAddressRanges()
+ : VariableDIE.getParent().getAddressRanges();
std::optional<DenseSet<SourceLocation>> ParentLines;
if (ParentRanges) {
ParentLines = DenseSet<SourceLocation>();
@@ -140,10 +144,15 @@ struct VarKey {
struct VarCoverage {
SmallVector<DWARFDie> Parents;
size_t Cov;
+ size_t BaselineCov;
+ size_t LTCov;
+ size_t Missing;
size_t Instances;
+ bool MissingBaseline;
};
typedef std::multimap<VarKey, VarCoverage, std::less<>> VarMap;
+typedef std::map<VarKey, DenseSet<SourceLocation>, std::less<>> BaselineVarMap;
static std::optional<const VarKey> getVarKey(DWARFDie Die, DWARFDie Parent) {
const auto *const DieName = Die.getName(DINameKind::LinkageName);
@@ -184,11 +193,52 @@ static void displayVariableCoverage(const VarKey &Key, const VarCoverage &Var,
WithColor(OS, HighlightColor::String) << Key.Name;
OS << "\t" << Key.DeclFile << ":" << Key.DeclLine;
OS << "\t" << format("%.3g", ((float)Var.Cov / Var.Instances));
+ if (Var.BaselineCov)
+ OS << "\t" << format("%.3g", ((float)Var.BaselineCov / Var.Instances))
+ << "\t" << format("%.3g", ((float)Var.Cov / Var.BaselineCov)) << "\t"
+ << format("%.3g", ((float)Var.LTCov / Var.Instances)) << "\t"
+ << format("%.3g", ((float)Var.LTCov / Var.BaselineCov));
OS << "\n";
+ if (Var.MissingBaseline)
+ WithColor(errs(), HighlightColor::Warning).warning()
+ << "DIE not found in baseline\n";
+ if (Var.Missing)
+ WithColor(errs(), HighlightColor::Warning).warning()
+ << Var.Missing << " lines not found in baseline\n";
}
bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
+ ObjectFile *BaselineObj,
+ DWARFContext *BaselineCtx,
bool CombineInstances, raw_ostream &OS) {
+ BaselineVarMap BaselineVars;
+
+ if (BaselineCtx) {
+ for (const auto &U : BaselineCtx->info_section_units()) {
+ const auto *const LT = BaselineCtx->getLineTableForUnit(U.get());
+ for (const auto &Entry : U->dies()) {
+ DWARFDie Die = {U.get(), &Entry};
+ if (Die.getTag() != DW_TAG_variable &&
+ Die.getTag() != DW_TAG_formal_parameter)
+ continue;
+
+ const auto Parents = getParentSubroutines(Die);
+ if (!Parents.size())
+ continue;
+ const auto Parent = Parents.front();
+ auto Key = getVarKey(Die, Parent);
+ if (!Key)
+ continue;
+
+ const auto Cov = computeVariableCoverage(*BaselineCtx, Die, LT, false);
+
+ auto Result = BaselineVars.insert({*Key, Cov});
+ if (!Result.second)
+ Result.first->second.insert_range(Cov);
+ }
+ }
+ }
+
VarMap Vars;
for (const auto &U : DICtx.info_section_units()) {
@@ -207,9 +257,28 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
if (!Key)
continue;
- const auto Cov = computeVariableCoverage(DICtx, Die, LT);
+ const auto Cov = computeVariableCoverage(DICtx, Die, LT, false);
+
+ VarCoverage VarCov = {Parents, Cov.size(), 0, 0, 0, 1, false};
+
+ if (BaselineCtx) {
+ BaselineVarMap::iterator Var = BaselineVars.find(*Key);
- VarCoverage VarCov = {Parents, Cov.size(), 1};
+ if (Var != BaselineVars.end()) {
+ const auto BCov = Var->second;
+ VarCov.BaselineCov = BCov.size();
+
+ for (const auto &L : Cov)
+ VarCov.Missing += (1 - BCov.count(L));
+
+ const auto LTCov = computeVariableCoverage(DICtx, Parent, LT, true);
+
+ for (const auto &L : BCov)
+ VarCov.LTCov += LTCov.count(L);
+ } else {
+ VarCov.MissingBaseline = true;
+ }
+ }
Vars.insert({*Key, VarCov});
}
@@ -219,16 +288,23 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
OS << "\nVariable coverage statistics:\nFunction\t"
<< (CombineInstances ? "InstanceCount" : "InlChain")
- << "\tVariable\tDecl\tLinesCovered\n";
+ << "\tVariable\tDecl\tLinesCovered";
+ if (BaselineCtx)
+ OS << "\tBaseline\tCoveredRatio\tLT\tLTRatio";
+ OS << "\n";
if (CombineInstances) {
for (auto FirstVar = Vars.begin(); FirstVar != Vars.end();
FirstVar = Range.second) {
Range = Vars.equal_range(FirstVar->first);
- VarCoverage CombinedCov = {{}, 0, 0};
+ VarCoverage CombinedCov = {{}, 0, 0, 0, 0, 0, false};
for (auto Var = Range.first; Var != Range.second; ++Var) {
++CombinedCov.Instances;
CombinedCov.Cov += Var->second.Cov;
+ CombinedCov.BaselineCov += Var->second.BaselineCov;
+ CombinedCov.LTCov += Var->second.LTCov;
+ CombinedCov.Missing += Var->second.Missing;
+ CombinedCov.MissingBaseline |= Var->second.MissingBaseline;
}
displayVariableCoverage(FirstVar->first, CombinedCov, true, OS);
}
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 26778f51e674a..88e5fb33471a6 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -338,6 +338,11 @@ static opt<bool>
ShowVariableCoverage("show-variable-coverage",
desc("Show per-variable coverage metrics."),
cat(DwarfDumpCategory));
+static opt<std::string>
+ CoverageBaseline("coverage-baseline",
+ desc("File to use as the baseline for variable coverage "
+ "statistics (implies --show-variable-coverage)"),
+ value_desc("filename"), cat(DwarfDumpCategory));
static opt<bool> CombineInstances(
"combine-inline-variable-instances",
desc(
@@ -915,7 +920,8 @@ int main(int argc, char **argv) {
DumpType |= DIDT_UUID;
if (DumpAll)
DumpType = DIDT_All;
- if (DumpType == DIDT_Null && !ShowVariableCoverage) {
+ if (DumpType == DIDT_Null && !ShowVariableCoverage &&
+ CoverageBaseline.empty()) {
if (Verbose || Verify)
DumpType = DIDT_All;
else
@@ -967,10 +973,25 @@ int main(int argc, char **argv) {
Success &= handleFile(Object, dumpObjectFile, OutputFile.os());
}
- if (ShowVariableCoverage) {
+ if (!CoverageBaseline.empty()) {
+ auto handleBaseline = [&](ObjectFile &BaselineObj,
+ DWARFContext &BaselineCtx, const Twine &Filename,
+ raw_ostream &OS) {
+ auto showCoverage = [&](ObjectFile &Obj, DWARFContext &DICtx,
+ const Twine &Filename, raw_ostream &OS) {
+ return showVariableCoverage(Obj, DICtx, &BaselineObj, &BaselineCtx,
+ CombineInstances, OS);
+ };
+ for (StringRef Object : Objects)
+ Success &= handleFile(Object, showCoverage, OutputFile.os());
+ return true;
+ };
+ Success &= handleFile(CoverageBaseline, handleBaseline, OutputFile.os());
+ } else if (ShowVariableCoverage) {
auto showCoverage = [&](ObjectFile &Obj, DWARFContext &DICtx,
const Twine &Filename, raw_ostream &OS) {
- return showVariableCoverage(Obj, DICtx, CombineInstances, OS);
+ return showVariableCoverage(Obj, DICtx, nullptr, nullptr,
+ CombineInstances, OS);
};
for (StringRef Object : Objects)
Success &= handleFile(Object, showCoverage, OutputFile.os());
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h
index ff6d91f12009e..90a49e8f75ffc 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h
@@ -40,7 +40,9 @@ bool collectObjectSectionSizes(object::ObjectFile &Obj, DWARFContext &DICtx,
const Twine &Filename, raw_ostream &OS);
bool showVariableCoverage(object::ObjectFile &Obj, DWARFContext &DICtx,
- bool CombineInstances, raw_ostream &OS);
+ object::ObjectFile *BaselineObj,
+ DWARFContext *BaselineCtx, bool CombineInstances,
+ raw_ostream &OS);
} // namespace dwarfdump
} // namespace llvm
>From ae6e7d038b75679a406f6e14233e038a422f18f0 Mon Sep 17 00:00:00 2001
From: unexpectedlydefined <unexpectedlydefined at gmail.com>
Date: Wed, 18 Mar 2026 14:38:12 +0000
Subject: [PATCH 2/7] fixup! Add coverage baseline comparison and line table
coverage in isolation
PR feedback
---
llvm/docs/CommandGuide/llvm-dwarfdump.rst | 13 ++--
.../tools/llvm-dwarfdump/X86/coverage.test | 2 +-
llvm/tools/llvm-dwarfdump/Coverage.cpp | 78 +++++++++++--------
3 files changed, 53 insertions(+), 40 deletions(-)
diff --git a/llvm/docs/CommandGuide/llvm-dwarfdump.rst b/llvm/docs/CommandGuide/llvm-dwarfdump.rst
index a9dab58fc37ab..03d3623259610 100644
--- a/llvm/docs/CommandGuide/llvm-dwarfdump.rst
+++ b/llvm/docs/CommandGuide/llvm-dwarfdump.rst
@@ -291,12 +291,13 @@ a tab-separated table containing the following columns:
- `CoveredRatio` (empty if :option:`--coverage-baseline` is not
specified) ==> Ratio of the coverage compared to the baseline
(calculated as `LinesCovered/Baseline`)
- - `LT` (empty if :option:`--coverage-baseline` is not specified) ==>
- Number of source lines covered in the variable's baseline debug
- information that are also present in the input file's line table
- - `LTRatio` (empty if :option:`--coverage-baseline` is not specified) ==>
- Ratio of the line table coverage compared to the baseline (calculated
- as `LT/Baseline`)
+ - `LinesPresent` (empty if :option:`--coverage-baseline` is not
+ specified) ==> Number of source lines covered in the variable's
+ baseline debug information that are also present in the input file's
+ line table
+ - `LinesPresentRatio` (empty if :option:`--coverage-baseline` is not
+ specified) ==> Ratio of the line table coverage compared to the
+ baseline (calculated as `LinesPresent/Baseline`)
EXIT STATUS
-----------
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/coverage.test b/llvm/test/tools/llvm-dwarfdump/X86/coverage.test
index 20cc6b8d38dac..647f277ae64e5 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/coverage.test
+++ b/llvm/test/tools/llvm-dwarfdump/X86/coverage.test
@@ -28,7 +28,7 @@ COMBINE-NEXT: fn1 1 y test.c:3 7
RUN: llvm-dwarfdump --show-variable-coverage --coverage-baseline=%t.o %t-opt.o | FileCheck %s --check-prefix=BASELINE
BASELINE: Variable coverage statistics:
-BASELINE-NEXT: Function InlChain Variable Decl LinesCovered Baseline CoveredRatio LT LTRatio
+BASELINE-NEXT: Function InlChain Variable Decl LinesCovered Baseline CoveredRatio LinesPresent LinesPresentRatio
BASELINE-NEXT: f k test.c:20 5 5 1 5 1
BASELINE-NEXT: f l test.c:20 5 5 1 5 1
BASELINE-NEXT: fn1 a test.c:11 5 14 0.357 7 0.5
diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp
index 1ca29319d9dec..2284742591f8b 100644
--- a/llvm/tools/llvm-dwarfdump/Coverage.cpp
+++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp
@@ -25,39 +25,37 @@
using namespace llvm;
using namespace llvm::dwarf;
-using namespace llvm::dwarfdump;
using namespace llvm::object;
/// Pair of file index and line number representing a source location.
typedef std::pair<uint16_t, size_t> SourceLocation;
-/// Returns the set of source lines covered by a variable's debug information,
-/// computed by intersecting the variable's location ranges and the containing
-/// scope's address ranges.
-static DenseSet<SourceLocation>
-computeVariableCoverage(DWARFContext &DICtx, DWARFDie VariableDIE,
- const DWARFDebugLine::LineTable *const LineTable,
- bool LTCov) {
- /// Adds source locations to the set that correspond to an address range.
- auto addLines = [](const DWARFDebugLine::LineTable *LineTable,
+/// Adds source locations to the line set that correspond to an address range.
+static void addLines(const DWARFDebugLine::LineTable *LineTable,
DenseSet<SourceLocation> &Lines, DWARFAddressRange Range) {
- std::vector<uint32_t> Rows;
- if (LineTable->lookupAddressRange({Range.LowPC, Range.SectionIndex},
- Range.HighPC - Range.LowPC, Rows)) {
- for (const auto &RowI : Rows) {
- const auto Row = LineTable->Rows[RowI];
- // Lookup can return addresses below the LowPC - filter these out.
- if (Row.Address.Address < Range.LowPC)
- continue;
- const auto FileIndex = Row.File;
+ std::vector<uint32_t> Rows;
+ if (LineTable->lookupAddressRange({Range.LowPC, Range.SectionIndex},
+ Range.HighPC - Range.LowPC, Rows)) {
+ for (const auto &RowI : Rows) {
+ const auto Row = LineTable->Rows[RowI];
+ // Lookup can return addresses below the LowPC - filter these out.
+ if (Row.Address.Address < Range.LowPC)
+ continue;
+ const auto FileIndex = Row.File;
- const auto Line = Row.Line;
- if (Line) // Ignore zero lines.
- Lines.insert({FileIndex, Line});
- }
+ const auto Line = Row.Line;
+ if (Line) // Ignore zero lines.
+ Lines.insert({FileIndex, Line});
}
- };
+ }
+}
+/// Returns the set of source lines covered by a variable's debug information,
+/// computed by intersecting the variable's location ranges and the containing
+/// scope's address ranges.
+static DenseSet<SourceLocation>
+computeVariableCoverage(DWARFDie VariableDIE,
+ const DWARFDebugLine::LineTable *const LineTable) {
// The optionals below will be empty if no address ranges were found, and
// present (but containing an empty set) if ranges were found but contained no
// source locations, in order to distinguish the two cases.
@@ -73,17 +71,15 @@ computeVariableCoverage(DWARFContext &DICtx, DWARFDie VariableDIE,
}
}
} else {
- consumeError(Locations.takeError());
// If the variable is optimized out and has no DW_AT_location, return an
// empty set instead of falling back to the parent scope's address ranges.
- if (!LTCov)
- return {};
+ consumeError(Locations.takeError());
+ return {};
}
// DW_AT_location attribute may contain overly broad address ranges, or none
// at all, so we also consider the parent scope's address ranges if present.
- auto ParentRanges = LTCov ? VariableDIE.getAddressRanges()
- : VariableDIE.getParent().getAddressRanges();
+ auto ParentRanges = VariableDIE.getParent().getAddressRanges();
std::optional<DenseSet<SourceLocation>> ParentLines;
if (ParentRanges) {
ParentLines = DenseSet<SourceLocation>();
@@ -101,6 +97,22 @@ computeVariableCoverage(DWARFContext &DICtx, DWARFDie VariableDIE,
return Lines.value_or(DenseSet<SourceLocation>());
}
+/// Returns the set of source lines present in the line table for a subroutine.
+static DenseSet<SourceLocation>
+computeSubroutineCoverage(DWARFDie SubroutineDIE,
+ const DWARFDebugLine::LineTable *const LineTable) {
+ auto Ranges = SubroutineDIE.getAddressRanges();
+ DenseSet<SourceLocation> Lines = DenseSet<SourceLocation>();
+ if (Ranges) {
+ for (const auto &R : Ranges.get())
+ addLines(LineTable, Lines, R);
+ } else {
+ consumeError(Ranges.takeError());
+ }
+
+ return Lines;
+}
+
static const SmallVector<DWARFDie> getParentSubroutines(DWARFDie DIE) {
SmallVector<DWARFDie> Parents;
DWARFDie Parent = DIE;
@@ -230,7 +242,7 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
if (!Key)
continue;
- const auto Cov = computeVariableCoverage(*BaselineCtx, Die, LT, false);
+ const auto Cov = computeVariableCoverage(Die, LT);
auto Result = BaselineVars.insert({*Key, Cov});
if (!Result.second)
@@ -257,7 +269,7 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
if (!Key)
continue;
- const auto Cov = computeVariableCoverage(DICtx, Die, LT, false);
+ const auto Cov = computeVariableCoverage(Die, LT);
VarCoverage VarCov = {Parents, Cov.size(), 0, 0, 0, 1, false};
@@ -271,7 +283,7 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
for (const auto &L : Cov)
VarCov.Missing += (1 - BCov.count(L));
- const auto LTCov = computeVariableCoverage(DICtx, Parent, LT, true);
+ const auto LTCov = computeSubroutineCoverage(Parent, LT);
for (const auto &L : BCov)
VarCov.LTCov += LTCov.count(L);
@@ -290,7 +302,7 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
<< (CombineInstances ? "InstanceCount" : "InlChain")
<< "\tVariable\tDecl\tLinesCovered";
if (BaselineCtx)
- OS << "\tBaseline\tCoveredRatio\tLT\tLTRatio";
+ OS << "\tBaseline\tCoveredRatio\tLinesPresent\tLinesPresentRatio";
OS << "\n";
if (CombineInstances) {
>From 4f5d4e3edf1df4843c55b12b09be542c87a308ed Mon Sep 17 00:00:00 2001
From: unexpectedlydefined <unexpectedlydefined at gmail.com>
Date: Wed, 18 Mar 2026 15:38:12 +0000
Subject: [PATCH 3/7] fixup! Add coverage baseline comparison and line table
coverage in isolation
PR feedback
---
llvm/tools/llvm-dwarfdump/Coverage.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp
index 2284742591f8b..3cc52f4ae5774 100644
--- a/llvm/tools/llvm-dwarfdump/Coverage.cpp
+++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp
@@ -102,7 +102,7 @@ static DenseSet<SourceLocation>
computeSubroutineCoverage(DWARFDie SubroutineDIE,
const DWARFDebugLine::LineTable *const LineTable) {
auto Ranges = SubroutineDIE.getAddressRanges();
- DenseSet<SourceLocation> Lines = DenseSet<SourceLocation>();
+ DenseSet<SourceLocation> Lines;
if (Ranges) {
for (const auto &R : Ranges.get())
addLines(LineTable, Lines, R);
>From aa97b8655bc67ac2432ccece6f29ee3d2027a360 Mon Sep 17 00:00:00 2001
From: unexpectedlydefined <unexpectedlydefined at gmail.com>
Date: Fri, 20 Mar 2026 17:25:08 +0000
Subject: [PATCH 4/7] fixup! Add coverage baseline comparison and line table
coverage in isolation
Use internal index for coverage baseline comparison
---
llvm/tools/llvm-dwarfdump/Coverage.cpp | 47 +++++++++++++++++++++++---
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp
index 3cc52f4ae5774..1e9cd153ba86b 100644
--- a/llvm/tools/llvm-dwarfdump/Coverage.cpp
+++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp
@@ -55,7 +55,9 @@ static void addLines(const DWARFDebugLine::LineTable *LineTable,
/// scope's address ranges.
static DenseSet<SourceLocation>
computeVariableCoverage(DWARFDie VariableDIE,
- const DWARFDebugLine::LineTable *const LineTable) {
+ const DWARFDebugLine::LineTable *const LineTable,
+ DenseMap<uint16_t, uint16_t> &FileIndexMap,
+ StringMap<uint16_t> &FileNameMap) {
// The optionals below will be empty if no address ranges were found, and
// present (but containing an empty set) if ranges were found but contained no
// source locations, in order to distinguish the two cases.
@@ -94,7 +96,39 @@ computeVariableCoverage(DWARFDie VariableDIE,
else if (ParentLines)
llvm::set_intersect(*Lines, *ParentLines);
- return Lines.value_or(DenseSet<SourceLocation>());
+ // The DWARF index of a file may differ across compilations, so use our own
+ // internal index instead.
+ DenseSet<SourceLocation> ResultLines;
+ if (Lines) {
+ for (const auto &L : *Lines) {
+ uint16_t Index;
+ const auto IndexIt = FileIndexMap.find(L.first);
+ if (IndexIt != FileIndexMap.end()) {
+ Index = IndexIt->second;
+ } else {
+ std::string Name;
+ assert(LineTable->getFileNameByIndex(
+ L.first, "",
+ DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath,
+ Name) &&
+ "File index should always be valid");
+
+ auto NameIt = FileNameMap.find(Name);
+ if (NameIt != FileNameMap.end()) {
+ Index = NameIt->second;
+ } else {
+ Index = FileNameMap.size();
+ FileNameMap.insert({Name, Index});
+ }
+
+ FileIndexMap.insert({L.first, Index});
+ }
+
+ ResultLines.insert({Index, L.second});
+ }
+ }
+
+ return ResultLines;
}
/// Returns the set of source lines present in the line table for a subroutine.
@@ -224,10 +258,12 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
DWARFContext *BaselineCtx,
bool CombineInstances, raw_ostream &OS) {
BaselineVarMap BaselineVars;
+ StringMap<uint16_t> FileNameMap;
if (BaselineCtx) {
for (const auto &U : BaselineCtx->info_section_units()) {
const auto *const LT = BaselineCtx->getLineTableForUnit(U.get());
+ DenseMap<uint16_t, uint16_t> FileIndexMap;
for (const auto &Entry : U->dies()) {
DWARFDie Die = {U.get(), &Entry};
if (Die.getTag() != DW_TAG_variable &&
@@ -242,7 +278,8 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
if (!Key)
continue;
- const auto Cov = computeVariableCoverage(Die, LT);
+ const auto Cov =
+ computeVariableCoverage(Die, LT, FileIndexMap, FileNameMap);
auto Result = BaselineVars.insert({*Key, Cov});
if (!Result.second)
@@ -255,6 +292,7 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
for (const auto &U : DICtx.info_section_units()) {
const auto *const LT = DICtx.getLineTableForUnit(U.get());
+ DenseMap<uint16_t, uint16_t> FileIndexMap;
for (const auto &Entry : U->dies()) {
DWARFDie Die = {U.get(), &Entry};
if (Die.getTag() != DW_TAG_variable &&
@@ -269,7 +307,8 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
if (!Key)
continue;
- const auto Cov = computeVariableCoverage(Die, LT);
+ const auto Cov =
+ computeVariableCoverage(Die, LT, FileIndexMap, FileNameMap);
VarCoverage VarCov = {Parents, Cov.size(), 0, 0, 0, 1, false};
>From fa4b5511246f7f541f5be864ac035029f652a639 Mon Sep 17 00:00:00 2001
From: unexpectedlydefined <unexpectedlydefined at gmail.com>
Date: Fri, 20 Mar 2026 19:06:58 +0000
Subject: [PATCH 5/7] fixup! Add coverage baseline comparison and line table
coverage in isolation
---
llvm/tools/llvm-dwarfdump/Coverage.cpp | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp
index 1e9cd153ba86b..17a534aaeaa3a 100644
--- a/llvm/tools/llvm-dwarfdump/Coverage.cpp
+++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp
@@ -107,11 +107,10 @@ computeVariableCoverage(DWARFDie VariableDIE,
Index = IndexIt->second;
} else {
std::string Name;
- assert(LineTable->getFileNameByIndex(
- L.first, "",
- DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath,
- Name) &&
- "File index should always be valid");
+ [[maybe_unused]] bool ValidIndex = LineTable->getFileNameByIndex(
+ L.first, "",
+ DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, Name);
+ assert(ValidIndex && "File index should always be valid");
auto NameIt = FileNameMap.find(Name);
if (NameIt != FileNameMap.end()) {
>From 815232a6d49bf49a6ae58dfb1870f8bf816f9400 Mon Sep 17 00:00:00 2001
From: unexpectedlydefined <unexpectedlydefined at gmail.com>
Date: Mon, 6 Apr 2026 16:05:34 +0100
Subject: [PATCH 6/7] fixup! Add coverage baseline comparison and line table
coverage in isolation
Exclude lines from inlined subroutines
---
llvm/tools/llvm-dwarfdump/Coverage.cpp | 175 +++++++++++++++----------
1 file changed, 108 insertions(+), 67 deletions(-)
diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp
index 17a534aaeaa3a..edc23c69ca0c8 100644
--- a/llvm/tools/llvm-dwarfdump/Coverage.cpp
+++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp
@@ -41,20 +41,56 @@ static void addLines(const DWARFDebugLine::LineTable *LineTable,
// Lookup can return addresses below the LowPC - filter these out.
if (Row.Address.Address < Range.LowPC)
continue;
- const auto FileIndex = Row.File;
- const auto Line = Row.Line;
- if (Line) // Ignore zero lines.
- Lines.insert({FileIndex, Line});
+ if (Row.Line) // Ignore zero lines.
+ Lines.insert({Row.File, Row.Line});
}
}
}
+// Converts the file index of each line in the set to use our own internal
+// file index. This is required for a reliable comparison as the DWARF index may
+// differ across compilations.
+static DenseSet<SourceLocation>
+convertFileIndices(DenseSet<SourceLocation> Lines,
+ const DWARFDebugLine::LineTable *const LineTable,
+ DenseMap<uint16_t, uint16_t> &FileIndexMap,
+ StringMap<uint16_t> &FileNameMap) {
+ DenseSet<SourceLocation> ResultLines;
+ for (const auto &L : Lines) {
+ uint16_t Index;
+ const auto IndexIt = FileIndexMap.find(L.first);
+ if (IndexIt != FileIndexMap.end()) {
+ Index = IndexIt->second;
+ } else {
+ std::string Name;
+ [[maybe_unused]] bool ValidIndex = LineTable->getFileNameByIndex(
+ L.first, "", DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath,
+ Name);
+ assert(ValidIndex && "File index should always be valid");
+
+ auto NameIt = FileNameMap.find(Name);
+ if (NameIt != FileNameMap.end()) {
+ Index = NameIt->second;
+ } else {
+ Index = FileNameMap.size();
+ FileNameMap.insert({Name, Index});
+ }
+
+ FileIndexMap.insert({L.first, Index});
+ }
+
+ ResultLines.insert({Index, L.second});
+ }
+
+ return ResultLines;
+}
+
/// Returns the set of source lines covered by a variable's debug information,
/// computed by intersecting the variable's location ranges and the containing
/// scope's address ranges.
static DenseSet<SourceLocation>
-computeVariableCoverage(DWARFDie VariableDIE,
+computeVariableCoverage(DWARFDie VariableDie,
const DWARFDebugLine::LineTable *const LineTable,
DenseMap<uint16_t, uint16_t> &FileIndexMap,
StringMap<uint16_t> &FileNameMap) {
@@ -62,7 +98,7 @@ computeVariableCoverage(DWARFDie VariableDIE,
// present (but containing an empty set) if ranges were found but contained no
// source locations, in order to distinguish the two cases.
- auto Locations = VariableDIE.getLocations(DW_AT_location);
+ auto Locations = VariableDie.getLocations(DW_AT_location);
std::optional<DenseSet<SourceLocation>> Lines;
if (Locations) {
for (const auto &L : Locations.get()) {
@@ -81,7 +117,7 @@ computeVariableCoverage(DWARFDie VariableDIE,
// DW_AT_location attribute may contain overly broad address ranges, or none
// at all, so we also consider the parent scope's address ranges if present.
- auto ParentRanges = VariableDIE.getParent().getAddressRanges();
+ auto ParentRanges = VariableDie.getParent().getAddressRanges();
std::optional<DenseSet<SourceLocation>> ParentLines;
if (ParentRanges) {
ParentLines = DenseSet<SourceLocation>();
@@ -96,45 +132,38 @@ computeVariableCoverage(DWARFDie VariableDIE,
else if (ParentLines)
llvm::set_intersect(*Lines, *ParentLines);
- // The DWARF index of a file may differ across compilations, so use our own
- // internal index instead.
- DenseSet<SourceLocation> ResultLines;
- if (Lines) {
- for (const auto &L : *Lines) {
- uint16_t Index;
- const auto IndexIt = FileIndexMap.find(L.first);
- if (IndexIt != FileIndexMap.end()) {
- Index = IndexIt->second;
- } else {
- std::string Name;
- [[maybe_unused]] bool ValidIndex = LineTable->getFileNameByIndex(
- L.first, "",
- DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, Name);
- assert(ValidIndex && "File index should always be valid");
-
- auto NameIt = FileNameMap.find(Name);
- if (NameIt != FileNameMap.end()) {
- Index = NameIt->second;
- } else {
- Index = FileNameMap.size();
- FileNameMap.insert({Name, Index});
- }
+ if (!Lines)
+ return {};
- FileIndexMap.insert({L.first, Index});
- }
+ return convertFileIndices(Lines.value_or(DenseSet<SourceLocation>()),
+ LineTable, FileIndexMap, FileNameMap);
+}
- ResultLines.insert({Index, L.second});
+/// Adds source locations to the line set that are within an inlined subroutine.
+static void getInlinedLines(DWARFDie Die, DenseSet<SourceLocation> &Lines,
+ const DWARFDebugLine::LineTable *const LineTable) {
+ for (const auto &ChildDie : Die.children()) {
+ if (ChildDie.getTag() == DW_TAG_inlined_subroutine) {
+ auto Ranges = ChildDie.getAddressRanges();
+ if (Ranges) {
+ for (const auto &R : Ranges.get())
+ addLines(LineTable, Lines, R);
+ } else {
+ consumeError(Ranges.takeError());
+ }
+ } else {
+ getInlinedLines(ChildDie, Lines, LineTable);
}
}
-
- return ResultLines;
}
/// Returns the set of source lines present in the line table for a subroutine.
static DenseSet<SourceLocation>
-computeSubroutineCoverage(DWARFDie SubroutineDIE,
- const DWARFDebugLine::LineTable *const LineTable) {
- auto Ranges = SubroutineDIE.getAddressRanges();
+computeSubroutineCoverage(DWARFDie SubroutineDie,
+ const DWARFDebugLine::LineTable *const LineTable,
+ DenseMap<uint16_t, uint16_t> &FileIndexMap,
+ StringMap<uint16_t> &FileNameMap) {
+ auto Ranges = SubroutineDie.getAddressRanges();
DenseSet<SourceLocation> Lines;
if (Ranges) {
for (const auto &R : Ranges.get())
@@ -143,12 +172,17 @@ computeSubroutineCoverage(DWARFDie SubroutineDIE,
consumeError(Ranges.takeError());
}
- return Lines;
+ // Exclude lines from any subroutines inlined into this one.
+ DenseSet<SourceLocation> InlinedLines;
+ getInlinedLines(SubroutineDie, InlinedLines, LineTable);
+ llvm::set_subtract(Lines, InlinedLines);
+
+ return convertFileIndices(Lines, LineTable, FileIndexMap, FileNameMap);
}
-static const SmallVector<DWARFDie> getParentSubroutines(DWARFDie DIE) {
+static const SmallVector<DWARFDie> getParentSubroutines(DWARFDie Die) {
SmallVector<DWARFDie> Parents;
- DWARFDie Parent = DIE;
+ DWARFDie Parent = Die;
do {
if (Parent.getTag() == DW_TAG_subprogram) {
Parents.push_back(Parent);
@@ -199,14 +233,17 @@ struct VarCoverage {
typedef std::multimap<VarKey, VarCoverage, std::less<>> VarMap;
typedef std::map<VarKey, DenseSet<SourceLocation>, std::less<>> BaselineVarMap;
-static std::optional<const VarKey> getVarKey(DWARFDie Die, DWARFDie Parent) {
- const auto *const DieName = Die.getName(DINameKind::LinkageName);
- const auto DieFile =
- Die.getDeclFile(DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath);
- const auto *const ParentName = Parent.getName(DINameKind::LinkageName);
- if (!DieName || !ParentName)
+static std::optional<const VarKey> getVarKey(DWARFDie VariableDie,
+ DWARFDie SubroutineDie) {
+ const auto *const VariableName = VariableDie.getName(DINameKind::LinkageName);
+ const auto DieFile = VariableDie.getDeclFile(
+ DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath);
+ const auto *const SubroutineName =
+ SubroutineDie.getName(DINameKind::LinkageName);
+ if (!VariableName || !SubroutineName)
return std::nullopt;
- return VarKey{ParentName, DieName, DieFile, Die.getDeclLine()};
+ return VarKey{SubroutineName, VariableName, DieFile,
+ VariableDie.getDeclLine()};
}
static void displayParents(SmallVector<DWARFDie> Parents, raw_ostream &OS) {
@@ -264,21 +301,24 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
const auto *const LT = BaselineCtx->getLineTableForUnit(U.get());
DenseMap<uint16_t, uint16_t> FileIndexMap;
for (const auto &Entry : U->dies()) {
- DWARFDie Die = {U.get(), &Entry};
- if (Die.getTag() != DW_TAG_variable &&
- Die.getTag() != DW_TAG_formal_parameter)
+ DWARFDie VariableDie = {U.get(), &Entry};
+ if (VariableDie.getTag() != DW_TAG_variable &&
+ VariableDie.getTag() != DW_TAG_formal_parameter)
continue;
- const auto Parents = getParentSubroutines(Die);
+ const auto Parents = getParentSubroutines(VariableDie);
if (!Parents.size())
continue;
- const auto Parent = Parents.front();
- auto Key = getVarKey(Die, Parent);
+ const auto SubroutineDie = Parents.front();
+ auto Key = getVarKey(VariableDie, SubroutineDie);
if (!Key)
continue;
- const auto Cov =
- computeVariableCoverage(Die, LT, FileIndexMap, FileNameMap);
+ auto Cov =
+ computeVariableCoverage(VariableDie, LT, FileIndexMap, FileNameMap);
+ const auto SubroutineCov = computeSubroutineCoverage(
+ SubroutineDie, LT, FileIndexMap, FileNameMap);
+ llvm::set_intersect(Cov, SubroutineCov);
auto Result = BaselineVars.insert({*Key, Cov});
if (!Result.second)
@@ -293,21 +333,24 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
const auto *const LT = DICtx.getLineTableForUnit(U.get());
DenseMap<uint16_t, uint16_t> FileIndexMap;
for (const auto &Entry : U->dies()) {
- DWARFDie Die = {U.get(), &Entry};
- if (Die.getTag() != DW_TAG_variable &&
- Die.getTag() != DW_TAG_formal_parameter)
+ DWARFDie VariableDie = {U.get(), &Entry};
+ if (VariableDie.getTag() != DW_TAG_variable &&
+ VariableDie.getTag() != DW_TAG_formal_parameter)
continue;
- const auto Parents = getParentSubroutines(Die);
+ const auto Parents = getParentSubroutines(VariableDie);
if (!Parents.size())
continue;
- const auto Parent = Parents.front();
- auto Key = getVarKey(Die, Parent);
+ const auto SubroutineDie = Parents.front();
+ auto Key = getVarKey(VariableDie, SubroutineDie);
if (!Key)
continue;
- const auto Cov =
- computeVariableCoverage(Die, LT, FileIndexMap, FileNameMap);
+ auto Cov =
+ computeVariableCoverage(VariableDie, LT, FileIndexMap, FileNameMap);
+ const auto SubroutineCov = computeSubroutineCoverage(
+ SubroutineDie, LT, FileIndexMap, FileNameMap);
+ llvm::set_intersect(Cov, SubroutineCov);
VarCoverage VarCov = {Parents, Cov.size(), 0, 0, 0, 1, false};
@@ -321,10 +364,8 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
for (const auto &L : Cov)
VarCov.Missing += (1 - BCov.count(L));
- const auto LTCov = computeSubroutineCoverage(Parent, LT);
-
for (const auto &L : BCov)
- VarCov.LTCov += LTCov.count(L);
+ VarCov.LTCov += SubroutineCov.count(L);
} else {
VarCov.MissingBaseline = true;
}
>From aa4c9451694a4b9d80755c2d4eaef5588a2f03cb Mon Sep 17 00:00:00 2001
From: unexpectedlydefined <unexpectedlydefined at gmail.com>
Date: Tue, 7 Apr 2026 15:06:40 +0100
Subject: [PATCH 7/7] fixup! Add coverage baseline comparison and line table
coverage in isolation
PR feedback
---
llvm/tools/llvm-dwarfdump/Coverage.cpp | 87 +++++++++++++-------------
1 file changed, 45 insertions(+), 42 deletions(-)
diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp
index edc23c69ca0c8..b6a68b0af0d75 100644
--- a/llvm/tools/llvm-dwarfdump/Coverage.cpp
+++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp
@@ -67,7 +67,7 @@ convertFileIndices(DenseSet<SourceLocation> Lines,
[[maybe_unused]] bool ValidIndex = LineTable->getFileNameByIndex(
L.first, "", DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath,
Name);
- assert(ValidIndex && "File index should always be valid");
+ assert(ValidIndex && "File index was not valid for its own line table");
auto NameIt = FileNameMap.find(Name);
if (NameIt != FileNameMap.end()) {
@@ -90,7 +90,7 @@ convertFileIndices(DenseSet<SourceLocation> Lines,
/// computed by intersecting the variable's location ranges and the containing
/// scope's address ranges.
static DenseSet<SourceLocation>
-computeVariableCoverage(DWARFDie VariableDie,
+computeVariableCoverage(DWARFDie VariableDIE,
const DWARFDebugLine::LineTable *const LineTable,
DenseMap<uint16_t, uint16_t> &FileIndexMap,
StringMap<uint16_t> &FileNameMap) {
@@ -98,7 +98,7 @@ computeVariableCoverage(DWARFDie VariableDie,
// present (but containing an empty set) if ranges were found but contained no
// source locations, in order to distinguish the two cases.
- auto Locations = VariableDie.getLocations(DW_AT_location);
+ auto Locations = VariableDIE.getLocations(DW_AT_location);
std::optional<DenseSet<SourceLocation>> Lines;
if (Locations) {
for (const auto &L : Locations.get()) {
@@ -117,7 +117,7 @@ computeVariableCoverage(DWARFDie VariableDie,
// DW_AT_location attribute may contain overly broad address ranges, or none
// at all, so we also consider the parent scope's address ranges if present.
- auto ParentRanges = VariableDie.getParent().getAddressRanges();
+ auto ParentRanges = VariableDIE.getParent().getAddressRanges();
std::optional<DenseSet<SourceLocation>> ParentLines;
if (ParentRanges) {
ParentLines = DenseSet<SourceLocation>();
@@ -130,7 +130,7 @@ computeVariableCoverage(DWARFDie VariableDie,
if (!Lines && ParentLines)
Lines = ParentLines;
else if (ParentLines)
- llvm::set_intersect(*Lines, *ParentLines);
+ set_intersect(*Lines, *ParentLines);
if (!Lines)
return {};
@@ -140,11 +140,12 @@ computeVariableCoverage(DWARFDie VariableDie,
}
/// Adds source locations to the line set that are within an inlined subroutine.
-static void getInlinedLines(DWARFDie Die, DenseSet<SourceLocation> &Lines,
+static void getInlinedLines(DWARFDie SubroutineDIE,
+ DenseSet<SourceLocation> &Lines,
const DWARFDebugLine::LineTable *const LineTable) {
- for (const auto &ChildDie : Die.children()) {
- if (ChildDie.getTag() == DW_TAG_inlined_subroutine) {
- auto Ranges = ChildDie.getAddressRanges();
+ for (const auto &ChildDIE : SubroutineDIE.children()) {
+ if (ChildDIE.getTag() == DW_TAG_inlined_subroutine) {
+ auto Ranges = ChildDIE.getAddressRanges();
if (Ranges) {
for (const auto &R : Ranges.get())
addLines(LineTable, Lines, R);
@@ -152,18 +153,18 @@ static void getInlinedLines(DWARFDie Die, DenseSet<SourceLocation> &Lines,
consumeError(Ranges.takeError());
}
} else {
- getInlinedLines(ChildDie, Lines, LineTable);
+ getInlinedLines(ChildDIE, Lines, LineTable);
}
}
}
/// Returns the set of source lines present in the line table for a subroutine.
static DenseSet<SourceLocation>
-computeSubroutineCoverage(DWARFDie SubroutineDie,
+computeSubroutineCoverage(DWARFDie SubroutineDIE,
const DWARFDebugLine::LineTable *const LineTable,
DenseMap<uint16_t, uint16_t> &FileIndexMap,
StringMap<uint16_t> &FileNameMap) {
- auto Ranges = SubroutineDie.getAddressRanges();
+ auto Ranges = SubroutineDIE.getAddressRanges();
DenseSet<SourceLocation> Lines;
if (Ranges) {
for (const auto &R : Ranges.get())
@@ -174,15 +175,15 @@ computeSubroutineCoverage(DWARFDie SubroutineDie,
// Exclude lines from any subroutines inlined into this one.
DenseSet<SourceLocation> InlinedLines;
- getInlinedLines(SubroutineDie, InlinedLines, LineTable);
- llvm::set_subtract(Lines, InlinedLines);
+ getInlinedLines(SubroutineDIE, InlinedLines, LineTable);
+ set_subtract(Lines, InlinedLines);
return convertFileIndices(Lines, LineTable, FileIndexMap, FileNameMap);
}
-static const SmallVector<DWARFDie> getParentSubroutines(DWARFDie Die) {
+static const SmallVector<DWARFDie> getParentSubroutines(DWARFDie DIE) {
SmallVector<DWARFDie> Parents;
- DWARFDie Parent = Die;
+ DWARFDie Parent = DIE;
do {
if (Parent.getTag() == DW_TAG_subprogram) {
Parents.push_back(Parent);
@@ -233,17 +234,17 @@ struct VarCoverage {
typedef std::multimap<VarKey, VarCoverage, std::less<>> VarMap;
typedef std::map<VarKey, DenseSet<SourceLocation>, std::less<>> BaselineVarMap;
-static std::optional<const VarKey> getVarKey(DWARFDie VariableDie,
- DWARFDie SubroutineDie) {
- const auto *const VariableName = VariableDie.getName(DINameKind::LinkageName);
- const auto DieFile = VariableDie.getDeclFile(
+static std::optional<const VarKey> getVarKey(DWARFDie VariableDIE,
+ DWARFDie SubroutineDIE) {
+ const auto *const VariableName = VariableDIE.getName(DINameKind::LinkageName);
+ const auto DeclFile = VariableDIE.getDeclFile(
DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath);
const auto *const SubroutineName =
- SubroutineDie.getName(DINameKind::LinkageName);
+ SubroutineDIE.getName(DINameKind::LinkageName);
if (!VariableName || !SubroutineName)
return std::nullopt;
- return VarKey{SubroutineName, VariableName, DieFile,
- VariableDie.getDeclLine()};
+ return VarKey{SubroutineName, VariableName, DeclFile,
+ VariableDIE.getDeclLine()};
}
static void displayParents(SmallVector<DWARFDie> Parents, raw_ostream &OS) {
@@ -273,7 +274,9 @@ static void displayVariableCoverage(const VarKey &Key, const VarCoverage &Var,
displayParents(Var.Parents, OS);
OS << "\t";
WithColor(OS, HighlightColor::String) << Key.Name;
- OS << "\t" << Key.DeclFile << ":" << Key.DeclLine;
+ OS << "\t";
+ if (!Key.DeclFile.empty())
+ OS << Key.DeclFile << ":" << Key.DeclLine;
OS << "\t" << format("%.3g", ((float)Var.Cov / Var.Instances));
if (Var.BaselineCov)
OS << "\t" << format("%.3g", ((float)Var.BaselineCov / Var.Instances))
@@ -301,24 +304,24 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
const auto *const LT = BaselineCtx->getLineTableForUnit(U.get());
DenseMap<uint16_t, uint16_t> FileIndexMap;
for (const auto &Entry : U->dies()) {
- DWARFDie VariableDie = {U.get(), &Entry};
- if (VariableDie.getTag() != DW_TAG_variable &&
- VariableDie.getTag() != DW_TAG_formal_parameter)
+ DWARFDie VariableDIE = {U.get(), &Entry};
+ if (VariableDIE.getTag() != DW_TAG_variable &&
+ VariableDIE.getTag() != DW_TAG_formal_parameter)
continue;
- const auto Parents = getParentSubroutines(VariableDie);
+ const auto Parents = getParentSubroutines(VariableDIE);
if (!Parents.size())
continue;
- const auto SubroutineDie = Parents.front();
- auto Key = getVarKey(VariableDie, SubroutineDie);
+ const auto SubroutineDIE = Parents.front();
+ auto Key = getVarKey(VariableDIE, SubroutineDIE);
if (!Key)
continue;
auto Cov =
- computeVariableCoverage(VariableDie, LT, FileIndexMap, FileNameMap);
+ computeVariableCoverage(VariableDIE, LT, FileIndexMap, FileNameMap);
const auto SubroutineCov = computeSubroutineCoverage(
- SubroutineDie, LT, FileIndexMap, FileNameMap);
- llvm::set_intersect(Cov, SubroutineCov);
+ SubroutineDIE, LT, FileIndexMap, FileNameMap);
+ set_intersect(Cov, SubroutineCov);
auto Result = BaselineVars.insert({*Key, Cov});
if (!Result.second)
@@ -333,24 +336,24 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
const auto *const LT = DICtx.getLineTableForUnit(U.get());
DenseMap<uint16_t, uint16_t> FileIndexMap;
for (const auto &Entry : U->dies()) {
- DWARFDie VariableDie = {U.get(), &Entry};
- if (VariableDie.getTag() != DW_TAG_variable &&
- VariableDie.getTag() != DW_TAG_formal_parameter)
+ DWARFDie VariableDIE = {U.get(), &Entry};
+ if (VariableDIE.getTag() != DW_TAG_variable &&
+ VariableDIE.getTag() != DW_TAG_formal_parameter)
continue;
- const auto Parents = getParentSubroutines(VariableDie);
+ const auto Parents = getParentSubroutines(VariableDIE);
if (!Parents.size())
continue;
- const auto SubroutineDie = Parents.front();
- auto Key = getVarKey(VariableDie, SubroutineDie);
+ const auto SubroutineDIE = Parents.front();
+ auto Key = getVarKey(VariableDIE, SubroutineDIE);
if (!Key)
continue;
auto Cov =
- computeVariableCoverage(VariableDie, LT, FileIndexMap, FileNameMap);
+ computeVariableCoverage(VariableDIE, LT, FileIndexMap, FileNameMap);
const auto SubroutineCov = computeSubroutineCoverage(
- SubroutineDie, LT, FileIndexMap, FileNameMap);
- llvm::set_intersect(Cov, SubroutineCov);
+ SubroutineDIE, LT, FileIndexMap, FileNameMap);
+ set_intersect(Cov, SubroutineCov);
VarCoverage VarCov = {Parents, Cov.size(), 0, 0, 0, 1, false};
More information about the llvm-commits
mailing list