blob: 6a4cbd0c18540ee5454885fa1de82e1870f3cf25 [file] [log] [blame]
Alex Lorenze82d89c2014-08-22 22:56:03 +00001//===- CoverageSummaryInfo.cpp - Coverage summary for function/file -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These structures are used to represent code coverage metrics
11// for functions/files.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CoverageSummaryInfo.h"
16
17using namespace llvm;
18using namespace coverage;
19
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000020LineCoverageStats::LineCoverageStats(
21 ArrayRef<const coverage::CoverageSegment *> LineSegments,
22 const coverage::CoverageSegment *WrappedSegment) {
23 // Find the minimum number of regions which start in this line.
24 unsigned MinRegionCount = 0;
25 auto isStartOfRegion = [](const coverage::CoverageSegment *S) {
26 return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
27 };
28 for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
29 if (isStartOfRegion(LineSegments[I]))
30 ++MinRegionCount;
31
32 bool StartOfSkippedRegion = !LineSegments.empty() &&
33 !LineSegments.front()->HasCount &&
34 LineSegments.front()->IsRegionEntry;
35
36 ExecutionCount = 0;
37 HasMultipleRegions = MinRegionCount > 1;
38 Mapped =
39 !StartOfSkippedRegion &&
40 ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
41
42 if (!Mapped)
43 return;
44
45 // Pick the max count among regions which start and end on this line, to
46 // avoid erroneously using the wrapped count, and to avoid picking region
47 // counts which come from deferred regions.
48 if (LineSegments.size() > 1) {
49 for (unsigned I = 0; I < LineSegments.size() - 1; ++I) {
50 if (!LineSegments[I]->IsGapRegion)
51 ExecutionCount = std::max(ExecutionCount, LineSegments[I]->Count);
52 }
53 return;
54 }
55
56 // If a non-gap region starts here, use its count. Otherwise use the wrapped
57 // count.
58 if (MinRegionCount == 1)
59 ExecutionCount = LineSegments[0]->Count;
60 else
61 ExecutionCount = WrappedSegment->Count;
62}
63
Alex Lorenze82d89c2014-08-22 22:56:03 +000064FunctionCoverageSummary
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000065FunctionCoverageSummary::get(const CoverageMapping &CM,
66 const coverage::FunctionRecord &Function) {
Ying Yi78db64e2016-07-22 09:20:21 +000067 // Compute the region coverage.
Alex Lorenze82d89c2014-08-22 22:56:03 +000068 size_t NumCodeRegions = 0, CoveredRegions = 0;
Justin Bogner8e8aa3f2014-09-09 05:32:14 +000069 for (auto &CR : Function.CountedRegions) {
70 if (CR.Kind != CounterMappingRegion::CodeRegion)
Alex Lorenze82d89c2014-08-22 22:56:03 +000071 continue;
72 ++NumCodeRegions;
Justin Bogner8e8aa3f2014-09-09 05:32:14 +000073 if (CR.ExecutionCount != 0)
Alex Lorenze82d89c2014-08-22 22:56:03 +000074 ++CoveredRegions;
75 }
76
77 // Compute the line coverage
78 size_t NumLines = 0, CoveredLines = 0;
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000079 CoverageData CD = CM.getCoverageForFunction(Function);
80 auto NextSegment = CD.begin();
81 auto EndSegment = CD.end();
82 const coverage::CoverageSegment *WrappedSegment = nullptr;
83 SmallVector<const coverage::CoverageSegment *, 4> LineSegments;
84 unsigned Line = NextSegment->Line;
85 while (NextSegment != EndSegment) {
86 // Gather the segments on this line and the wrapped segment.
87 if (LineSegments.size())
88 WrappedSegment = LineSegments.back();
89 LineSegments.clear();
90 while (NextSegment != EndSegment && NextSegment->Line == Line)
91 LineSegments.push_back(&*NextSegment++);
Alex Lorenze82d89c2014-08-22 22:56:03 +000092
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000093 LineCoverageStats LCS{LineSegments, WrappedSegment};
94 if (LCS.isMapped()) {
95 ++NumLines;
96 if (LCS.ExecutionCount)
97 ++CoveredLines;
Alex Lorenze82d89c2014-08-22 22:56:03 +000098 }
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000099
100 ++Line;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000101 }
Vedant Kumarb7fdaf22017-09-19 02:00:12 +0000102
Alex Lorenze82d89c2014-08-22 22:56:03 +0000103 return FunctionCoverageSummary(
Alex Lorenzcb1702d2014-09-30 12:45:13 +0000104 Function.Name, Function.ExecutionCount,
105 RegionCoverageInfo(CoveredRegions, NumCodeRegions),
Vedant Kumarb8d06942016-09-19 01:46:01 +0000106 LineCoverageInfo(CoveredLines, NumLines));
Alex Lorenze82d89c2014-08-22 22:56:03 +0000107}
Vedant Kumar016111f2016-09-19 00:38:23 +0000108
Vedant Kumardde19c52017-08-02 23:35:25 +0000109FunctionCoverageSummary
110FunctionCoverageSummary::get(const InstantiationGroup &Group,
111 ArrayRef<FunctionCoverageSummary> Summaries) {
112 std::string Name;
113 if (Group.hasName()) {
114 Name = Group.getName();
115 } else {
116 llvm::raw_string_ostream OS(Name);
117 OS << "Definition at line " << Group.getLine() << ", column "
118 << Group.getColumn();
119 }
120
Vedant Kumar72c3a112017-09-08 18:44:49 +0000121 FunctionCoverageSummary Summary(Name);
Vedant Kumardde19c52017-08-02 23:35:25 +0000122 Summary.ExecutionCount = Group.getTotalExecutionCount();
123 Summary.RegionCoverage = Summaries[0].RegionCoverage;
124 Summary.LineCoverage = Summaries[0].LineCoverage;
125 for (const auto &FCS : Summaries.drop_front()) {
Vedant Kumarc445e652017-09-15 23:00:01 +0000126 Summary.RegionCoverage.merge(FCS.RegionCoverage);
127 Summary.LineCoverage.merge(FCS.LineCoverage);
Vedant Kumardde19c52017-08-02 23:35:25 +0000128 }
129 return Summary;
Vedant Kumar016111f2016-09-19 00:38:23 +0000130}