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 /// A summary of function's code coverage. 227 struct FunctionCoverageSummary { 228 std::string Name; 229 uint64_t ExecutionCount; 230 RegionCoverageInfo RegionCoverage; 231 LineCoverageInfo LineCoverage; 232 BranchCoverageInfo BranchCoverage; 233 MCDCCoverageInfo MCDCCoverage; 234 235 FunctionCoverageSummary(const std::string &Name) 236 : Name(Name), ExecutionCount(0) {} 237 238 FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount, 239 const RegionCoverageInfo &RegionCoverage, 240 const LineCoverageInfo &LineCoverage, 241 const BranchCoverageInfo &BranchCoverage, 242 const MCDCCoverageInfo &MCDCCoverage) 243 : Name(Name), ExecutionCount(ExecutionCount), 244 RegionCoverage(RegionCoverage), LineCoverage(LineCoverage), 245 BranchCoverage(BranchCoverage), MCDCCoverage(MCDCCoverage) {} 246 247 /// Compute the code coverage summary for the given function coverage 248 /// mapping record. 249 static FunctionCoverageSummary get(const coverage::CoverageMapping &CM, 250 const coverage::FunctionRecord &Function); 251 252 /// Compute the code coverage summary for an instantiation group \p Group, 253 /// given a list of summaries for each instantiation in \p Summaries. 254 static FunctionCoverageSummary 255 get(const coverage::InstantiationGroup &Group, 256 ArrayRef<FunctionCoverageSummary> Summaries); 257 }; 258 259 /// A summary of file's code coverage. 260 struct FileCoverageSummary { 261 StringRef Name; 262 RegionCoverageInfo RegionCoverage; 263 LineCoverageInfo LineCoverage; 264 BranchCoverageInfo BranchCoverage; 265 MCDCCoverageInfo MCDCCoverage; 266 FunctionCoverageInfo FunctionCoverage; 267 FunctionCoverageInfo InstantiationCoverage; 268 269 FileCoverageSummary() = default; 270 FileCoverageSummary(StringRef Name) : Name(Name) {} 271 272 FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) { 273 RegionCoverage += RHS.RegionCoverage; 274 LineCoverage += RHS.LineCoverage; 275 FunctionCoverage += RHS.FunctionCoverage; 276 BranchCoverage += RHS.BranchCoverage; 277 MCDCCoverage += RHS.MCDCCoverage; 278 InstantiationCoverage += RHS.InstantiationCoverage; 279 return *this; 280 } 281 282 void addFunction(const FunctionCoverageSummary &Function) { 283 RegionCoverage += Function.RegionCoverage; 284 LineCoverage += Function.LineCoverage; 285 BranchCoverage += Function.BranchCoverage; 286 MCDCCoverage += Function.MCDCCoverage; 287 FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); 288 } 289 290 void addInstantiation(const FunctionCoverageSummary &Function) { 291 InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); 292 } 293 }; 294 295 /// A cache for demangled symbols. 296 struct DemangleCache { 297 StringMap<std::string> DemangledNames; 298 299 /// Demangle \p Sym if possible. Otherwise, just return \p Sym. 300 StringRef demangle(StringRef Sym) const { 301 const auto DemangledName = DemangledNames.find(Sym); 302 if (DemangledName == DemangledNames.end()) 303 return Sym; 304 return DemangledName->getValue(); 305 } 306 }; 307 308 } // namespace llvm 309 310 #endif // LLVM_COV_COVERAGESUMMARYINFO_H 311