10b57cec5SDimitry Andric //===- CoverageSummaryInfo.cpp - 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 #include "CoverageSummaryInfo.h" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric using namespace llvm; 170b57cec5SDimitry Andric using namespace coverage; 180b57cec5SDimitry Andric 19e8d8bef9SDimitry Andric static void sumBranches(size_t &NumBranches, size_t &CoveredBranches, 20e8d8bef9SDimitry Andric const ArrayRef<CountedRegion> &Branches) { 21e8d8bef9SDimitry Andric for (const auto &BR : Branches) { 22e8d8bef9SDimitry Andric // Skip folded branches. 23e8d8bef9SDimitry Andric if (BR.Folded) 24e8d8bef9SDimitry Andric continue; 25e8d8bef9SDimitry Andric 26e8d8bef9SDimitry Andric // "True" Condition Branches. 27e8d8bef9SDimitry Andric ++NumBranches; 28e8d8bef9SDimitry Andric if (BR.ExecutionCount > 0) 29e8d8bef9SDimitry Andric ++CoveredBranches; 30e8d8bef9SDimitry Andric // "False" Condition Branches. 31e8d8bef9SDimitry Andric ++NumBranches; 32e8d8bef9SDimitry Andric if (BR.FalseExecutionCount > 0) 33e8d8bef9SDimitry Andric ++CoveredBranches; 34e8d8bef9SDimitry Andric } 35e8d8bef9SDimitry Andric } 36e8d8bef9SDimitry Andric 37e8d8bef9SDimitry Andric static void sumBranchExpansions(size_t &NumBranches, size_t &CoveredBranches, 38e8d8bef9SDimitry Andric const CoverageMapping &CM, 39e8d8bef9SDimitry Andric ArrayRef<ExpansionRecord> Expansions) { 40e8d8bef9SDimitry Andric for (const auto &Expansion : Expansions) { 41e8d8bef9SDimitry Andric auto CE = CM.getCoverageForExpansion(Expansion); 42e8d8bef9SDimitry Andric sumBranches(NumBranches, CoveredBranches, CE.getBranches()); 43e8d8bef9SDimitry Andric sumBranchExpansions(NumBranches, CoveredBranches, CM, CE.getExpansions()); 44e8d8bef9SDimitry Andric } 45e8d8bef9SDimitry Andric } 46e8d8bef9SDimitry Andric 47*5f757f3fSDimitry Andric static std::pair<size_t, size_t> 48*5f757f3fSDimitry Andric sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) { 49*5f757f3fSDimitry Andric size_t NumPairs = 0, CoveredPairs = 0; 50*5f757f3fSDimitry Andric for (const auto &Record : Records) { 51*5f757f3fSDimitry Andric const auto NumConditions = Record.getNumConditions(); 52*5f757f3fSDimitry Andric for (unsigned C = 0; C < NumConditions; C++) { 53*5f757f3fSDimitry Andric if (!Record.isCondFolded(C)) 54*5f757f3fSDimitry Andric ++NumPairs; 55*5f757f3fSDimitry Andric if (Record.isConditionIndependencePairCovered(C)) 56*5f757f3fSDimitry Andric ++CoveredPairs; 57*5f757f3fSDimitry Andric } 58*5f757f3fSDimitry Andric } 59*5f757f3fSDimitry Andric return {NumPairs, CoveredPairs}; 60*5f757f3fSDimitry Andric } 61*5f757f3fSDimitry Andric 620b57cec5SDimitry Andric FunctionCoverageSummary 630b57cec5SDimitry Andric FunctionCoverageSummary::get(const CoverageMapping &CM, 640b57cec5SDimitry Andric const coverage::FunctionRecord &Function) { 650b57cec5SDimitry Andric // Compute the region coverage. 660b57cec5SDimitry Andric size_t NumCodeRegions = 0, CoveredRegions = 0; 670b57cec5SDimitry Andric for (auto &CR : Function.CountedRegions) { 680b57cec5SDimitry Andric if (CR.Kind != CounterMappingRegion::CodeRegion) 690b57cec5SDimitry Andric continue; 700b57cec5SDimitry Andric ++NumCodeRegions; 710b57cec5SDimitry Andric if (CR.ExecutionCount != 0) 720b57cec5SDimitry Andric ++CoveredRegions; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // Compute the line coverage 760b57cec5SDimitry Andric size_t NumLines = 0, CoveredLines = 0; 770b57cec5SDimitry Andric CoverageData CD = CM.getCoverageForFunction(Function); 780b57cec5SDimitry Andric for (const auto &LCS : getLineCoverageStats(CD)) { 790b57cec5SDimitry Andric if (!LCS.isMapped()) 800b57cec5SDimitry Andric continue; 810b57cec5SDimitry Andric ++NumLines; 820b57cec5SDimitry Andric if (LCS.getExecutionCount()) 830b57cec5SDimitry Andric ++CoveredLines; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 86e8d8bef9SDimitry Andric // Compute the branch coverage, including branches from expansions. 87e8d8bef9SDimitry Andric size_t NumBranches = 0, CoveredBranches = 0; 88e8d8bef9SDimitry Andric sumBranches(NumBranches, CoveredBranches, CD.getBranches()); 89e8d8bef9SDimitry Andric sumBranchExpansions(NumBranches, CoveredBranches, CM, CD.getExpansions()); 90e8d8bef9SDimitry Andric 91*5f757f3fSDimitry Andric size_t NumPairs = 0, CoveredPairs = 0; 92*5f757f3fSDimitry Andric std::tie(NumPairs, CoveredPairs) = sumMCDCPairs(CD.getMCDCRecords()); 93*5f757f3fSDimitry Andric 940b57cec5SDimitry Andric return FunctionCoverageSummary( 950b57cec5SDimitry Andric Function.Name, Function.ExecutionCount, 960b57cec5SDimitry Andric RegionCoverageInfo(CoveredRegions, NumCodeRegions), 97e8d8bef9SDimitry Andric LineCoverageInfo(CoveredLines, NumLines), 98*5f757f3fSDimitry Andric BranchCoverageInfo(CoveredBranches, NumBranches), 99*5f757f3fSDimitry Andric MCDCCoverageInfo(CoveredPairs, NumPairs)); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric FunctionCoverageSummary 1030b57cec5SDimitry Andric FunctionCoverageSummary::get(const InstantiationGroup &Group, 1040b57cec5SDimitry Andric ArrayRef<FunctionCoverageSummary> Summaries) { 1050b57cec5SDimitry Andric std::string Name; 1060b57cec5SDimitry Andric if (Group.hasName()) { 1075ffd83dbSDimitry Andric Name = std::string(Group.getName()); 1080b57cec5SDimitry Andric } else { 1090b57cec5SDimitry Andric llvm::raw_string_ostream OS(Name); 1100b57cec5SDimitry Andric OS << "Definition at line " << Group.getLine() << ", column " 1110b57cec5SDimitry Andric << Group.getColumn(); 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric FunctionCoverageSummary Summary(Name); 1150b57cec5SDimitry Andric Summary.ExecutionCount = Group.getTotalExecutionCount(); 1160b57cec5SDimitry Andric Summary.RegionCoverage = Summaries[0].RegionCoverage; 1170b57cec5SDimitry Andric Summary.LineCoverage = Summaries[0].LineCoverage; 118e8d8bef9SDimitry Andric Summary.BranchCoverage = Summaries[0].BranchCoverage; 119*5f757f3fSDimitry Andric Summary.MCDCCoverage = Summaries[0].MCDCCoverage; 1200b57cec5SDimitry Andric for (const auto &FCS : Summaries.drop_front()) { 1210b57cec5SDimitry Andric Summary.RegionCoverage.merge(FCS.RegionCoverage); 1220b57cec5SDimitry Andric Summary.LineCoverage.merge(FCS.LineCoverage); 1234652422eSDimitry Andric Summary.BranchCoverage.merge(FCS.BranchCoverage); 124*5f757f3fSDimitry Andric Summary.MCDCCoverage.merge(FCS.MCDCCoverage); 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric return Summary; 1270b57cec5SDimitry Andric } 128