1 | //===- CoverageSummaryInfo.cpp - 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 | #include "CoverageSummaryInfo.h" |
15 | |
16 | using namespace llvm; |
17 | using namespace coverage; |
18 | |
19 | static void sumBranches(size_t &NumBranches, size_t &CoveredBranches, |
20 | const ArrayRef<CountedRegion> &Branches) { |
21 | for (const auto &BR : Branches) { |
22 | // Skip folded branches. |
23 | if (BR.Folded) |
24 | continue; |
25 | |
26 | // "True" Condition Branches. |
27 | ++NumBranches; |
28 | if (BR.ExecutionCount > 0) |
29 | ++CoveredBranches; |
30 | // "False" Condition Branches. |
31 | ++NumBranches; |
32 | if (BR.FalseExecutionCount > 0) |
33 | ++CoveredBranches; |
34 | } |
35 | } |
36 | |
37 | static void sumBranchExpansions(size_t &NumBranches, size_t &CoveredBranches, |
38 | const CoverageMapping &CM, |
39 | ArrayRef<ExpansionRecord> Expansions) { |
40 | for (const auto &Expansion : Expansions) { |
41 | auto CE = CM.getCoverageForExpansion(Expansion); |
42 | sumBranches(NumBranches, CoveredBranches, Branches: CE.getBranches()); |
43 | sumBranchExpansions(NumBranches, CoveredBranches, CM, Expansions: CE.getExpansions()); |
44 | } |
45 | } |
46 | |
47 | static std::pair<size_t, size_t> |
48 | sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) { |
49 | size_t NumPairs = 0, CoveredPairs = 0; |
50 | for (const auto &Record : Records) { |
51 | const auto NumConditions = Record.getNumConditions(); |
52 | for (unsigned C = 0; C < NumConditions; C++) { |
53 | if (!Record.isCondFolded(Condition: C)) |
54 | ++NumPairs; |
55 | if (Record.isConditionIndependencePairCovered(Condition: C)) |
56 | ++CoveredPairs; |
57 | } |
58 | } |
59 | return {NumPairs, CoveredPairs}; |
60 | } |
61 | |
62 | FunctionCoverageSummary |
63 | FunctionCoverageSummary::get(const CoverageMapping &CM, |
64 | const coverage::FunctionRecord &Function) { |
65 | // Compute the region coverage. |
66 | size_t NumCodeRegions = 0, CoveredRegions = 0; |
67 | for (auto &CR : Function.CountedRegions) { |
68 | if (CR.Kind != CounterMappingRegion::CodeRegion) |
69 | continue; |
70 | ++NumCodeRegions; |
71 | if (CR.ExecutionCount != 0) |
72 | ++CoveredRegions; |
73 | } |
74 | |
75 | // Compute the line coverage |
76 | size_t NumLines = 0, CoveredLines = 0; |
77 | CoverageData CD = CM.getCoverageForFunction(Function); |
78 | for (const auto &LCS : getLineCoverageStats(CD)) { |
79 | if (!LCS.isMapped()) |
80 | continue; |
81 | ++NumLines; |
82 | if (LCS.getExecutionCount()) |
83 | ++CoveredLines; |
84 | } |
85 | |
86 | // Compute the branch coverage, including branches from expansions. |
87 | size_t NumBranches = 0, CoveredBranches = 0; |
88 | sumBranches(NumBranches, CoveredBranches, Branches: CD.getBranches()); |
89 | sumBranchExpansions(NumBranches, CoveredBranches, CM, Expansions: CD.getExpansions()); |
90 | |
91 | size_t NumPairs = 0, CoveredPairs = 0; |
92 | std::tie(args&: NumPairs, args&: CoveredPairs) = sumMCDCPairs(Records: CD.getMCDCRecords()); |
93 | |
94 | return FunctionCoverageSummary( |
95 | Function.Name, Function.ExecutionCount, |
96 | RegionCoverageInfo(CoveredRegions, NumCodeRegions), |
97 | LineCoverageInfo(CoveredLines, NumLines), |
98 | BranchCoverageInfo(CoveredBranches, NumBranches), |
99 | MCDCCoverageInfo(CoveredPairs, NumPairs)); |
100 | } |
101 | |
102 | FunctionCoverageSummary |
103 | FunctionCoverageSummary::get(const InstantiationGroup &Group, |
104 | ArrayRef<FunctionCoverageSummary> Summaries) { |
105 | std::string Name; |
106 | if (Group.hasName()) { |
107 | Name = std::string(Group.getName()); |
108 | } else { |
109 | llvm::raw_string_ostream OS(Name); |
110 | OS << "Definition at line " << Group.getLine() << ", column " |
111 | << Group.getColumn(); |
112 | } |
113 | |
114 | FunctionCoverageSummary Summary(Name); |
115 | Summary.ExecutionCount = Group.getTotalExecutionCount(); |
116 | Summary.RegionCoverage = Summaries[0].RegionCoverage; |
117 | Summary.LineCoverage = Summaries[0].LineCoverage; |
118 | Summary.BranchCoverage = Summaries[0].BranchCoverage; |
119 | Summary.MCDCCoverage = Summaries[0].MCDCCoverage; |
120 | for (const auto &FCS : Summaries.drop_front()) { |
121 | Summary.RegionCoverage.merge(RHS: FCS.RegionCoverage); |
122 | Summary.LineCoverage.merge(RHS: FCS.LineCoverage); |
123 | Summary.BranchCoverage.merge(RHS: FCS.BranchCoverage); |
124 | Summary.MCDCCoverage.merge(RHS: FCS.MCDCCoverage); |
125 | } |
126 | return Summary; |
127 | } |
128 | |