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 size_t getCovered() const { return Covered; } 127 128 size_t getNumBranches() const { return NumBranches; } 129 130 bool isFullyCovered() const { return Covered == NumBranches; } 131 132 double getPercentCovered() const { 133 assert(Covered <= NumBranches && "Covered branches over-counted"); 134 if (NumBranches == 0) 135 return 0.0; 136 return double(Covered) / double(NumBranches) * 100.0; 137 } 138 }; 139 140 /// Provides information about function coverage for a file. 141 class FunctionCoverageInfo { 142 /// The number of functions that were executed. 143 size_t Executed; 144 145 /// The total number of functions in this file. 146 size_t NumFunctions; 147 148 public: 149 FunctionCoverageInfo() : Executed(0), NumFunctions(0) {} 150 151 FunctionCoverageInfo(size_t Executed, size_t NumFunctions) 152 : Executed(Executed), NumFunctions(NumFunctions) {} 153 154 FunctionCoverageInfo &operator+=(const FunctionCoverageInfo &RHS) { 155 Executed += RHS.Executed; 156 NumFunctions += RHS.NumFunctions; 157 return *this; 158 } 159 160 void addFunction(bool Covered) { 161 if (Covered) 162 ++Executed; 163 ++NumFunctions; 164 } 165 166 size_t getExecuted() const { return Executed; } 167 168 size_t getNumFunctions() const { return NumFunctions; } 169 170 bool isFullyCovered() const { return Executed == NumFunctions; } 171 172 double getPercentCovered() const { 173 assert(Executed <= NumFunctions && "Covered functions over-counted"); 174 if (NumFunctions == 0) 175 return 0.0; 176 return double(Executed) / double(NumFunctions) * 100.0; 177 } 178 }; 179 180 /// A summary of function's code coverage. 181 struct FunctionCoverageSummary { 182 std::string Name; 183 uint64_t ExecutionCount; 184 RegionCoverageInfo RegionCoverage; 185 LineCoverageInfo LineCoverage; 186 BranchCoverageInfo BranchCoverage; 187 188 FunctionCoverageSummary(const std::string &Name) 189 : Name(Name), ExecutionCount(0), RegionCoverage(), LineCoverage(), 190 BranchCoverage() {} 191 192 FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount, 193 const RegionCoverageInfo &RegionCoverage, 194 const LineCoverageInfo &LineCoverage, 195 const BranchCoverageInfo &BranchCoverage) 196 : Name(Name), ExecutionCount(ExecutionCount), 197 RegionCoverage(RegionCoverage), LineCoverage(LineCoverage), 198 BranchCoverage(BranchCoverage) {} 199 200 /// Compute the code coverage summary for the given function coverage 201 /// mapping record. 202 static FunctionCoverageSummary get(const coverage::CoverageMapping &CM, 203 const coverage::FunctionRecord &Function); 204 205 /// Compute the code coverage summary for an instantiation group \p Group, 206 /// given a list of summaries for each instantiation in \p Summaries. 207 static FunctionCoverageSummary 208 get(const coverage::InstantiationGroup &Group, 209 ArrayRef<FunctionCoverageSummary> Summaries); 210 }; 211 212 /// A summary of file's code coverage. 213 struct FileCoverageSummary { 214 StringRef Name; 215 RegionCoverageInfo RegionCoverage; 216 LineCoverageInfo LineCoverage; 217 BranchCoverageInfo BranchCoverage; 218 FunctionCoverageInfo FunctionCoverage; 219 FunctionCoverageInfo InstantiationCoverage; 220 221 FileCoverageSummary(StringRef Name) 222 : Name(Name), RegionCoverage(), LineCoverage(), FunctionCoverage(), 223 InstantiationCoverage() {} 224 225 FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) { 226 RegionCoverage += RHS.RegionCoverage; 227 LineCoverage += RHS.LineCoverage; 228 FunctionCoverage += RHS.FunctionCoverage; 229 BranchCoverage += RHS.BranchCoverage; 230 InstantiationCoverage += RHS.InstantiationCoverage; 231 return *this; 232 } 233 234 void addFunction(const FunctionCoverageSummary &Function) { 235 RegionCoverage += Function.RegionCoverage; 236 LineCoverage += Function.LineCoverage; 237 BranchCoverage += Function.BranchCoverage; 238 FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); 239 } 240 241 void addInstantiation(const FunctionCoverageSummary &Function) { 242 InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); 243 } 244 }; 245 246 /// A cache for demangled symbols. 247 struct DemangleCache { 248 StringMap<std::string> DemangledNames; 249 250 /// Demangle \p Sym if possible. Otherwise, just return \p Sym. 251 StringRef demangle(StringRef Sym) const { 252 const auto DemangledName = DemangledNames.find(Sym); 253 if (DemangledName == DemangledNames.end()) 254 return Sym; 255 return DemangledName->getValue(); 256 } 257 }; 258 259 } // namespace llvm 260 261 #endif // LLVM_COV_COVERAGESUMMARYINFO_H 262