310 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// These structures are used to represent code coverage metrics10// for functions/files.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_COV_COVERAGESUMMARYINFO_H15#define LLVM_COV_COVERAGESUMMARYINFO_H16 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(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.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(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.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(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 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(CoveredPairs, RHS.CoveredPairs);169 NumPairs = std::max(NumPairs, 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 coverage254 /// 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 FunctionCoverageSummary261 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=*/Function.ExecutionCount > 0);287 }288 289 void addInstantiation(const FunctionCoverageSummary &Function) {290 InstantiationCoverage.addFunction(/*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(Sym);301 if (DemangledName == DemangledNames.end())302 return Sym;303 return DemangledName->getValue();304 }305};306 307} // namespace llvm308 309#endif // LLVM_COV_COVERAGESUMMARYINFO_H310