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