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 MC/DC coverage for a function/file. 146 class 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 153 public: 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. 187 class 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 194 public: 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 struct 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. 246 struct 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 coverage 254 /// 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 FunctionCoverageSummary 261 get(const coverage::InstantiationGroup &Group, 262 ArrayRef<FunctionCoverageSummary> Summaries); 263 }; 264 265 /// A summary of file's code coverage. 266 struct 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. 295 struct 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 llvm 308 309 #endif // LLVM_COV_COVERAGESUMMARYINFO_H 310