[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