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