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
226/// A summary of function's code coverage.
227struct FunctionCoverageSummary {
228 std::string Name;
229 uint64_t ExecutionCount;
230 RegionCoverageInfo RegionCoverage;
231 LineCoverageInfo LineCoverage;
232 BranchCoverageInfo BranchCoverage;
233 MCDCCoverageInfo MCDCCoverage;
234
235 FunctionCoverageSummary(const std::string &Name)
236 : Name(Name), ExecutionCount(0) {}
237
238 FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount,
239 const RegionCoverageInfo &RegionCoverage,
240 const LineCoverageInfo &LineCoverage,
241 const BranchCoverageInfo &BranchCoverage,
242 const MCDCCoverageInfo &MCDCCoverage)
243 : Name(Name), ExecutionCount(ExecutionCount),
244 RegionCoverage(RegionCoverage), LineCoverage(LineCoverage),
245 BranchCoverage(BranchCoverage), MCDCCoverage(MCDCCoverage) {}
246
247 /// Compute the code coverage summary for the given function coverage
248 /// mapping record.
249 static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
250 const coverage::FunctionRecord &Function);
251
252 /// Compute the code coverage summary for an instantiation group \p Group,
253 /// given a list of summaries for each instantiation in \p Summaries.
254 static FunctionCoverageSummary
255 get(const coverage::InstantiationGroup &Group,
256 ArrayRef<FunctionCoverageSummary> Summaries);
257};
258
259/// A summary of file's code coverage.
260struct FileCoverageSummary {
261 StringRef Name;
262 RegionCoverageInfo RegionCoverage;
263 LineCoverageInfo LineCoverage;
264 BranchCoverageInfo BranchCoverage;
265 MCDCCoverageInfo MCDCCoverage;
266 FunctionCoverageInfo FunctionCoverage;
267 FunctionCoverageInfo InstantiationCoverage;
268
269 FileCoverageSummary() = default;
270 FileCoverageSummary(StringRef Name) : Name(Name) {}
271
272 FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
273 RegionCoverage += RHS.RegionCoverage;
274 LineCoverage += RHS.LineCoverage;
275 FunctionCoverage += RHS.FunctionCoverage;
276 BranchCoverage += RHS.BranchCoverage;
277 MCDCCoverage += RHS.MCDCCoverage;
278 InstantiationCoverage += RHS.InstantiationCoverage;
279 return *this;
280 }
281
282 void addFunction(const FunctionCoverageSummary &Function) {
283 RegionCoverage += Function.RegionCoverage;
284 LineCoverage += Function.LineCoverage;
285 BranchCoverage += Function.BranchCoverage;
286 MCDCCoverage += Function.MCDCCoverage;
287 FunctionCoverage.addFunction(/*Covered=*/Covered: Function.ExecutionCount > 0);
288 }
289
290 void addInstantiation(const FunctionCoverageSummary &Function) {
291 InstantiationCoverage.addFunction(/*Covered=*/Covered: Function.ExecutionCount > 0);
292 }
293};
294
295/// A cache for demangled symbols.
296struct DemangleCache {
297 StringMap<std::string> DemangledNames;
298
299 /// Demangle \p Sym if possible. Otherwise, just return \p Sym.
300 StringRef demangle(StringRef Sym) const {
301 const auto DemangledName = DemangledNames.find(Key: Sym);
302 if (DemangledName == DemangledNames.end())
303 return Sym;
304 return DemangledName->getValue();
305 }
306};
307
308} // namespace llvm
309
310#endif // LLVM_COV_COVERAGESUMMARYINFO_H
311