xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.h (revision 79ac3c12a714bcd3f2354c52d948aed9575c46d6)
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 
20 namespace llvm {
21 
22 /// Provides information about region coverage for a function/file.
23 class 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 
30 public:
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(Covered, RHS.Covered);
46     NumRegions = std::max(NumRegions, 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.
64 class 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 
71 public:
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(Covered, RHS.Covered);
87     NumLines = std::max(NumLines, 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.
105 class 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 
112 public:
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   size_t getCovered() const { return Covered; }
127 
128   size_t getNumBranches() const { return NumBranches; }
129 
130   bool isFullyCovered() const { return Covered == NumBranches; }
131 
132   double getPercentCovered() const {
133     assert(Covered <= NumBranches && "Covered branches over-counted");
134     if (NumBranches == 0)
135       return 0.0;
136     return double(Covered) / double(NumBranches) * 100.0;
137   }
138 };
139 
140 /// Provides information about function coverage for a file.
141 class FunctionCoverageInfo {
142   /// The number of functions that were executed.
143   size_t Executed;
144 
145   /// The total number of functions in this file.
146   size_t NumFunctions;
147 
148 public:
149   FunctionCoverageInfo() : Executed(0), NumFunctions(0) {}
150 
151   FunctionCoverageInfo(size_t Executed, size_t NumFunctions)
152       : Executed(Executed), NumFunctions(NumFunctions) {}
153 
154   FunctionCoverageInfo &operator+=(const FunctionCoverageInfo &RHS) {
155     Executed += RHS.Executed;
156     NumFunctions += RHS.NumFunctions;
157     return *this;
158   }
159 
160   void addFunction(bool Covered) {
161     if (Covered)
162       ++Executed;
163     ++NumFunctions;
164   }
165 
166   size_t getExecuted() const { return Executed; }
167 
168   size_t getNumFunctions() const { return NumFunctions; }
169 
170   bool isFullyCovered() const { return Executed == NumFunctions; }
171 
172   double getPercentCovered() const {
173     assert(Executed <= NumFunctions && "Covered functions over-counted");
174     if (NumFunctions == 0)
175       return 0.0;
176     return double(Executed) / double(NumFunctions) * 100.0;
177   }
178 };
179 
180 /// A summary of function's code coverage.
181 struct FunctionCoverageSummary {
182   std::string Name;
183   uint64_t ExecutionCount;
184   RegionCoverageInfo RegionCoverage;
185   LineCoverageInfo LineCoverage;
186   BranchCoverageInfo BranchCoverage;
187 
188   FunctionCoverageSummary(const std::string &Name)
189       : Name(Name), ExecutionCount(0), RegionCoverage(), LineCoverage(),
190         BranchCoverage() {}
191 
192   FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount,
193                           const RegionCoverageInfo &RegionCoverage,
194                           const LineCoverageInfo &LineCoverage,
195                           const BranchCoverageInfo &BranchCoverage)
196       : Name(Name), ExecutionCount(ExecutionCount),
197         RegionCoverage(RegionCoverage), LineCoverage(LineCoverage),
198         BranchCoverage(BranchCoverage) {}
199 
200   /// Compute the code coverage summary for the given function coverage
201   /// mapping record.
202   static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
203                                      const coverage::FunctionRecord &Function);
204 
205   /// Compute the code coverage summary for an instantiation group \p Group,
206   /// given a list of summaries for each instantiation in \p Summaries.
207   static FunctionCoverageSummary
208   get(const coverage::InstantiationGroup &Group,
209       ArrayRef<FunctionCoverageSummary> Summaries);
210 };
211 
212 /// A summary of file's code coverage.
213 struct FileCoverageSummary {
214   StringRef Name;
215   RegionCoverageInfo RegionCoverage;
216   LineCoverageInfo LineCoverage;
217   BranchCoverageInfo BranchCoverage;
218   FunctionCoverageInfo FunctionCoverage;
219   FunctionCoverageInfo InstantiationCoverage;
220 
221   FileCoverageSummary(StringRef Name)
222       : Name(Name), RegionCoverage(), LineCoverage(), FunctionCoverage(),
223         InstantiationCoverage() {}
224 
225   FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
226     RegionCoverage += RHS.RegionCoverage;
227     LineCoverage += RHS.LineCoverage;
228     FunctionCoverage += RHS.FunctionCoverage;
229     BranchCoverage += RHS.BranchCoverage;
230     InstantiationCoverage += RHS.InstantiationCoverage;
231     return *this;
232   }
233 
234   void addFunction(const FunctionCoverageSummary &Function) {
235     RegionCoverage += Function.RegionCoverage;
236     LineCoverage += Function.LineCoverage;
237     BranchCoverage += Function.BranchCoverage;
238     FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
239   }
240 
241   void addInstantiation(const FunctionCoverageSummary &Function) {
242     InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
243   }
244 };
245 
246 /// A cache for demangled symbols.
247 struct DemangleCache {
248   StringMap<std::string> DemangledNames;
249 
250   /// Demangle \p Sym if possible. Otherwise, just return \p Sym.
251   StringRef demangle(StringRef Sym) const {
252     const auto DemangledName = DemangledNames.find(Sym);
253     if (DemangledName == DemangledNames.end())
254       return Sym;
255     return DemangledName->getValue();
256   }
257 };
258 
259 } // namespace llvm
260 
261 #endif // LLVM_COV_COVERAGESUMMARYINFO_H
262