[llvm] r315789 - [llvm-cov] Factor out logic to iterate over line coverage stats (NFC)

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 13 19:27:29 PDT 2017


Author: vedantk
Date: Fri Oct 13 19:27:29 2017
New Revision: 315789

URL: http://llvm.org/viewvc/llvm-project?rev=315789&view=rev
Log:
[llvm-cov] Factor out logic to iterate over line coverage stats (NFC)

There were two copies of the logic needed to construct a line stats
object for each line in a range: this patch brings it down to one. In
the future, this will make it easier for IDE clients to display coverage
in-line in source editors. To do that, we just need to move the new
LineCoverageIterator class to libCoverage.

Modified:
    llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.cpp
    llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.h
    llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
    llvm/trunk/tools/llvm-cov/SourceCoverageViewHTML.cpp
    llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp

Modified: llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.cpp?rev=315789&r1=315788&r2=315789&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.cpp (original)
+++ llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.cpp Fri Oct 13 19:27:29 2017
@@ -19,7 +19,9 @@ using namespace coverage;
 
 LineCoverageStats::LineCoverageStats(
     ArrayRef<const coverage::CoverageSegment *> LineSegments,
-    const coverage::CoverageSegment *WrappedSegment) {
+    const coverage::CoverageSegment *WrappedSegment, unsigned Line)
+    : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
+      LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
   // Find the minimum number of regions which start in this line.
   unsigned MinRegionCount = 0;
   auto isStartOfRegion = [](const coverage::CoverageSegment *S) {
@@ -33,7 +35,6 @@ LineCoverageStats::LineCoverageStats(
                               !LineSegments.front()->HasCount &&
                               LineSegments.front()->IsRegionEntry;
 
-  ExecutionCount = 0;
   HasMultipleRegions = MinRegionCount > 1;
   Mapped =
       !StartOfSkippedRegion &&
@@ -61,6 +62,22 @@ LineCoverageStats::LineCoverageStats(
     ExecutionCount = WrappedSegment->Count;
 }
 
+LineCoverageIterator &LineCoverageIterator::operator++() {
+  if (Next == CD.end()) {
+    Stats = LineCoverageStats();
+    Ended = true;
+    return *this;
+  }
+  if (Segments.size())
+    WrappedSegment = Segments.back();
+  Segments.clear();
+  while (Next != CD.end() && Next->Line == Line)
+    Segments.push_back(&*Next++);
+  Stats = LineCoverageStats(Segments, WrappedSegment, Line);
+  ++Line;
+  return *this;
+}
+
 FunctionCoverageSummary
 FunctionCoverageSummary::get(const CoverageMapping &CM,
                              const coverage::FunctionRecord &Function) {
@@ -77,27 +94,12 @@ FunctionCoverageSummary::get(const Cover
   // Compute the line coverage
   size_t NumLines = 0, CoveredLines = 0;
   CoverageData CD = CM.getCoverageForFunction(Function);
-  auto NextSegment = CD.begin();
-  auto EndSegment = CD.end();
-  const coverage::CoverageSegment *WrappedSegment = nullptr;
-  SmallVector<const coverage::CoverageSegment *, 4> LineSegments;
-  unsigned Line = NextSegment->Line;
-  while (NextSegment != EndSegment) {
-    // Gather the segments on this line and the wrapped segment.
-    if (LineSegments.size())
-      WrappedSegment = LineSegments.back();
-    LineSegments.clear();
-    while (NextSegment != EndSegment && NextSegment->Line == Line)
-      LineSegments.push_back(&*NextSegment++);
-
-    LineCoverageStats LCS{LineSegments, WrappedSegment};
-    if (LCS.isMapped()) {
-      ++NumLines;
-      if (LCS.ExecutionCount)
-        ++CoveredLines;
-    }
-
-    ++Line;
+  for (const auto &LCS : getLineCoverageStats(CD)) {
+    if (!LCS.isMapped())
+      continue;
+    ++NumLines;
+    if (LCS.getExecutionCount())
+      ++CoveredLines;
   }
 
   return FunctionCoverageSummary(

Modified: llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.h?rev=315789&r1=315788&r2=315789&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.h (original)
+++ llvm/trunk/tools/llvm-cov/CoverageSummaryInfo.h Fri Oct 13 19:27:29 2017
@@ -15,6 +15,8 @@
 #ifndef LLVM_COV_COVERAGESUMMARYINFO_H
 #define LLVM_COV_COVERAGESUMMARYINFO_H
 
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -137,19 +139,92 @@ public:
 };
 
 /// \brief Coverage statistics for a single line.
-struct LineCoverageStats {
+class LineCoverageStats {
   uint64_t ExecutionCount;
   bool HasMultipleRegions;
   bool Mapped;
+  unsigned Line;
+  ArrayRef<const coverage::CoverageSegment *> LineSegments;
+  const coverage::CoverageSegment *WrappedSegment;
 
+  friend class LineCoverageIterator;
+  LineCoverageStats() = default;
+
+public:
   LineCoverageStats(ArrayRef<const coverage::CoverageSegment *> LineSegments,
-                    const coverage::CoverageSegment *WrappedSegment);
+                    const coverage::CoverageSegment *WrappedSegment,
+                    unsigned Line);
 
-  bool isMapped() const { return Mapped; }
+  uint64_t getExecutionCount() const { return ExecutionCount; }
 
   bool hasMultipleRegions() const { return HasMultipleRegions; }
+
+  bool isMapped() const { return Mapped; }
+
+  unsigned getLine() const { return Line; }
+
+  ArrayRef<const coverage::CoverageSegment *> getLineSegments() const {
+    return LineSegments;
+  }
+
+  const coverage::CoverageSegment *getWrappedSegment() const {
+    return WrappedSegment;
+  }
 };
 
+/// Iterates over LineCoverageStats for each line described by a CoverageData
+/// object.
+class LineCoverageIterator
+    : public iterator_facade_base<
+          LineCoverageIterator, std::forward_iterator_tag, LineCoverageStats> {
+public:
+  LineCoverageIterator(const coverage::CoverageData &CD)
+      : LineCoverageIterator(CD, CD.begin()->Line) {}
+
+  LineCoverageIterator(const coverage::CoverageData &CD, unsigned Line)
+      : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false),
+        Line(Line), Segments(), Stats() {
+    this->operator++();
+  }
+
+  LineCoverageIterator &operator=(const LineCoverageIterator &R) = default;
+
+  bool operator==(const LineCoverageIterator &R) const {
+    return &CD == &R.CD && Next == R.Next && Ended == R.Ended;
+  }
+
+  const LineCoverageStats &operator*() const { return Stats; }
+
+  LineCoverageStats &operator*() { return Stats; }
+
+  LineCoverageIterator &operator++();
+
+  LineCoverageIterator getEnd() const {
+    auto EndIt = *this;
+    EndIt.Next = CD.end();
+    EndIt.Ended = true;
+    return EndIt;
+  }
+
+private:
+  const coverage::CoverageData &CD;
+  const coverage::CoverageSegment *WrappedSegment;
+  std::vector<coverage::CoverageSegment>::const_iterator Next;
+  bool Ended;
+  unsigned Line;
+  SmallVector<const coverage::CoverageSegment *, 4> Segments;
+  LineCoverageStats Stats;
+};
+
+/// Get a range of LineCoverageStats for each line described by a CoverageData
+/// object.
+static inline iterator_range<LineCoverageIterator>
+getLineCoverageStats(const coverage::CoverageData &CD) {
+  auto Begin = LineCoverageIterator(CD);
+  auto End = Begin.getEnd();
+  return make_range(Begin, End);
+}
+
 /// \brief A summary of function's code coverage.
 struct FunctionCoverageSummary {
   std::string Name;

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp?rev=315789&r1=315788&r2=315789&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp Fri Oct 13 19:27:29 2017
@@ -187,36 +187,29 @@ void SourceCoverageView::print(raw_ostre
   auto EndISV = InstantiationSubViews.end();
 
   // Get the coverage information for the file.
-  auto NextSegment = CoverageInfo.begin();
+  auto StartSegment = CoverageInfo.begin();
   auto EndSegment = CoverageInfo.end();
+  LineCoverageIterator LCI{CoverageInfo, 1};
+  LineCoverageIterator LCIEnd = LCI.getEnd();
 
-  unsigned FirstLine = NextSegment != EndSegment ? NextSegment->Line : 0;
-  const coverage::CoverageSegment *WrappedSegment = nullptr;
-  SmallVector<const coverage::CoverageSegment *, 8> LineSegments;
-  for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI) {
+  unsigned FirstLine = StartSegment != EndSegment ? StartSegment->Line : 0;
+  for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof();
+       ++LI, ++LCI) {
     // If we aren't rendering the whole file, we need to filter out the prologue
     // and epilogue.
     if (!WholeFile) {
-      if (NextSegment == EndSegment)
+      if (LCI == LCIEnd)
         break;
       else if (LI.line_number() < FirstLine)
         continue;
     }
 
-    // Collect the coverage information relevant to this line.
-    if (LineSegments.size())
-      WrappedSegment = LineSegments.back();
-    LineSegments.clear();
-    while (NextSegment != EndSegment && NextSegment->Line == LI.line_number())
-      LineSegments.push_back(&*NextSegment++);
-
     renderLinePrefix(OS, ViewDepth);
     if (getOptions().ShowLineNumbers)
       renderLineNumberColumn(OS, LI.line_number());
 
-    LineCoverageStats LineCount{LineSegments, WrappedSegment};
     if (getOptions().ShowLineStats)
-      renderLineCoverageColumn(OS, LineCount);
+      renderLineCoverageColumn(OS, *LCI);
 
     // If there are expansion subviews, we want to highlight the first one.
     unsigned ExpansionColumn = 0;
@@ -225,12 +218,12 @@ void SourceCoverageView::print(raw_ostre
       ExpansionColumn = NextESV->getStartCol();
 
     // Display the source code for the current line.
-    renderLine(OS, {*LI, LI.line_number()}, WrappedSegment, LineSegments,
-               ExpansionColumn, ViewDepth);
+    renderLine(OS, {*LI, LI.line_number()}, LCI->getWrappedSegment(),
+               LCI->getLineSegments(), ExpansionColumn, ViewDepth);
 
     // Show the region markers.
-    if (shouldRenderRegionMarkers(LineSegments))
-      renderRegionMarkers(OS, LineSegments, ViewDepth);
+    if (shouldRenderRegionMarkers(LCI->getLineSegments()))
+      renderRegionMarkers(OS, LCI->getLineSegments(), ViewDepth);
 
     // Show the expansions and instantiations for this line.
     bool RenderedSubView = false;
@@ -242,8 +235,9 @@ void SourceCoverageView::print(raw_ostre
       // this subview.
       if (RenderedSubView) {
         ExpansionColumn = NextESV->getStartCol();
-        renderExpansionSite(OS, {*LI, LI.line_number()}, WrappedSegment,
-                            LineSegments, ExpansionColumn, ViewDepth);
+        renderExpansionSite(OS, {*LI, LI.line_number()},
+                            LCI->getWrappedSegment(), LCI->getLineSegments(),
+                            ExpansionColumn, ViewDepth);
         renderViewDivider(OS, ViewDepth + 1);
       }
 

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageViewHTML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageViewHTML.cpp?rev=315789&r1=315788&r2=315789&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageViewHTML.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageViewHTML.cpp Fri Oct 13 19:27:29 2017
@@ -589,9 +589,9 @@ void SourceCoverageViewHTML::renderLineC
     raw_ostream &OS, const LineCoverageStats &Line) {
   std::string Count = "";
   if (Line.isMapped())
-    Count = tag("pre", formatCount(Line.ExecutionCount));
+    Count = tag("pre", formatCount(Line.getExecutionCount()));
   std::string CoverageClass =
-      (Line.ExecutionCount > 0) ? "covered-line" : "uncovered-line";
+      (Line.getExecutionCount() > 0) ? "covered-line" : "uncovered-line";
   OS << tag("td", Count, CoverageClass);
 }
 

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp?rev=315789&r1=315788&r2=315789&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp Fri Oct 13 19:27:29 2017
@@ -148,7 +148,7 @@ void SourceCoverageViewText::renderLineC
     OS.indent(LineCoverageColumnWidth) << '|';
     return;
   }
-  std::string C = formatCount(Line.ExecutionCount);
+  std::string C = formatCount(Line.getExecutionCount());
   OS.indent(LineCoverageColumnWidth - C.size());
   colored_ostream(OS, raw_ostream::MAGENTA,
                   Line.hasMultipleRegions() && getOptions().Colors)




More information about the llvm-commits mailing list