10b57cec5SDimitry Andric //===- CoverageSummaryInfo.h - Coverage summary for function/file ---------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // These structures are used to represent code coverage metrics 100b57cec5SDimitry Andric // for functions/files. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_COV_COVERAGESUMMARYINFO_H 150b57cec5SDimitry Andric #define LLVM_COV_COVERAGESUMMARYINFO_H 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMapping.h" 180b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace llvm { 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric /// Provides information about region coverage for a function/file. 230b57cec5SDimitry Andric class RegionCoverageInfo { 240b57cec5SDimitry Andric /// The number of regions that were executed at least once. 250b57cec5SDimitry Andric size_t Covered; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric /// The total number of regions in a function/file. 280b57cec5SDimitry Andric size_t NumRegions; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric public: 310b57cec5SDimitry Andric RegionCoverageInfo() : Covered(0), NumRegions(0) {} 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric RegionCoverageInfo(size_t Covered, size_t NumRegions) 340b57cec5SDimitry Andric : Covered(Covered), NumRegions(NumRegions) { 350b57cec5SDimitry Andric assert(Covered <= NumRegions && "Covered regions over-counted"); 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric RegionCoverageInfo &operator+=(const RegionCoverageInfo &RHS) { 390b57cec5SDimitry Andric Covered += RHS.Covered; 400b57cec5SDimitry Andric NumRegions += RHS.NumRegions; 410b57cec5SDimitry Andric return *this; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric void merge(const RegionCoverageInfo &RHS) { 450b57cec5SDimitry Andric Covered = std::max(Covered, RHS.Covered); 460b57cec5SDimitry Andric NumRegions = std::max(NumRegions, RHS.NumRegions); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric size_t getCovered() const { return Covered; } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric size_t getNumRegions() const { return NumRegions; } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric bool isFullyCovered() const { return Covered == NumRegions; } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric double getPercentCovered() const { 560b57cec5SDimitry Andric assert(Covered <= NumRegions && "Covered regions over-counted"); 570b57cec5SDimitry Andric if (NumRegions == 0) 580b57cec5SDimitry Andric return 0.0; 590b57cec5SDimitry Andric return double(Covered) / double(NumRegions) * 100.0; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric }; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// Provides information about line coverage for a function/file. 640b57cec5SDimitry Andric class LineCoverageInfo { 650b57cec5SDimitry Andric /// The number of lines that were executed at least once. 660b57cec5SDimitry Andric size_t Covered; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric /// The total number of lines in a function/file. 690b57cec5SDimitry Andric size_t NumLines; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric public: 720b57cec5SDimitry Andric LineCoverageInfo() : Covered(0), NumLines(0) {} 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric LineCoverageInfo(size_t Covered, size_t NumLines) 750b57cec5SDimitry Andric : Covered(Covered), NumLines(NumLines) { 760b57cec5SDimitry Andric assert(Covered <= NumLines && "Covered lines over-counted"); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric LineCoverageInfo &operator+=(const LineCoverageInfo &RHS) { 800b57cec5SDimitry Andric Covered += RHS.Covered; 810b57cec5SDimitry Andric NumLines += RHS.NumLines; 820b57cec5SDimitry Andric return *this; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric void merge(const LineCoverageInfo &RHS) { 860b57cec5SDimitry Andric Covered = std::max(Covered, RHS.Covered); 870b57cec5SDimitry Andric NumLines = std::max(NumLines, RHS.NumLines); 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric size_t getCovered() const { return Covered; } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric size_t getNumLines() const { return NumLines; } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric bool isFullyCovered() const { return Covered == NumLines; } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric double getPercentCovered() const { 970b57cec5SDimitry Andric assert(Covered <= NumLines && "Covered lines over-counted"); 980b57cec5SDimitry Andric if (NumLines == 0) 990b57cec5SDimitry Andric return 0.0; 1000b57cec5SDimitry Andric return double(Covered) / double(NumLines) * 100.0; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric }; 1030b57cec5SDimitry Andric 104e8d8bef9SDimitry Andric /// Provides information about branches coverage for a function/file. 105e8d8bef9SDimitry Andric class BranchCoverageInfo { 106e8d8bef9SDimitry Andric /// The number of branches that were executed at least once. 107e8d8bef9SDimitry Andric size_t Covered; 108e8d8bef9SDimitry Andric 109e8d8bef9SDimitry Andric /// The total number of branches in a function/file. 110e8d8bef9SDimitry Andric size_t NumBranches; 111e8d8bef9SDimitry Andric 112e8d8bef9SDimitry Andric public: 113e8d8bef9SDimitry Andric BranchCoverageInfo() : Covered(0), NumBranches(0) {} 114e8d8bef9SDimitry Andric 115e8d8bef9SDimitry Andric BranchCoverageInfo(size_t Covered, size_t NumBranches) 116e8d8bef9SDimitry Andric : Covered(Covered), NumBranches(NumBranches) { 117e8d8bef9SDimitry Andric assert(Covered <= NumBranches && "Covered branches over-counted"); 118e8d8bef9SDimitry Andric } 119e8d8bef9SDimitry Andric 120e8d8bef9SDimitry Andric BranchCoverageInfo &operator+=(const BranchCoverageInfo &RHS) { 121e8d8bef9SDimitry Andric Covered += RHS.Covered; 122e8d8bef9SDimitry Andric NumBranches += RHS.NumBranches; 123e8d8bef9SDimitry Andric return *this; 124e8d8bef9SDimitry Andric } 125e8d8bef9SDimitry Andric 1264652422eSDimitry Andric void merge(const BranchCoverageInfo &RHS) { 1274652422eSDimitry Andric Covered = std::max(Covered, RHS.Covered); 1284652422eSDimitry Andric NumBranches = std::max(NumBranches, RHS.NumBranches); 1294652422eSDimitry Andric } 1304652422eSDimitry Andric 131e8d8bef9SDimitry Andric size_t getCovered() const { return Covered; } 132e8d8bef9SDimitry Andric 133e8d8bef9SDimitry Andric size_t getNumBranches() const { return NumBranches; } 134e8d8bef9SDimitry Andric 135e8d8bef9SDimitry Andric bool isFullyCovered() const { return Covered == NumBranches; } 136e8d8bef9SDimitry Andric 137e8d8bef9SDimitry Andric double getPercentCovered() const { 138e8d8bef9SDimitry Andric assert(Covered <= NumBranches && "Covered branches over-counted"); 139e8d8bef9SDimitry Andric if (NumBranches == 0) 140e8d8bef9SDimitry Andric return 0.0; 141e8d8bef9SDimitry Andric return double(Covered) / double(NumBranches) * 100.0; 142e8d8bef9SDimitry Andric } 143e8d8bef9SDimitry Andric }; 144e8d8bef9SDimitry Andric 145*5f757f3fSDimitry Andric /// Provides information about MC/DC coverage for a function/file. 146*5f757f3fSDimitry Andric class MCDCCoverageInfo { 147*5f757f3fSDimitry Andric /// The number of Independence Pairs that were covered. 148*5f757f3fSDimitry Andric size_t CoveredPairs; 149*5f757f3fSDimitry Andric 150*5f757f3fSDimitry Andric /// The total number of Independence Pairs in a function/file. 151*5f757f3fSDimitry Andric size_t NumPairs; 152*5f757f3fSDimitry Andric 153*5f757f3fSDimitry Andric public: 154*5f757f3fSDimitry Andric MCDCCoverageInfo() : CoveredPairs(0), NumPairs(0) {} 155*5f757f3fSDimitry Andric 156*5f757f3fSDimitry Andric MCDCCoverageInfo(size_t CoveredPairs, size_t NumPairs) 157*5f757f3fSDimitry Andric : CoveredPairs(CoveredPairs), NumPairs(NumPairs) { 158*5f757f3fSDimitry Andric assert(CoveredPairs <= NumPairs && "Covered pairs over-counted"); 159*5f757f3fSDimitry Andric } 160*5f757f3fSDimitry Andric 161*5f757f3fSDimitry Andric MCDCCoverageInfo &operator+=(const MCDCCoverageInfo &RHS) { 162*5f757f3fSDimitry Andric CoveredPairs += RHS.CoveredPairs; 163*5f757f3fSDimitry Andric NumPairs += RHS.NumPairs; 164*5f757f3fSDimitry Andric return *this; 165*5f757f3fSDimitry Andric } 166*5f757f3fSDimitry Andric 167*5f757f3fSDimitry Andric void merge(const MCDCCoverageInfo &RHS) { 168*5f757f3fSDimitry Andric CoveredPairs = std::max(CoveredPairs, RHS.CoveredPairs); 169*5f757f3fSDimitry Andric NumPairs = std::max(NumPairs, RHS.NumPairs); 170*5f757f3fSDimitry Andric } 171*5f757f3fSDimitry Andric 172*5f757f3fSDimitry Andric size_t getCoveredPairs() const { return CoveredPairs; } 173*5f757f3fSDimitry Andric 174*5f757f3fSDimitry Andric size_t getNumPairs() const { return NumPairs; } 175*5f757f3fSDimitry Andric 176*5f757f3fSDimitry Andric bool isFullyCovered() const { return CoveredPairs == NumPairs; } 177*5f757f3fSDimitry Andric 178*5f757f3fSDimitry Andric double getPercentCovered() const { 179*5f757f3fSDimitry Andric assert(CoveredPairs <= NumPairs && "Covered pairs over-counted"); 180*5f757f3fSDimitry Andric if (NumPairs == 0) 181*5f757f3fSDimitry Andric return 0.0; 182*5f757f3fSDimitry Andric return double(CoveredPairs) / double(NumPairs) * 100.0; 183*5f757f3fSDimitry Andric } 184*5f757f3fSDimitry Andric }; 185*5f757f3fSDimitry Andric 1860b57cec5SDimitry Andric /// Provides information about function coverage for a file. 1870b57cec5SDimitry Andric class FunctionCoverageInfo { 1880b57cec5SDimitry Andric /// The number of functions that were executed. 1890b57cec5SDimitry Andric size_t Executed; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric /// The total number of functions in this file. 1920b57cec5SDimitry Andric size_t NumFunctions; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric public: 1950b57cec5SDimitry Andric FunctionCoverageInfo() : Executed(0), NumFunctions(0) {} 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric FunctionCoverageInfo(size_t Executed, size_t NumFunctions) 1980b57cec5SDimitry Andric : Executed(Executed), NumFunctions(NumFunctions) {} 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric FunctionCoverageInfo &operator+=(const FunctionCoverageInfo &RHS) { 2010b57cec5SDimitry Andric Executed += RHS.Executed; 2020b57cec5SDimitry Andric NumFunctions += RHS.NumFunctions; 2030b57cec5SDimitry Andric return *this; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric void addFunction(bool Covered) { 2070b57cec5SDimitry Andric if (Covered) 2080b57cec5SDimitry Andric ++Executed; 2090b57cec5SDimitry Andric ++NumFunctions; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric size_t getExecuted() const { return Executed; } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric size_t getNumFunctions() const { return NumFunctions; } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric bool isFullyCovered() const { return Executed == NumFunctions; } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric double getPercentCovered() const { 2190b57cec5SDimitry Andric assert(Executed <= NumFunctions && "Covered functions over-counted"); 2200b57cec5SDimitry Andric if (NumFunctions == 0) 2210b57cec5SDimitry Andric return 0.0; 2220b57cec5SDimitry Andric return double(Executed) / double(NumFunctions) * 100.0; 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric }; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric /// A summary of function's code coverage. 2270b57cec5SDimitry Andric struct FunctionCoverageSummary { 2280b57cec5SDimitry Andric std::string Name; 2290b57cec5SDimitry Andric uint64_t ExecutionCount; 2300b57cec5SDimitry Andric RegionCoverageInfo RegionCoverage; 2310b57cec5SDimitry Andric LineCoverageInfo LineCoverage; 232e8d8bef9SDimitry Andric BranchCoverageInfo BranchCoverage; 233*5f757f3fSDimitry Andric MCDCCoverageInfo MCDCCoverage; 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric FunctionCoverageSummary(const std::string &Name) 23604eeddc0SDimitry Andric : Name(Name), ExecutionCount(0) {} 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount, 2390b57cec5SDimitry Andric const RegionCoverageInfo &RegionCoverage, 240e8d8bef9SDimitry Andric const LineCoverageInfo &LineCoverage, 241*5f757f3fSDimitry Andric const BranchCoverageInfo &BranchCoverage, 242*5f757f3fSDimitry Andric const MCDCCoverageInfo &MCDCCoverage) 2430b57cec5SDimitry Andric : Name(Name), ExecutionCount(ExecutionCount), 244e8d8bef9SDimitry Andric RegionCoverage(RegionCoverage), LineCoverage(LineCoverage), 245*5f757f3fSDimitry Andric BranchCoverage(BranchCoverage), MCDCCoverage(MCDCCoverage) {} 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric /// Compute the code coverage summary for the given function coverage 2480b57cec5SDimitry Andric /// mapping record. 2490b57cec5SDimitry Andric static FunctionCoverageSummary get(const coverage::CoverageMapping &CM, 2500b57cec5SDimitry Andric const coverage::FunctionRecord &Function); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric /// Compute the code coverage summary for an instantiation group \p Group, 2530b57cec5SDimitry Andric /// given a list of summaries for each instantiation in \p Summaries. 2540b57cec5SDimitry Andric static FunctionCoverageSummary 2550b57cec5SDimitry Andric get(const coverage::InstantiationGroup &Group, 2560b57cec5SDimitry Andric ArrayRef<FunctionCoverageSummary> Summaries); 2570b57cec5SDimitry Andric }; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric /// A summary of file's code coverage. 2600b57cec5SDimitry Andric struct FileCoverageSummary { 2610b57cec5SDimitry Andric StringRef Name; 2620b57cec5SDimitry Andric RegionCoverageInfo RegionCoverage; 2630b57cec5SDimitry Andric LineCoverageInfo LineCoverage; 264e8d8bef9SDimitry Andric BranchCoverageInfo BranchCoverage; 265*5f757f3fSDimitry Andric MCDCCoverageInfo MCDCCoverage; 2660b57cec5SDimitry Andric FunctionCoverageInfo FunctionCoverage; 2670b57cec5SDimitry Andric FunctionCoverageInfo InstantiationCoverage; 2680b57cec5SDimitry Andric 269*5f757f3fSDimitry Andric FileCoverageSummary() = default; 27004eeddc0SDimitry Andric FileCoverageSummary(StringRef Name) : Name(Name) {} 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) { 2730b57cec5SDimitry Andric RegionCoverage += RHS.RegionCoverage; 2740b57cec5SDimitry Andric LineCoverage += RHS.LineCoverage; 2750b57cec5SDimitry Andric FunctionCoverage += RHS.FunctionCoverage; 276e8d8bef9SDimitry Andric BranchCoverage += RHS.BranchCoverage; 277*5f757f3fSDimitry Andric MCDCCoverage += RHS.MCDCCoverage; 2780b57cec5SDimitry Andric InstantiationCoverage += RHS.InstantiationCoverage; 2790b57cec5SDimitry Andric return *this; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric void addFunction(const FunctionCoverageSummary &Function) { 2830b57cec5SDimitry Andric RegionCoverage += Function.RegionCoverage; 2840b57cec5SDimitry Andric LineCoverage += Function.LineCoverage; 285e8d8bef9SDimitry Andric BranchCoverage += Function.BranchCoverage; 286*5f757f3fSDimitry Andric MCDCCoverage += Function.MCDCCoverage; 2870b57cec5SDimitry Andric FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric void addInstantiation(const FunctionCoverageSummary &Function) { 2910b57cec5SDimitry Andric InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0); 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric }; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric /// A cache for demangled symbols. 2960b57cec5SDimitry Andric struct DemangleCache { 2970b57cec5SDimitry Andric StringMap<std::string> DemangledNames; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric /// Demangle \p Sym if possible. Otherwise, just return \p Sym. 3000b57cec5SDimitry Andric StringRef demangle(StringRef Sym) const { 3010b57cec5SDimitry Andric const auto DemangledName = DemangledNames.find(Sym); 3020b57cec5SDimitry Andric if (DemangledName == DemangledNames.end()) 3030b57cec5SDimitry Andric return Sym; 3040b57cec5SDimitry Andric return DemangledName->getValue(); 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric }; 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric } // namespace llvm 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric #endif // LLVM_COV_COVERAGESUMMARYINFO_H 311