1//===- CoverageSummaryInfo.h - Coverage summary for function/file ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// These structures are used to represent code coverage metrics
10// for functions/files.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_COV_COVERAGESUMMARYINFO_H
15#define LLVM_COV_COVERAGESUMMARYINFO_H
16
17#include "llvm/ProfileData/Coverage/CoverageMapping.h"
18#include "llvm/Support/raw_ostream.h"
19
20namespace llvm {
21
22/// Provides information about region coverage for a function/file.
23class RegionCoverageInfo {
24 /// The number of regions that were executed at least once.
25 size_t Covered;
26
27 /// The total number of regions in a function/file.
28 size_t NumRegions;
29
30public:
31 RegionCoverageInfo() : Covered(0), NumRegions(0) {}
32
33 RegionCoverageInfo(size_t Covered, size_t NumRegions)
34 : Covered(Covered), NumRegions(NumRegions) {
35 assert(Covered <= NumRegions && "Covered regions over-counted");
36 }
37
38 RegionCoverageInfo &operator+=(const RegionCoverageInfo &RHS) {
39 Covered += RHS.Covered;
40 NumRegions += RHS.NumRegions;
41 return *this;
42 }
43
44 void merge(const RegionCoverageInfo &RHS) {
45 Covered = std::max(a: Covered, b: RHS.Covered);
46 NumRegions = std::max(a: NumRegions, b: RHS.NumRegions);
47 }
48
49 size_t getCovered() const { return Covered; }
50
51 size_t getNumRegions() const { return NumRegions; }
52
53 bool isFullyCovered() const { return Covered == NumRegions; }
54
55 double getPercentCovered() const {
56 assert(Covered <= NumRegions && "Covered regions over-counted");
57 if (NumRegions == 0)
58 return 0.0;
59 return double(Covered) / double(NumRegions) * 100.0;
60 }
61};
62
63/// Provides information about line coverage for a function/file.
64class LineCoverageInfo {
65 /// The number of lines that were executed at least once.
66 size_t Covered;
67
68 /// The total number of lines in a function/file.
69 size_t NumLines;
70
71public:
72 LineCoverageInfo() : Covered(0), NumLines(0) {}
73
74 LineCoverageInfo(size_t Covered, size_t NumLines)
75 : Covered(Covered), NumLines(NumLines) {
76 assert(Covered <= NumLines && "Covered lines over-counted");
77 }
78
79 LineCoverageInfo &operator+=(const LineCoverageInfo &RHS) {
80 Covered += RHS.Covered;
81 NumLines += RHS.NumLines;
82 return *this;
83 }
84
85 void merge(const LineCoverageInfo &RHS) {
86 Covered = std::max(a: Covered, b: RHS.Covered);
87 NumLines = std::max(a: NumLines, b: RHS.NumLines);
88 }
89
90 size_t getCovered() const { return Covered; }
91
92 size_t getNumLines() const { return NumLines; }
93
94 bool isFullyCovered() const { return Covered == NumLines; }
95
96 double getPercentCovered() const {
97 assert(Covered <= NumLines && "Covered lines over-counted");
98 if (NumLines == 0)
99 return 0.0;
100 return double(Covered) / double(NumLines) * 100.0;
101 }
102};
103
104/// Provides information about branches coverage for a function/file.
105class BranchCoverageInfo {
106 /// The number of branches that were executed at least once.
107 size_t Covered;
108
109 /// The total number of branches in a function/file.
110 size_t NumBranches;
111
112public:
113 BranchCoverageInfo() : Covered(0), NumBranches(0) {}
114
115 BranchCoverageInfo(size_t Covered, size_t NumBranches)
116 : Covered(Covered), NumBranches(NumBranches) {
117 assert(Covered <= NumBranches && "Covered branches over-counted");
118 }
119
120 BranchCoverageInfo &operator+=(const BranchCoverageInfo &RHS) {
121 Covered += RHS.Covered;
122 NumBranches += RHS.NumBranches;
123 return *this;
124 }
125
126 void merge(const BranchCoverageInfo &RHS) {
127 Covered = std::max(a: Covered, b: RHS.Covered);
128 NumBranches = std::max(a: NumBranches, b: RHS.NumBranches);
129 }
130
131 size_t getCovered() const { return Covered; }
132
133 size_t getNumBranches() const { return NumBranches; }
134
135 bool isFullyCovered() const { return Covered == NumBranches; }
136
137 double getPercentCovered() const {
138 assert(Covered <= NumBranches && "Covered branches over-counted");
139 if (NumBranches == 0)
140 return 0.0;
141 return double(Covered) / double(NumBranches) * 100.0;
142 }
143};
144
145/// Provides information about MC/DC coverage for a function/file.
146class MCDCCoverageInfo {
147 /// The number of Independence Pairs that were covered.
148 size_t CoveredPairs;
149
150 /// The total number of Independence Pairs in a function/file.
151 size_t NumPairs;
152
153public:
154 MCDCCoverageInfo() : CoveredPairs(0), NumPairs(0) {}
155
156 MCDCCoverageInfo(size_t CoveredPairs, size_t NumPairs)
157 : CoveredPairs(CoveredPairs), NumPairs(NumPairs) {
158 assert(CoveredPairs <= NumPairs && "Covered pairs over-counted");
159 }
160
161 MCDCCoverageInfo &operator+=(const MCDCCoverageInfo &RHS) {
162 CoveredPairs += RHS.CoveredPairs;
163 NumPairs += RHS.NumPairs;
164 return *this;
165 }
166
167 void merge(const MCDCCoverageInfo &RHS) {
168 CoveredPairs = std::max(a: CoveredPairs, b: RHS.CoveredPairs);
169 NumPairs = std::max(a: NumPairs, b: RHS.NumPairs);
170 }
171
172 size_t getCoveredPairs() const { return CoveredPairs; }
173
174 size_t getNumPairs() const { return NumPairs; }
175
176 bool isFullyCovered() const { return CoveredPairs == NumPairs; }
177
178 double getPercentCovered() const {
179 assert(CoveredPairs <= NumPairs && "Covered pairs over-counted");
180 if (NumPairs == 0)
181 return 0.0;
182 return double(CoveredPairs) / double(NumPairs) * 100.0;
183 }
184};
185
186/// Provides information about function coverage for a file.
187class FunctionCoverageInfo {
188 /// The number of functions that were executed.
189 size_t Executed;
190
191 /// The total number of functions in this file.
192 size_t NumFunctions;
193
194public:
195 FunctionCoverageInfo() : Executed(0), NumFunctions(0) {}
196
197 FunctionCoverageInfo(size_t Executed, size_t NumFunctions)
198 : Executed(Executed), NumFunctions(NumFunctions) {}
199
200 FunctionCoverageInfo &operator+=(const FunctionCoverageInfo &RHS) {
201 Executed += RHS.Executed;
202 NumFunctions += RHS.NumFunctions;
203 return *this;
204 }
205
206 void addFunction(bool Covered) {
207 if (Covered)
208 ++Executed;
209 ++NumFunctions;
210 }
211
212 size_t getExecuted() const { return Executed; }
213
214 size_t getNumFunctions() const { return NumFunctions; }
215
216 bool isFullyCovered() const { return Executed == NumFunctions; }
217
218 double getPercentCovered() const {
219 assert(Executed <= NumFunctions && "Covered functions over-counted");
220 if (NumFunctions == 0)
221 return 0.0;
222 return double(Executed) / double(NumFunctions) * 100.0;
223 }
224};
225
226struct CoverageDataSummary {
227 RegionCoverageInfo RegionCoverage;
228 LineCoverageInfo LineCoverage;
229 BranchCoverageInfo BranchCoverage;
230 MCDCCoverageInfo MCDCCoverage;
231
232 CoverageDataSummary() = default;
233 CoverageDataSummary(const coverage::CoverageData &CD,
234 ArrayRef<coverage::CountedRegion> CodeRegions);
235
236 auto &operator+=(const CoverageDataSummary &RHS) {
237 RegionCoverage += RHS.RegionCoverage;
238 LineCoverage += RHS.LineCoverage;
239 BranchCoverage += RHS.BranchCoverage;
240 MCDCCoverage += RHS.MCDCCoverage;
241 return *this;
242 }
243};
244
245/// A summary of function's code coverage.
246struct FunctionCoverageSummary : CoverageDataSummary {
247 std::string Name;
248 uint64_t ExecutionCount;
249
250 FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount = 0)
251 : Name(Name), ExecutionCount(ExecutionCount) {}
252
253 /// Compute the code coverage summary for the given function coverage
254 /// mapping record.
255 static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
256 const coverage::FunctionRecord &Function);
257
258 /// Compute the code coverage summary for an instantiation group \p Group,
259 /// given a list of summaries for each instantiation in \p Summaries.
260 static FunctionCoverageSummary
261 get(const coverage::InstantiationGroup &Group,
262 ArrayRef<FunctionCoverageSummary> Summaries);
263};
264
265/// A summary of file's code coverage.
266struct FileCoverageSummary : CoverageDataSummary {
267 StringRef Name;
268 FunctionCoverageInfo FunctionCoverage;
269 FunctionCoverageInfo InstantiationCoverage;
270
271 FileCoverageSummary() = default;
272 FileCoverageSummary(StringRef Name) : Name(Name) {}
273
274 FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
275 *static_cast<CoverageDataSummary *>(this) += RHS;
276 FunctionCoverage += RHS.FunctionCoverage;
277 InstantiationCoverage += RHS.InstantiationCoverage;
278 return *this;
279 }
280
281 void addFunction(const FunctionCoverageSummary &Function) {
282 RegionCoverage += Function.RegionCoverage;
283 LineCoverage += Function.LineCoverage;
284 BranchCoverage += Function.BranchCoverage;
285 MCDCCoverage += Function.MCDCCoverage;
286 FunctionCoverage.addFunction(/*Covered=*/Covered: Function.ExecutionCount > 0);
287 }
288
289 void addInstantiation(const FunctionCoverageSummary &Function) {
290 InstantiationCoverage.addFunction(/*Covered=*/Covered: Function.ExecutionCount > 0);
291 }
292};
293
294/// A cache for demangled symbols.
295struct DemangleCache {
296 StringMap<std::string> DemangledNames;
297
298 /// Demangle \p Sym if possible. Otherwise, just return \p Sym.
299 StringRef demangle(StringRef Sym) const {
300 const auto DemangledName = DemangledNames.find(Key: Sym);
301 if (DemangledName == DemangledNames.end())
302 return Sym;
303 return DemangledName->getValue();
304 }
305};
306
307} // namespace llvm
308
309#endif // LLVM_COV_COVERAGESUMMARYINFO_H
310