xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- CoverageSummaryInfo.h - Coverage summary for function/file ---------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // These structures are used to represent code coverage metrics
100b57cec5SDimitry Andric // for functions/files.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_COV_COVERAGESUMMARYINFO_H
150b57cec5SDimitry Andric #define LLVM_COV_COVERAGESUMMARYINFO_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMapping.h"
180b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace llvm {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric /// Provides information about region coverage for a function/file.
230b57cec5SDimitry Andric class RegionCoverageInfo {
240b57cec5SDimitry Andric   /// The number of regions that were executed at least once.
250b57cec5SDimitry Andric   size_t Covered;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric   /// The total number of regions in a function/file.
280b57cec5SDimitry Andric   size_t NumRegions;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric public:
310b57cec5SDimitry Andric   RegionCoverageInfo() : Covered(0), NumRegions(0) {}
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric   RegionCoverageInfo(size_t Covered, size_t NumRegions)
340b57cec5SDimitry Andric       : Covered(Covered), NumRegions(NumRegions) {
350b57cec5SDimitry Andric     assert(Covered <= NumRegions && "Covered regions over-counted");
360b57cec5SDimitry Andric   }
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   RegionCoverageInfo &operator+=(const RegionCoverageInfo &RHS) {
390b57cec5SDimitry Andric     Covered += RHS.Covered;
400b57cec5SDimitry Andric     NumRegions += RHS.NumRegions;
410b57cec5SDimitry Andric     return *this;
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   void merge(const RegionCoverageInfo &RHS) {
450b57cec5SDimitry Andric     Covered = std::max(Covered, RHS.Covered);
460b57cec5SDimitry Andric     NumRegions = std::max(NumRegions, RHS.NumRegions);
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   size_t getCovered() const { return Covered; }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   size_t getNumRegions() const { return NumRegions; }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   bool isFullyCovered() const { return Covered == NumRegions; }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   double getPercentCovered() const {
560b57cec5SDimitry Andric     assert(Covered <= NumRegions && "Covered regions over-counted");
570b57cec5SDimitry Andric     if (NumRegions == 0)
580b57cec5SDimitry Andric       return 0.0;
590b57cec5SDimitry Andric     return double(Covered) / double(NumRegions) * 100.0;
600b57cec5SDimitry Andric   }
610b57cec5SDimitry Andric };
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric /// Provides information about line coverage for a function/file.
640b57cec5SDimitry Andric class LineCoverageInfo {
650b57cec5SDimitry Andric   /// The number of lines that were executed at least once.
660b57cec5SDimitry Andric   size_t Covered;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   /// The total number of lines in a function/file.
690b57cec5SDimitry Andric   size_t NumLines;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric public:
720b57cec5SDimitry Andric   LineCoverageInfo() : Covered(0), NumLines(0) {}
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   LineCoverageInfo(size_t Covered, size_t NumLines)
750b57cec5SDimitry Andric       : Covered(Covered), NumLines(NumLines) {
760b57cec5SDimitry Andric     assert(Covered <= NumLines && "Covered lines over-counted");
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   LineCoverageInfo &operator+=(const LineCoverageInfo &RHS) {
800b57cec5SDimitry Andric     Covered += RHS.Covered;
810b57cec5SDimitry Andric     NumLines += RHS.NumLines;
820b57cec5SDimitry Andric     return *this;
830b57cec5SDimitry Andric   }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   void merge(const LineCoverageInfo &RHS) {
860b57cec5SDimitry Andric     Covered = std::max(Covered, RHS.Covered);
870b57cec5SDimitry Andric     NumLines = std::max(NumLines, RHS.NumLines);
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   size_t getCovered() const { return Covered; }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   size_t getNumLines() const { return NumLines; }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   bool isFullyCovered() const { return Covered == NumLines; }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   double getPercentCovered() const {
970b57cec5SDimitry Andric     assert(Covered <= NumLines && "Covered lines over-counted");
980b57cec5SDimitry Andric     if (NumLines == 0)
990b57cec5SDimitry Andric       return 0.0;
1000b57cec5SDimitry Andric     return double(Covered) / double(NumLines) * 100.0;
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric };
1030b57cec5SDimitry Andric 
104e8d8bef9SDimitry Andric /// Provides information about branches coverage for a function/file.
105e8d8bef9SDimitry Andric class BranchCoverageInfo {
106e8d8bef9SDimitry Andric   /// The number of branches that were executed at least once.
107e8d8bef9SDimitry Andric   size_t Covered;
108e8d8bef9SDimitry Andric 
109e8d8bef9SDimitry Andric   /// The total number of branches in a function/file.
110e8d8bef9SDimitry Andric   size_t NumBranches;
111e8d8bef9SDimitry Andric 
112e8d8bef9SDimitry Andric public:
113e8d8bef9SDimitry Andric   BranchCoverageInfo() : Covered(0), NumBranches(0) {}
114e8d8bef9SDimitry Andric 
115e8d8bef9SDimitry Andric   BranchCoverageInfo(size_t Covered, size_t NumBranches)
116e8d8bef9SDimitry Andric       : Covered(Covered), NumBranches(NumBranches) {
117e8d8bef9SDimitry Andric     assert(Covered <= NumBranches && "Covered branches over-counted");
118e8d8bef9SDimitry Andric   }
119e8d8bef9SDimitry Andric 
120e8d8bef9SDimitry Andric   BranchCoverageInfo &operator+=(const BranchCoverageInfo &RHS) {
121e8d8bef9SDimitry Andric     Covered += RHS.Covered;
122e8d8bef9SDimitry Andric     NumBranches += RHS.NumBranches;
123e8d8bef9SDimitry Andric     return *this;
124e8d8bef9SDimitry Andric   }
125e8d8bef9SDimitry Andric 
1264652422eSDimitry Andric   void merge(const BranchCoverageInfo &RHS) {
1274652422eSDimitry Andric     Covered = std::max(Covered, RHS.Covered);
1284652422eSDimitry Andric     NumBranches = std::max(NumBranches, RHS.NumBranches);
1294652422eSDimitry Andric   }
1304652422eSDimitry Andric 
131e8d8bef9SDimitry Andric   size_t getCovered() const { return Covered; }
132e8d8bef9SDimitry Andric 
133e8d8bef9SDimitry Andric   size_t getNumBranches() const { return NumBranches; }
134e8d8bef9SDimitry Andric 
135e8d8bef9SDimitry Andric   bool isFullyCovered() const { return Covered == NumBranches; }
136e8d8bef9SDimitry Andric 
137e8d8bef9SDimitry Andric   double getPercentCovered() const {
138e8d8bef9SDimitry Andric     assert(Covered <= NumBranches && "Covered branches over-counted");
139e8d8bef9SDimitry Andric     if (NumBranches == 0)
140e8d8bef9SDimitry Andric       return 0.0;
141e8d8bef9SDimitry Andric     return double(Covered) / double(NumBranches) * 100.0;
142e8d8bef9SDimitry Andric   }
143e8d8bef9SDimitry Andric };
144e8d8bef9SDimitry Andric 
145*5f757f3fSDimitry Andric /// Provides information about MC/DC coverage for a function/file.
146*5f757f3fSDimitry Andric class MCDCCoverageInfo {
147*5f757f3fSDimitry Andric   /// The number of Independence Pairs that were covered.
148*5f757f3fSDimitry Andric   size_t CoveredPairs;
149*5f757f3fSDimitry Andric 
150*5f757f3fSDimitry Andric   /// The total number of Independence Pairs in a function/file.
151*5f757f3fSDimitry Andric   size_t NumPairs;
152*5f757f3fSDimitry Andric 
153*5f757f3fSDimitry Andric public:
154*5f757f3fSDimitry Andric   MCDCCoverageInfo() : CoveredPairs(0), NumPairs(0) {}
155*5f757f3fSDimitry Andric 
156*5f757f3fSDimitry Andric   MCDCCoverageInfo(size_t CoveredPairs, size_t NumPairs)
157*5f757f3fSDimitry Andric       : CoveredPairs(CoveredPairs), NumPairs(NumPairs) {
158*5f757f3fSDimitry Andric     assert(CoveredPairs <= NumPairs && "Covered pairs over-counted");
159*5f757f3fSDimitry Andric   }
160*5f757f3fSDimitry Andric 
161*5f757f3fSDimitry Andric   MCDCCoverageInfo &operator+=(const MCDCCoverageInfo &RHS) {
162*5f757f3fSDimitry Andric     CoveredPairs += RHS.CoveredPairs;
163*5f757f3fSDimitry Andric     NumPairs += RHS.NumPairs;
164*5f757f3fSDimitry Andric     return *this;
165*5f757f3fSDimitry Andric   }
166*5f757f3fSDimitry Andric 
167*5f757f3fSDimitry Andric   void merge(const MCDCCoverageInfo &RHS) {
168*5f757f3fSDimitry Andric     CoveredPairs = std::max(CoveredPairs, RHS.CoveredPairs);
169*5f757f3fSDimitry Andric     NumPairs = std::max(NumPairs, RHS.NumPairs);
170*5f757f3fSDimitry Andric   }
171*5f757f3fSDimitry Andric 
172*5f757f3fSDimitry Andric   size_t getCoveredPairs() const { return CoveredPairs; }
173*5f757f3fSDimitry Andric 
174*5f757f3fSDimitry Andric   size_t getNumPairs() const { return NumPairs; }
175*5f757f3fSDimitry Andric 
176*5f757f3fSDimitry Andric   bool isFullyCovered() const { return CoveredPairs == NumPairs; }
177*5f757f3fSDimitry Andric 
178*5f757f3fSDimitry Andric   double getPercentCovered() const {
179*5f757f3fSDimitry Andric     assert(CoveredPairs <= NumPairs && "Covered pairs over-counted");
180*5f757f3fSDimitry Andric     if (NumPairs == 0)
181*5f757f3fSDimitry Andric       return 0.0;
182*5f757f3fSDimitry Andric     return double(CoveredPairs) / double(NumPairs) * 100.0;
183*5f757f3fSDimitry Andric   }
184*5f757f3fSDimitry Andric };
185*5f757f3fSDimitry Andric 
1860b57cec5SDimitry Andric /// Provides information about function coverage for a file.
1870b57cec5SDimitry Andric class FunctionCoverageInfo {
1880b57cec5SDimitry Andric   /// The number of functions that were executed.
1890b57cec5SDimitry Andric   size_t Executed;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   /// The total number of functions in this file.
1920b57cec5SDimitry Andric   size_t NumFunctions;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric public:
1950b57cec5SDimitry Andric   FunctionCoverageInfo() : Executed(0), NumFunctions(0) {}
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   FunctionCoverageInfo(size_t Executed, size_t NumFunctions)
1980b57cec5SDimitry Andric       : Executed(Executed), NumFunctions(NumFunctions) {}
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   FunctionCoverageInfo &operator+=(const FunctionCoverageInfo &RHS) {
2010b57cec5SDimitry Andric     Executed += RHS.Executed;
2020b57cec5SDimitry Andric     NumFunctions += RHS.NumFunctions;
2030b57cec5SDimitry Andric     return *this;
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   void addFunction(bool Covered) {
2070b57cec5SDimitry Andric     if (Covered)
2080b57cec5SDimitry Andric       ++Executed;
2090b57cec5SDimitry Andric     ++NumFunctions;
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   size_t getExecuted() const { return Executed; }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   size_t getNumFunctions() const { return NumFunctions; }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   bool isFullyCovered() const { return Executed == NumFunctions; }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   double getPercentCovered() const {
2190b57cec5SDimitry Andric     assert(Executed <= NumFunctions && "Covered functions over-counted");
2200b57cec5SDimitry Andric     if (NumFunctions == 0)
2210b57cec5SDimitry Andric       return 0.0;
2220b57cec5SDimitry Andric     return double(Executed) / double(NumFunctions) * 100.0;
2230b57cec5SDimitry Andric   }
2240b57cec5SDimitry Andric };
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric /// A summary of function's code coverage.
2270b57cec5SDimitry Andric struct FunctionCoverageSummary {
2280b57cec5SDimitry Andric   std::string Name;
2290b57cec5SDimitry Andric   uint64_t ExecutionCount;
2300b57cec5SDimitry Andric   RegionCoverageInfo RegionCoverage;
2310b57cec5SDimitry Andric   LineCoverageInfo LineCoverage;
232e8d8bef9SDimitry Andric   BranchCoverageInfo BranchCoverage;
233*5f757f3fSDimitry Andric   MCDCCoverageInfo MCDCCoverage;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   FunctionCoverageSummary(const std::string &Name)
23604eeddc0SDimitry Andric       : Name(Name), ExecutionCount(0) {}
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount,
2390b57cec5SDimitry Andric                           const RegionCoverageInfo &RegionCoverage,
240e8d8bef9SDimitry Andric                           const LineCoverageInfo &LineCoverage,
241*5f757f3fSDimitry Andric                           const BranchCoverageInfo &BranchCoverage,
242*5f757f3fSDimitry Andric                           const MCDCCoverageInfo &MCDCCoverage)
2430b57cec5SDimitry Andric       : Name(Name), ExecutionCount(ExecutionCount),
244e8d8bef9SDimitry Andric         RegionCoverage(RegionCoverage), LineCoverage(LineCoverage),
245*5f757f3fSDimitry Andric         BranchCoverage(BranchCoverage), MCDCCoverage(MCDCCoverage) {}
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   /// Compute the code coverage summary for the given function coverage
2480b57cec5SDimitry Andric   /// mapping record.
2490b57cec5SDimitry Andric   static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
2500b57cec5SDimitry Andric                                      const coverage::FunctionRecord &Function);
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   /// Compute the code coverage summary for an instantiation group \p Group,
2530b57cec5SDimitry Andric   /// given a list of summaries for each instantiation in \p Summaries.
2540b57cec5SDimitry Andric   static FunctionCoverageSummary
2550b57cec5SDimitry Andric   get(const coverage::InstantiationGroup &Group,
2560b57cec5SDimitry Andric       ArrayRef<FunctionCoverageSummary> Summaries);
2570b57cec5SDimitry Andric };
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric /// A summary of file's code coverage.
2600b57cec5SDimitry Andric struct FileCoverageSummary {
2610b57cec5SDimitry Andric   StringRef Name;
2620b57cec5SDimitry Andric   RegionCoverageInfo RegionCoverage;
2630b57cec5SDimitry Andric   LineCoverageInfo LineCoverage;
264e8d8bef9SDimitry Andric   BranchCoverageInfo BranchCoverage;
265*5f757f3fSDimitry Andric   MCDCCoverageInfo MCDCCoverage;
2660b57cec5SDimitry Andric   FunctionCoverageInfo FunctionCoverage;
2670b57cec5SDimitry Andric   FunctionCoverageInfo InstantiationCoverage;
2680b57cec5SDimitry Andric 
269*5f757f3fSDimitry Andric   FileCoverageSummary() = default;
27004eeddc0SDimitry Andric   FileCoverageSummary(StringRef Name) : Name(Name) {}
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
2730b57cec5SDimitry Andric     RegionCoverage += RHS.RegionCoverage;
2740b57cec5SDimitry Andric     LineCoverage += RHS.LineCoverage;
2750b57cec5SDimitry Andric     FunctionCoverage += RHS.FunctionCoverage;
276e8d8bef9SDimitry Andric     BranchCoverage += RHS.BranchCoverage;
277*5f757f3fSDimitry Andric     MCDCCoverage += RHS.MCDCCoverage;
2780b57cec5SDimitry Andric     InstantiationCoverage += RHS.InstantiationCoverage;
2790b57cec5SDimitry Andric     return *this;
2800b57cec5SDimitry Andric   }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   void addFunction(const FunctionCoverageSummary &Function) {
2830b57cec5SDimitry Andric     RegionCoverage += Function.RegionCoverage;
2840b57cec5SDimitry Andric     LineCoverage += Function.LineCoverage;
285e8d8bef9SDimitry Andric     BranchCoverage += Function.BranchCoverage;
286*5f757f3fSDimitry Andric     MCDCCoverage += Function.MCDCCoverage;
2870b57cec5SDimitry Andric     FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
2880b57cec5SDimitry Andric   }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   void addInstantiation(const FunctionCoverageSummary &Function) {
2910b57cec5SDimitry Andric     InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
2920b57cec5SDimitry Andric   }
2930b57cec5SDimitry Andric };
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric /// A cache for demangled symbols.
2960b57cec5SDimitry Andric struct DemangleCache {
2970b57cec5SDimitry Andric   StringMap<std::string> DemangledNames;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   /// Demangle \p Sym if possible. Otherwise, just return \p Sym.
3000b57cec5SDimitry Andric   StringRef demangle(StringRef Sym) const {
3010b57cec5SDimitry Andric     const auto DemangledName = DemangledNames.find(Sym);
3020b57cec5SDimitry Andric     if (DemangledName == DemangledNames.end())
3030b57cec5SDimitry Andric       return Sym;
3040b57cec5SDimitry Andric     return DemangledName->getValue();
3050b57cec5SDimitry Andric   }
3060b57cec5SDimitry Andric };
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric } // namespace llvm
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric #endif // LLVM_COV_COVERAGESUMMARYINFO_H
311