xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===//
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 // Code coverage mapping data is generated by clang and read by
10 // llvm-cov to show code coverage statistics for a file.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
15 #define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/BitVector.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/DenseSet.h"
21 #include "llvm/ADT/Hashing.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/iterator.h"
24 #include "llvm/ADT/iterator_range.h"
25 #include "llvm/Object/BuildID.h"
26 #include "llvm/ProfileData/Coverage/MCDCTypes.h"
27 #include "llvm/ProfileData/InstrProf.h"
28 #include "llvm/Support/Alignment.h"
29 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/Endian.h"
32 #include "llvm/Support/Error.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include <algorithm>
35 #include <cassert>
36 #include <cstdint>
37 #include <iterator>
38 #include <map>
39 #include <memory>
40 #include <optional>
41 #include <sstream>
42 #include <string>
43 #include <system_error>
44 #include <utility>
45 #include <vector>
46 
47 namespace llvm {
48 
49 class IndexedInstrProfReader;
50 
51 namespace object {
52 class BuildIDFetcher;
53 } // namespace object
54 
55 namespace vfs {
56 class FileSystem;
57 } // namespace vfs
58 
59 namespace coverage {
60 
61 class CoverageMappingReader;
62 struct CoverageMappingRecord;
63 
64 enum class coveragemap_error {
65   success = 0,
66   eof,
67   no_data_found,
68   unsupported_version,
69   truncated,
70   malformed,
71   decompression_failed,
72   invalid_or_missing_arch_specifier
73 };
74 
75 LLVM_ABI const std::error_category &coveragemap_category();
76 
make_error_code(coveragemap_error E)77 inline std::error_code make_error_code(coveragemap_error E) {
78   return std::error_code(static_cast<int>(E), coveragemap_category());
79 }
80 
81 class LLVM_ABI CoverageMapError : public ErrorInfo<CoverageMapError> {
82 public:
83   CoverageMapError(coveragemap_error Err, const Twine &ErrStr = Twine())
Err(Err)84       : Err(Err), Msg(ErrStr.str()) {
85     assert(Err != coveragemap_error::success && "Not an error");
86   }
87 
88   std::string message() const override;
89 
log(raw_ostream & OS)90   void log(raw_ostream &OS) const override { OS << message(); }
91 
convertToErrorCode()92   std::error_code convertToErrorCode() const override {
93     return make_error_code(Err);
94   }
95 
get()96   coveragemap_error get() const { return Err; }
getMessage()97   const std::string &getMessage() const { return Msg; }
98 
99   static char ID;
100 
101 private:
102   coveragemap_error Err;
103   std::string Msg;
104 };
105 
106 /// A Counter is an abstract value that describes how to compute the
107 /// execution count for a region of code using the collected profile count data.
108 struct Counter {
109   /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to
110   /// the CounterKind. This means CounterKind has to leave bit 0 free.
111   enum CounterKind { Zero, CounterValueReference, Expression };
112   static const unsigned EncodingTagBits = 2;
113   static const unsigned EncodingTagMask = 0x3;
114   static const unsigned EncodingCounterTagAndExpansionRegionTagBits =
115       EncodingTagBits + 1;
116 
117 private:
118   CounterKind Kind = Zero;
119   unsigned ID = 0;
120 
CounterCounter121   Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
122 
123 public:
124   Counter() = default;
125 
getKindCounter126   CounterKind getKind() const { return Kind; }
127 
isZeroCounter128   bool isZero() const { return Kind == Zero; }
129 
isExpressionCounter130   bool isExpression() const { return Kind == Expression; }
131 
getCounterIDCounter132   unsigned getCounterID() const { return ID; }
133 
getExpressionIDCounter134   unsigned getExpressionID() const { return ID; }
135 
136   friend bool operator==(const Counter &LHS, const Counter &RHS) {
137     return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID;
138   }
139 
140   friend bool operator!=(const Counter &LHS, const Counter &RHS) {
141     return !(LHS == RHS);
142   }
143 
144   friend bool operator<(const Counter &LHS, const Counter &RHS) {
145     return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID);
146   }
147 
148   /// Return the counter that represents the number zero.
getZeroCounter149   static Counter getZero() { return Counter(); }
150 
151   /// Return the counter that corresponds to a specific profile counter.
getCounterCounter152   static Counter getCounter(unsigned CounterId) {
153     return Counter(CounterValueReference, CounterId);
154   }
155 
156   /// Return the counter that corresponds to a specific addition counter
157   /// expression.
getExpressionCounter158   static Counter getExpression(unsigned ExpressionId) {
159     return Counter(Expression, ExpressionId);
160   }
161 };
162 
163 /// A Counter expression is a value that represents an arithmetic operation
164 /// with two counters.
165 struct CounterExpression {
166   enum ExprKind { Subtract, Add };
167   ExprKind Kind;
168   Counter LHS, RHS;
169 
CounterExpressionCounterExpression170   CounterExpression(ExprKind Kind, Counter LHS, Counter RHS)
171       : Kind(Kind), LHS(LHS), RHS(RHS) {}
172 };
173 
174 /// A Counter expression builder is used to construct the counter expressions.
175 /// It avoids unnecessary duplication and simplifies algebraic expressions.
176 class CounterExpressionBuilder {
177   /// A list of all the counter expressions
178   std::vector<CounterExpression> Expressions;
179 
180   /// A lookup table for the index of a given expression.
181   DenseMap<CounterExpression, unsigned> ExpressionIndices;
182 
183   /// Return the counter which corresponds to the given expression.
184   ///
185   /// If the given expression is already stored in the builder, a counter
186   /// that references that expression is returned. Otherwise, the given
187   /// expression is added to the builder's collection of expressions.
188   Counter get(const CounterExpression &E);
189 
190   /// Represents a term in a counter expression tree.
191   struct Term {
192     unsigned CounterID;
193     int Factor;
194 
TermTerm195     Term(unsigned CounterID, int Factor)
196         : CounterID(CounterID), Factor(Factor) {}
197   };
198 
199   /// Gather the terms of the expression tree for processing.
200   ///
201   /// This collects each addition and subtraction referenced by the counter into
202   /// a sequence that can be sorted and combined to build a simplified counter
203   /// expression.
204   void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms);
205 
206   /// Simplifies the given expression tree
207   /// by getting rid of algebraically redundant operations.
208   Counter simplify(Counter ExpressionTree);
209 
210 public:
getExpressions()211   ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
212 
213   /// Return a counter that represents the expression that adds LHS and RHS.
214   LLVM_ABI Counter add(Counter LHS, Counter RHS, bool Simplify = true);
215 
216   /// Return a counter that represents the expression that subtracts RHS from
217   /// LHS.
218   LLVM_ABI Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
219 
220   /// K to V map. K will be Counter in most cases. V may be Counter or
221   /// Expression.
222   using SubstMap = std::map<Counter, Counter>;
223 
224   /// \return A counter equivalent to \C, with each term in its
225   /// expression replaced with term from \p Map.
226   LLVM_ABI Counter subst(Counter C, const SubstMap &Map);
227 };
228 
229 using LineColPair = std::pair<unsigned, unsigned>;
230 
231 /// A Counter mapping region associates a source range with a specific counter.
232 struct CounterMappingRegion {
233   enum RegionKind {
234     /// A CodeRegion associates some code with a counter
235     CodeRegion,
236 
237     /// An ExpansionRegion represents a file expansion region that associates
238     /// a source range with the expansion of a virtual source file, such as
239     /// for a macro instantiation or #include file.
240     ExpansionRegion,
241 
242     /// A SkippedRegion represents a source range with code that was skipped
243     /// by a preprocessor or similar means.
244     SkippedRegion,
245 
246     /// A GapRegion is like a CodeRegion, but its count is only set as the
247     /// line execution count when its the only region in the line.
248     GapRegion,
249 
250     /// A BranchRegion represents leaf-level boolean expressions and is
251     /// associated with two counters, each representing the number of times the
252     /// expression evaluates to true or false.
253     BranchRegion,
254 
255     /// A DecisionRegion represents a top-level boolean expression and is
256     /// associated with a variable length bitmap index and condition number.
257     MCDCDecisionRegion,
258 
259     /// A Branch Region can be extended to include IDs to facilitate MC/DC.
260     MCDCBranchRegion
261   };
262 
263   /// Primary Counter that is also used for Branch Regions (TrueCount).
264   Counter Count;
265 
266   /// Secondary Counter used for Branch Regions (FalseCount).
267   Counter FalseCount;
268 
269   /// Parameters used for Modified Condition/Decision Coverage
270   mcdc::Parameters MCDCParams;
271 
getDecisionParamsCounterMappingRegion272   const auto &getDecisionParams() const {
273     return mcdc::getParams<const mcdc::DecisionParameters>(MCDCParams);
274   }
275 
getBranchParamsCounterMappingRegion276   const auto &getBranchParams() const {
277     return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams);
278   }
279 
280   unsigned FileID = 0;
281   unsigned ExpandedFileID = 0;
282   unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
283 
284   RegionKind Kind;
285 
isBranchCounterMappingRegion286   bool isBranch() const {
287     return (Kind == BranchRegion || Kind == MCDCBranchRegion);
288   }
289 
CounterMappingRegionCounterMappingRegion290   CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID,
291                        unsigned LineStart, unsigned ColumnStart,
292                        unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
293       : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID),
294         LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd),
295         ColumnEnd(ColumnEnd), Kind(Kind) {}
296 
297   CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID,
298                        unsigned ExpandedFileID, unsigned LineStart,
299                        unsigned ColumnStart, unsigned LineEnd,
300                        unsigned ColumnEnd, RegionKind Kind,
301                        const mcdc::Parameters &MCDCParams = std::monostate())
CountCounterMappingRegion302       : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
303         FileID(FileID), ExpandedFileID(ExpandedFileID), LineStart(LineStart),
304         ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
305         Kind(Kind) {}
306 
CounterMappingRegionCounterMappingRegion307   CounterMappingRegion(const mcdc::DecisionParameters &MCDCParams,
308                        unsigned FileID, unsigned LineStart,
309                        unsigned ColumnStart, unsigned LineEnd,
310                        unsigned ColumnEnd, RegionKind Kind)
311       : MCDCParams(MCDCParams), FileID(FileID), LineStart(LineStart),
312         ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
313         Kind(Kind) {}
314 
315   static CounterMappingRegion
makeRegionCounterMappingRegion316   makeRegion(Counter Count, unsigned FileID, unsigned LineStart,
317              unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
318     return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart,
319                                 LineEnd, ColumnEnd, CodeRegion);
320   }
321 
322   static CounterMappingRegion
makeExpansionCounterMappingRegion323   makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
324                 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
325     return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart,
326                                 ColumnStart, LineEnd, ColumnEnd,
327                                 ExpansionRegion);
328   }
329 
330   static CounterMappingRegion
makeSkippedCounterMappingRegion331   makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
332               unsigned LineEnd, unsigned ColumnEnd) {
333     return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart,
334                                 LineEnd, ColumnEnd, SkippedRegion);
335   }
336 
337   static CounterMappingRegion
makeGapRegionCounterMappingRegion338   makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart,
339                 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
340     return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart,
341                                 LineEnd, (1U << 31) | ColumnEnd, GapRegion);
342   }
343 
344   static CounterMappingRegion
345   makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID,
346                    unsigned LineStart, unsigned ColumnStart, unsigned LineEnd,
347                    unsigned ColumnEnd,
348                    const mcdc::Parameters &MCDCParams = std::monostate()) {
349     return CounterMappingRegion(
350         Count, FalseCount, FileID, 0, LineStart, ColumnStart, LineEnd,
351         ColumnEnd,
352         (std::get_if<mcdc::BranchParameters>(&MCDCParams) ? MCDCBranchRegion
353                                                           : BranchRegion),
354         MCDCParams);
355   }
356 
357   static CounterMappingRegion
makeDecisionRegionCounterMappingRegion358   makeDecisionRegion(const mcdc::DecisionParameters &MCDCParams,
359                      unsigned FileID, unsigned LineStart, unsigned ColumnStart,
360                      unsigned LineEnd, unsigned ColumnEnd) {
361     return CounterMappingRegion(MCDCParams, FileID, LineStart, ColumnStart,
362                                 LineEnd, ColumnEnd, MCDCDecisionRegion);
363   }
364 
startLocCounterMappingRegion365   inline LineColPair startLoc() const {
366     return LineColPair(LineStart, ColumnStart);
367   }
368 
endLocCounterMappingRegion369   inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); }
370 };
371 
372 /// Associates a source range with an execution count.
373 struct CountedRegion : public CounterMappingRegion {
374   uint64_t ExecutionCount;
375   uint64_t FalseExecutionCount;
376   bool TrueFolded;
377   bool FalseFolded;
378 
CountedRegionCountedRegion379   CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
380       : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
381         FalseExecutionCount(0), TrueFolded(false), FalseFolded(true) {}
382 
CountedRegionCountedRegion383   CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
384                 uint64_t FalseExecutionCount)
385       : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
386         FalseExecutionCount(FalseExecutionCount), TrueFolded(false),
387         FalseFolded(false) {}
388 };
389 
390 /// MCDC Record grouping all information together.
391 struct MCDCRecord {
392   /// CondState represents the evaluation of a condition in an executed test
393   /// vector, which can be True or False. A DontCare is used to mask an
394   /// unevaluatable condition resulting from short-circuit behavior of logical
395   /// operators in languages like C/C++. When comparing the evaluation of a
396   /// condition across executed test vectors, comparisons against a DontCare
397   /// are effectively ignored.
398   enum CondState { MCDC_DontCare = -1, MCDC_False = 0, MCDC_True = 1 };
399 
400   /// Emulate SmallVector<CondState> with a pair of BitVector.
401   ///
402   ///          True  False DontCare (Impossible)
403   /// Values:  True  False False    True
404   /// Visited: True  True  False    False
405   class TestVector {
406     BitVector Values;  /// True/False (False when DontCare)
407     BitVector Visited; /// ~DontCare
408 
409   public:
410     /// Default values are filled with DontCare.
TestVectorMCDCRecord411     TestVector(unsigned N) : Values(N), Visited(N) {}
412 
413     /// Emulate RHS SmallVector::operator[]
414     CondState operator[](int I) const {
415       return (Visited[I] ? (Values[I] ? MCDC_True : MCDC_False)
416                          : MCDC_DontCare);
417     }
418 
419     /// Equivalent to buildTestVector's Index.
getIndexMCDCRecord420     auto getIndex() const { return Values.getData()[0]; }
421 
422     /// Set the condition \p Val at position \p I.
423     /// This emulates LHS SmallVector::operator[].
setMCDCRecord424     void set(int I, CondState Val) {
425       Visited[I] = (Val != MCDC_DontCare);
426       Values[I] = (Val == MCDC_True);
427     }
428 
429     /// Emulate SmallVector::push_back.
push_backMCDCRecord430     void push_back(CondState Val) {
431       Visited.push_back(Val != MCDC_DontCare);
432       Values.push_back(Val == MCDC_True);
433       assert(Values.size() == Visited.size());
434     }
435 
436     /// For each element:
437     /// - False if either is DontCare
438     /// - False if both have the same value
439     /// - True if both have the opposite value
440     /// ((A.Values ^ B.Values) & A.Visited & B.Visited)
441     /// Dedicated to findIndependencePairs().
getDifferencesMCDCRecord442     auto getDifferences(const TestVector &B) const {
443       const auto &A = *this;
444       BitVector AB = A.Values;
445       AB ^= B.Values;
446       AB &= A.Visited;
447       AB &= B.Visited;
448       return AB;
449     }
450   };
451 
452   using TestVectors = llvm::SmallVector<std::pair<TestVector, CondState>>;
453   using BoolVector = std::array<BitVector, 2>;
454   using TVRowPair = std::pair<unsigned, unsigned>;
455   using TVPairMap = llvm::DenseMap<unsigned, TVRowPair>;
456   using CondIDMap = llvm::DenseMap<unsigned, unsigned>;
457   using LineColPairMap = llvm::DenseMap<unsigned, LineColPair>;
458 
459 private:
460   CounterMappingRegion Region;
461   TestVectors TV;
462   std::optional<TVPairMap> IndependencePairs;
463   BoolVector Folded;
464   CondIDMap PosToID;
465   LineColPairMap CondLoc;
466 
467 public:
MCDCRecordMCDCRecord468   MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV,
469              BoolVector &&Folded, CondIDMap &&PosToID, LineColPairMap &&CondLoc)
470       : Region(Region), TV(std::move(TV)), Folded(std::move(Folded)),
471         PosToID(std::move(PosToID)), CondLoc(std::move(CondLoc)) {
472     findIndependencePairs();
473   }
474 
475   // Compare executed test vectors against each other to find an independence
476   // pairs for each condition.  This processing takes the most time.
477   LLVM_ABI void findIndependencePairs();
478 
getDecisionRegionMCDCRecord479   const CounterMappingRegion &getDecisionRegion() const { return Region; }
getNumConditionsMCDCRecord480   unsigned getNumConditions() const {
481     return Region.getDecisionParams().NumConditions;
482   }
getNumTestVectorsMCDCRecord483   unsigned getNumTestVectors() const { return TV.size(); }
isCondFoldedMCDCRecord484   bool isCondFolded(unsigned Condition) const {
485     return Folded[false][Condition] || Folded[true][Condition];
486   }
487 
488   /// Return the evaluation of a condition (indicated by Condition) in an
489   /// executed test vector (indicated by TestVectorIndex), which will be True,
490   /// False, or DontCare if the condition is unevaluatable. Because condition
491   /// IDs are not associated based on their position in the expression,
492   /// accessing conditions in the TestVectors requires a translation from a
493   /// ordinal position to actual condition ID. This is done via PosToID[].
getTVConditionMCDCRecord494   CondState getTVCondition(unsigned TestVectorIndex, unsigned Condition) {
495     return TV[TestVectorIndex].first[PosToID[Condition]];
496   }
497 
498   /// Return the number of True and False decisions for all executed test
499   /// vectors.
getDecisionsMCDCRecord500   std::pair<unsigned, unsigned> getDecisions() const {
501     const unsigned TrueDecisions =
502         llvm::count(llvm::make_second_range(TV), CondState::MCDC_True);
503 
504     return {TrueDecisions, TV.size() - TrueDecisions};
505   }
506 
507   /// Return the Result evaluation for an executed test vector.
508   /// See MCDCRecordProcessor::RecordTestVector().
getTVResultMCDCRecord509   CondState getTVResult(unsigned TestVectorIndex) {
510     return TV[TestVectorIndex].second;
511   }
512 
513   /// Determine whether a given condition (indicated by Condition) is covered
514   /// by an Independence Pair. Because condition IDs are not associated based
515   /// on their position in the expression, accessing conditions in the
516   /// TestVectors requires a translation from a ordinal position to actual
517   /// condition ID. This is done via PosToID[].
isConditionIndependencePairCoveredMCDCRecord518   bool isConditionIndependencePairCovered(unsigned Condition) const {
519     assert(IndependencePairs);
520     auto It = PosToID.find(Condition);
521     assert(It != PosToID.end() && "Condition ID without an Ordinal mapping");
522     return IndependencePairs->contains(It->second);
523   }
524 
525   /// Return the Independence Pair that covers the given condition. Because
526   /// condition IDs are not associated based on their position in the
527   /// expression, accessing conditions in the TestVectors requires a
528   /// translation from a ordinal position to actual condition ID. This is done
529   /// via PosToID[].
getConditionIndependencePairMCDCRecord530   TVRowPair getConditionIndependencePair(unsigned Condition) {
531     assert(isConditionIndependencePairCovered(Condition));
532     assert(IndependencePairs);
533     return (*IndependencePairs)[PosToID[Condition]];
534   }
535 
getPercentCoveredMCDCRecord536   float getPercentCovered() const {
537     unsigned Folded = 0;
538     unsigned Covered = 0;
539     for (unsigned C = 0; C < getNumConditions(); C++) {
540       if (isCondFolded(C))
541         Folded++;
542       else if (isConditionIndependencePairCovered(C))
543         Covered++;
544     }
545 
546     unsigned Total = getNumConditions() - Folded;
547     if (Total == 0)
548       return 0.0;
549     return (static_cast<double>(Covered) / static_cast<double>(Total)) * 100.0;
550   }
551 
getConditionHeaderStringMCDCRecord552   std::string getConditionHeaderString(unsigned Condition) {
553     std::ostringstream OS;
554     const auto &[Line, Col] = CondLoc[Condition];
555     OS << "Condition C" << Condition + 1 << " --> (" << Line << ":" << Col
556        << ")\n";
557     return OS.str();
558   }
559 
getTestVectorHeaderStringMCDCRecord560   std::string getTestVectorHeaderString() const {
561     std::ostringstream OS;
562     if (getNumTestVectors() == 0) {
563       OS << "None.\n";
564       return OS.str();
565     }
566     const auto NumConditions = getNumConditions();
567     for (unsigned I = 0; I < NumConditions; I++) {
568       OS << "C" << I + 1;
569       if (I != NumConditions - 1)
570         OS << ", ";
571     }
572     OS << "    Result\n";
573     return OS.str();
574   }
575 
getTestVectorStringMCDCRecord576   std::string getTestVectorString(unsigned TestVectorIndex) {
577     assert(TestVectorIndex < getNumTestVectors() &&
578            "TestVector index out of bounds!");
579     std::ostringstream OS;
580     const auto NumConditions = getNumConditions();
581     // Add individual condition values to the string.
582     OS << "  " << TestVectorIndex + 1 << " { ";
583     for (unsigned Condition = 0; Condition < NumConditions; Condition++) {
584       if (isCondFolded(Condition))
585         OS << "C";
586       else {
587         switch (getTVCondition(TestVectorIndex, Condition)) {
588         case MCDCRecord::MCDC_DontCare:
589           OS << "-";
590           break;
591         case MCDCRecord::MCDC_True:
592           OS << "T";
593           break;
594         case MCDCRecord::MCDC_False:
595           OS << "F";
596           break;
597         }
598       }
599       if (Condition != NumConditions - 1)
600         OS << ",  ";
601     }
602 
603     // Add result value to the string.
604     OS << "  = ";
605     if (getTVResult(TestVectorIndex) == MCDC_True)
606       OS << "T";
607     else
608       OS << "F";
609     OS << "      }\n";
610 
611     return OS.str();
612   }
613 
getConditionCoverageStringMCDCRecord614   std::string getConditionCoverageString(unsigned Condition) {
615     assert(Condition < getNumConditions() &&
616            "Condition index is out of bounds!");
617     std::ostringstream OS;
618 
619     OS << "  C" << Condition + 1 << "-Pair: ";
620     if (isCondFolded(Condition)) {
621       OS << "constant folded\n";
622     } else if (isConditionIndependencePairCovered(Condition)) {
623       TVRowPair rows = getConditionIndependencePair(Condition);
624       OS << "covered: (" << rows.first << ",";
625       OS << rows.second << ")\n";
626     } else
627       OS << "not covered\n";
628 
629     return OS.str();
630   }
631 };
632 
633 namespace mcdc {
634 /// Compute TestVector Indices "TVIdx" from the Conds graph.
635 ///
636 /// Clang CodeGen handles the bitmap index based on TVIdx.
637 /// llvm-cov reconstructs conditions from TVIdx.
638 ///
639 /// For each leaf "The final decision",
640 /// - TVIdx should be unique.
641 /// - TVIdx has the Width.
642 ///   - The width represents the number of possible paths.
643 ///   - The minimum width is 1 "deterministic".
644 /// - The order of leaves are sorted by Width DESC. It expects
645 ///   latter TVIdx(s) (with Width=1) could be pruned and altered to
646 ///   other simple branch conditions.
647 ///
648 class TVIdxBuilder {
649 public:
650   struct MCDCNode {
651     int InCount = 0; /// Reference count; temporary use
652     int Width;       /// Number of accumulated paths (>= 1)
653     ConditionIDs NextIDs;
654   };
655 
656 #ifndef NDEBUG
657   /// This is no longer needed after the assignment.
658   /// It may be used in assert() for reconfirmation.
659   SmallVector<MCDCNode> SavedNodes;
660 #endif
661 
662   /// Output: Index for TestVectors bitmap (These are not CondIDs)
663   SmallVector<std::array<int, 2>> Indices;
664 
665   /// Output: The number of test vectors.
666   /// Error with HardMaxTVs if the number has exploded.
667   int NumTestVectors;
668 
669   /// Hard limit of test vectors
670   static constexpr auto HardMaxTVs =
671       std::numeric_limits<decltype(NumTestVectors)>::max();
672 
673 public:
674   /// Calculate and assign Indices
675   /// \param NextIDs The list of {FalseID, TrueID} indexed by ID
676   ///        The first element [0] should be the root node.
677   /// \param Offset Offset of index to final decisions.
678   LLVM_ABI TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs,
679                         int Offset = 0);
680 };
681 } // namespace mcdc
682 
683 /// A Counter mapping context is used to connect the counters, expressions
684 /// and the obtained counter values.
685 class CounterMappingContext {
686   ArrayRef<CounterExpression> Expressions;
687   ArrayRef<uint64_t> CounterValues;
688   BitVector Bitmap;
689 
690 public:
691   CounterMappingContext(ArrayRef<CounterExpression> Expressions,
692                         ArrayRef<uint64_t> CounterValues = {})
Expressions(Expressions)693       : Expressions(Expressions), CounterValues(CounterValues) {}
694 
setCounts(ArrayRef<uint64_t> Counts)695   void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
setBitmap(BitVector && Bitmap_)696   void setBitmap(BitVector &&Bitmap_) { Bitmap = std::move(Bitmap_); }
697 
698   LLVM_ABI void dump(const Counter &C, raw_ostream &OS) const;
dump(const Counter & C)699   void dump(const Counter &C) const { dump(C, dbgs()); }
700 
701   /// Return the number of times that a region of code associated with this
702   /// counter was executed.
703   LLVM_ABI Expected<int64_t> evaluate(const Counter &C) const;
704 
705   /// Return an MCDC record that indicates executed test vectors and condition
706   /// pairs.
707   LLVM_ABI Expected<MCDCRecord>
708   evaluateMCDCRegion(const CounterMappingRegion &Region,
709                      ArrayRef<const CounterMappingRegion *> Branches,
710                      bool IsVersion11);
711 
712   LLVM_ABI unsigned getMaxCounterID(const Counter &C) const;
713 };
714 
715 /// Code coverage information for a single function.
716 struct FunctionRecord {
717   /// Raw function name.
718   std::string Name;
719   /// Mapping from FileID (i.e. vector index) to filename. Used to support
720   /// macro expansions within a function in which the macro and function are
721   /// defined in separate files.
722   ///
723   /// TODO: Uniquing filenames across all function records may be a performance
724   /// optimization.
725   std::vector<std::string> Filenames;
726   /// Regions in the function along with their counts.
727   std::vector<CountedRegion> CountedRegions;
728   /// Branch Regions in the function along with their counts.
729   std::vector<CountedRegion> CountedBranchRegions;
730   /// MCDC Records record a DecisionRegion and associated BranchRegions.
731   std::vector<MCDCRecord> MCDCRecords;
732   /// The number of times this function was executed.
733   uint64_t ExecutionCount = 0;
734 
FunctionRecordFunctionRecord735   FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
736       : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
737 
738   FunctionRecord(FunctionRecord &&FR) = default;
739   FunctionRecord &operator=(FunctionRecord &&) = default;
740 
pushMCDCRecordFunctionRecord741   void pushMCDCRecord(MCDCRecord &&Record) {
742     MCDCRecords.push_back(std::move(Record));
743   }
744 
pushRegionFunctionRecord745   void pushRegion(CounterMappingRegion Region, uint64_t Count,
746                   uint64_t FalseCount) {
747     if (Region.isBranch()) {
748       CountedBranchRegions.emplace_back(Region, Count, FalseCount);
749       // If either counter is hard-coded to zero, then this region represents a
750       // constant-folded branch.
751       CountedBranchRegions.back().TrueFolded = Region.Count.isZero();
752       CountedBranchRegions.back().FalseFolded = Region.FalseCount.isZero();
753       return;
754     }
755     if (CountedRegions.empty())
756       ExecutionCount = Count;
757     CountedRegions.emplace_back(Region, Count, FalseCount);
758   }
759 };
760 
761 /// Iterator over Functions, optionally filtered to a single file.
762 /// When filtering to a single file, the iterator requires a list of potential
763 /// indices where to find the desired records to avoid quadratic behavior when
764 /// repeatedly iterating over functions from different files.
765 class FunctionRecordIterator
766     : public iterator_facade_base<FunctionRecordIterator,
767                                   std::forward_iterator_tag, FunctionRecord> {
768   ArrayRef<FunctionRecord> Records;
769   ArrayRef<unsigned> RecordIndices;
770   ArrayRef<unsigned>::iterator CurrentIndex;
771   ArrayRef<FunctionRecord>::iterator Current;
772   StringRef Filename;
773 
774   /// Skip records whose primary file is not \c Filename.
775   LLVM_ABI void skipOtherFiles();
776 
777 public:
778   FunctionRecordIterator(ArrayRef<FunctionRecord> Records_,
779                          StringRef Filename = "",
780                          ArrayRef<unsigned> RecordIndices_ = {})
Records(Records_)781       : Records(Records_), RecordIndices(RecordIndices_),
782         CurrentIndex(RecordIndices.begin()),
783         // If `RecordIndices` is provided, we can skip directly to the first
784         // index it provides.
785         Current(CurrentIndex == RecordIndices.end() ? Records.begin()
786                                                     : &Records[*CurrentIndex]),
787         Filename(Filename) {
788     assert(Filename.empty() == RecordIndices_.empty() &&
789            "If `Filename` is specified, `RecordIndices` must also be provided");
790     skipOtherFiles();
791   }
792 
FunctionRecordIterator()793   FunctionRecordIterator() : Current(Records.begin()) {}
794 
795   bool operator==(const FunctionRecordIterator &RHS) const {
796     return Current == RHS.Current && Filename == RHS.Filename;
797   }
798 
799   const FunctionRecord &operator*() const { return *Current; }
800 
801   FunctionRecordIterator &operator++() {
802     advanceOne();
803     skipOtherFiles();
804     return *this;
805   }
806 
807 private:
advanceOne()808   void advanceOne() {
809     if (RecordIndices.empty()) {
810       // Iteration over all entries, advance in the list of records.
811       assert(Current != Records.end() && "incremented past end");
812       ++Current;
813     } else {
814       // Iterator over entries filtered by file name. Advance in the list of
815       // indices, and adjust the cursor in the list of records accordingly.
816       assert(CurrentIndex != RecordIndices.end() && "incremented past end");
817       ++CurrentIndex;
818       if (CurrentIndex == RecordIndices.end()) {
819         Current = Records.end();
820       } else {
821         Current = &Records[*CurrentIndex];
822       }
823     }
824   }
825 };
826 
827 /// Coverage information for a macro expansion or #included file.
828 ///
829 /// When covered code has pieces that can be expanded for more detail, such as a
830 /// preprocessor macro use and its definition, these are represented as
831 /// expansions whose coverage can be looked up independently.
832 struct ExpansionRecord {
833   /// The abstract file this expansion covers.
834   unsigned FileID;
835   /// The region that expands to this record.
836   const CountedRegion &Region;
837   /// Coverage for the expansion.
838   const FunctionRecord &Function;
839 
ExpansionRecordExpansionRecord840   ExpansionRecord(const CountedRegion &Region,
841                   const FunctionRecord &Function)
842       : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
843 };
844 
845 /// The execution count information starting at a point in a file.
846 ///
847 /// A sequence of CoverageSegments gives execution counts for a file in format
848 /// that's simple to iterate through for processing.
849 struct CoverageSegment {
850   /// The line where this segment begins.
851   unsigned Line;
852   /// The column where this segment begins.
853   unsigned Col;
854   /// The execution count, or zero if no count was recorded.
855   uint64_t Count;
856   /// When false, the segment was uninstrumented or skipped.
857   bool HasCount;
858   /// Whether this enters a new region or returns to a previous count.
859   bool IsRegionEntry;
860   /// Whether this enters a gap region.
861   bool IsGapRegion;
862 
CoverageSegmentCoverageSegment863   CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
864       : Line(Line), Col(Col), Count(0), HasCount(false),
865         IsRegionEntry(IsRegionEntry), IsGapRegion(false) {}
866 
867   CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
868                   bool IsRegionEntry, bool IsGapRegion = false,
869                   bool IsBranchRegion = false)
LineCoverageSegment870       : Line(Line), Col(Col), Count(Count), HasCount(true),
871         IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {}
872 
873   friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) {
874     return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry,
875                     L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count,
876                                                R.HasCount, R.IsRegionEntry,
877                                                R.IsGapRegion);
878   }
879 };
880 
881 /// An instantiation group contains a \c FunctionRecord list, such that each
882 /// record corresponds to a distinct instantiation of the same function.
883 ///
884 /// Note that it's possible for a function to have more than one instantiation
885 /// (consider C++ template specializations or static inline functions).
886 class InstantiationGroup {
887   friend class CoverageMapping;
888 
889   unsigned Line;
890   unsigned Col;
891   std::vector<const FunctionRecord *> Instantiations;
892 
InstantiationGroup(unsigned Line,unsigned Col,std::vector<const FunctionRecord * > Instantiations)893   InstantiationGroup(unsigned Line, unsigned Col,
894                      std::vector<const FunctionRecord *> Instantiations)
895       : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {}
896 
897 public:
898   InstantiationGroup(const InstantiationGroup &) = delete;
899   InstantiationGroup(InstantiationGroup &&) = default;
900 
901   /// Get the number of instantiations in this group.
size()902   size_t size() const { return Instantiations.size(); }
903 
904   /// Get the line where the common function was defined.
getLine()905   unsigned getLine() const { return Line; }
906 
907   /// Get the column where the common function was defined.
getColumn()908   unsigned getColumn() const { return Col; }
909 
910   /// Check if the instantiations in this group have a common mangled name.
hasName()911   bool hasName() const {
912     for (unsigned I = 1, E = Instantiations.size(); I < E; ++I)
913       if (Instantiations[I]->Name != Instantiations[0]->Name)
914         return false;
915     return true;
916   }
917 
918   /// Get the common mangled name for instantiations in this group.
getName()919   StringRef getName() const {
920     assert(hasName() && "Instantiations don't have a shared name");
921     return Instantiations[0]->Name;
922   }
923 
924   /// Get the total execution count of all instantiations in this group.
getTotalExecutionCount()925   uint64_t getTotalExecutionCount() const {
926     uint64_t Count = 0;
927     for (const FunctionRecord *F : Instantiations)
928       Count += F->ExecutionCount;
929     return Count;
930   }
931 
932   /// Get the instantiations in this group.
getInstantiations()933   ArrayRef<const FunctionRecord *> getInstantiations() const {
934     return Instantiations;
935   }
936 };
937 
938 /// Coverage information to be processed or displayed.
939 ///
940 /// This represents the coverage of an entire file, expansion, or function. It
941 /// provides a sequence of CoverageSegments to iterate through, as well as the
942 /// list of expansions that can be further processed.
943 class CoverageData {
944   friend class CoverageMapping;
945 
946   std::string Filename;
947   std::vector<CoverageSegment> Segments;
948   std::vector<ExpansionRecord> Expansions;
949   std::vector<CountedRegion> BranchRegions;
950   std::vector<MCDCRecord> MCDCRecords;
951 
952   bool SingleByteCoverage = false;
953 
954 public:
955   CoverageData() = default;
956 
CoverageData(bool Single,StringRef Filename)957   CoverageData(bool Single, StringRef Filename)
958       : Filename(Filename), SingleByteCoverage(Single) {}
959 
960   /// Get the name of the file this data covers.
getFilename()961   StringRef getFilename() const { return Filename; }
962 
getSingleByteCoverage()963   bool getSingleByteCoverage() const { return SingleByteCoverage; }
964 
965   /// Get an iterator over the coverage segments for this object. The segments
966   /// are guaranteed to be uniqued and sorted by location.
begin()967   std::vector<CoverageSegment>::const_iterator begin() const {
968     return Segments.begin();
969   }
970 
end()971   std::vector<CoverageSegment>::const_iterator end() const {
972     return Segments.end();
973   }
974 
empty()975   bool empty() const { return Segments.empty(); }
976 
977   /// Expansions that can be further processed.
getExpansions()978   ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; }
979 
980   /// Branches that can be further processed.
getBranches()981   ArrayRef<CountedRegion> getBranches() const { return BranchRegions; }
982 
983   /// MCDC Records that can be further processed.
getMCDCRecords()984   ArrayRef<MCDCRecord> getMCDCRecords() const { return MCDCRecords; }
985 };
986 
987 /// The mapping of profile information to coverage data.
988 ///
989 /// This is the main interface to get coverage information, using a profile to
990 /// fill out execution counts.
991 class CoverageMapping {
992   DenseMap<size_t, DenseSet<size_t>> RecordProvenance;
993   std::vector<FunctionRecord> Functions;
994   DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
995   std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
996 
997   std::optional<bool> SingleByteCoverage;
998 
999   CoverageMapping() = default;
1000 
1001   // Load coverage records from readers.
1002   static Error loadFromReaders(
1003       ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
1004       std::optional<std::reference_wrapper<IndexedInstrProfReader>>
1005           &ProfileReader,
1006       CoverageMapping &Coverage);
1007 
1008   // Load coverage records from file.
1009   static Error
1010   loadFromFile(StringRef Filename, StringRef Arch, StringRef CompilationDir,
1011                std::optional<std::reference_wrapper<IndexedInstrProfReader>>
1012                    &ProfileReader,
1013                CoverageMapping &Coverage, bool &DataFound,
1014                SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr);
1015 
1016   /// Add a function record corresponding to \p Record.
1017   Error loadFunctionRecord(
1018       const CoverageMappingRecord &Record,
1019       const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
1020           &ProfileReader);
1021 
1022   /// Look up the indices for function records which are at least partially
1023   /// defined in the specified file. This is guaranteed to return a superset of
1024   /// such records: extra records not in the file may be included if there is
1025   /// a hash collision on the filename. Clients must be robust to collisions.
1026   LLVM_ABI ArrayRef<unsigned>
1027   getImpreciseRecordIndicesForFilename(StringRef Filename) const;
1028 
1029 public:
1030   CoverageMapping(const CoverageMapping &) = delete;
1031   CoverageMapping &operator=(const CoverageMapping &) = delete;
1032 
1033   /// Load the coverage mapping using the given readers.
1034   LLVM_ABI static Expected<std::unique_ptr<CoverageMapping>>
1035   load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
1036        std::optional<std::reference_wrapper<IndexedInstrProfReader>>
1037            &ProfileReader);
1038 
1039   /// Load the coverage mapping from the given object files and profile. If
1040   /// \p Arches is non-empty, it must specify an architecture for each object.
1041   /// Ignores non-instrumented object files unless all are not instrumented.
1042   LLVM_ABI static Expected<std::unique_ptr<CoverageMapping>>
1043   load(ArrayRef<StringRef> ObjectFilenames,
1044        std::optional<StringRef> ProfileFilename, vfs::FileSystem &FS,
1045        ArrayRef<StringRef> Arches = {}, StringRef CompilationDir = "",
1046        const object::BuildIDFetcher *BIDFetcher = nullptr,
1047        bool CheckBinaryIDs = false);
1048 
1049   /// The number of functions that couldn't have their profiles mapped.
1050   ///
1051   /// This is a count of functions whose profile is out of date or otherwise
1052   /// can't be associated with any coverage information.
getMismatchedCount()1053   unsigned getMismatchedCount() const { return FuncHashMismatches.size(); }
1054 
1055   /// A hash mismatch occurs when a profile record for a symbol does not have
1056   /// the same hash as a coverage mapping record for the same symbol. This
1057   /// returns a list of hash mismatches, where each mismatch is a pair of the
1058   /// symbol name and its coverage mapping hash.
getHashMismatches()1059   ArrayRef<std::pair<std::string, uint64_t>> getHashMismatches() const {
1060     return FuncHashMismatches;
1061   }
1062 
1063   /// Returns a lexicographically sorted, unique list of files that are
1064   /// covered.
1065   LLVM_ABI std::vector<StringRef> getUniqueSourceFiles() const;
1066 
1067   /// Get the coverage for a particular file.
1068   ///
1069   /// The given filename must be the name as recorded in the coverage
1070   /// information. That is, only names returned from getUniqueSourceFiles will
1071   /// yield a result.
1072   LLVM_ABI CoverageData getCoverageForFile(StringRef Filename) const;
1073 
1074   /// Get the coverage for a particular function.
1075   LLVM_ABI CoverageData
1076   getCoverageForFunction(const FunctionRecord &Function) const;
1077 
1078   /// Get the coverage for an expansion within a coverage set.
1079   LLVM_ABI CoverageData
1080   getCoverageForExpansion(const ExpansionRecord &Expansion) const;
1081 
1082   /// Gets all of the functions covered by this profile.
getCoveredFunctions()1083   iterator_range<FunctionRecordIterator> getCoveredFunctions() const {
1084     return make_range(FunctionRecordIterator(Functions),
1085                       FunctionRecordIterator());
1086   }
1087 
1088   /// Gets all of the functions in a particular file.
1089   iterator_range<FunctionRecordIterator>
getCoveredFunctions(StringRef Filename)1090   getCoveredFunctions(StringRef Filename) const {
1091     return make_range(
1092         FunctionRecordIterator(Functions, Filename,
1093                                getImpreciseRecordIndicesForFilename(Filename)),
1094         FunctionRecordIterator());
1095   }
1096 
1097   /// Get the list of function instantiation groups in a particular file.
1098   ///
1099   /// Every instantiation group in a program is attributed to exactly one file:
1100   /// the file in which the definition for the common function begins.
1101   LLVM_ABI std::vector<InstantiationGroup>
1102   getInstantiationGroups(StringRef Filename) const;
1103 };
1104 
1105 /// Coverage statistics for a single line.
1106 class LineCoverageStats {
1107   uint64_t ExecutionCount;
1108   bool HasMultipleRegions;
1109   bool Mapped;
1110   unsigned Line;
1111   ArrayRef<const CoverageSegment *> LineSegments;
1112   const CoverageSegment *WrappedSegment;
1113 
1114   friend class LineCoverageIterator;
1115   LineCoverageStats() = default;
1116 
1117 public:
1118   LLVM_ABI LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments,
1119                              const CoverageSegment *WrappedSegment,
1120                              unsigned Line);
1121 
getExecutionCount()1122   uint64_t getExecutionCount() const { return ExecutionCount; }
1123 
hasMultipleRegions()1124   bool hasMultipleRegions() const { return HasMultipleRegions; }
1125 
isMapped()1126   bool isMapped() const { return Mapped; }
1127 
getLine()1128   unsigned getLine() const { return Line; }
1129 
getLineSegments()1130   ArrayRef<const CoverageSegment *> getLineSegments() const {
1131     return LineSegments;
1132   }
1133 
getWrappedSegment()1134   const CoverageSegment *getWrappedSegment() const { return WrappedSegment; }
1135 };
1136 
1137 /// An iterator over the \c LineCoverageStats objects for lines described by
1138 /// a \c CoverageData instance.
1139 class LineCoverageIterator
1140     : public iterator_facade_base<LineCoverageIterator,
1141                                   std::forward_iterator_tag,
1142                                   const LineCoverageStats> {
1143 public:
LineCoverageIterator(const CoverageData & CD)1144   LineCoverageIterator(const CoverageData &CD)
1145       : LineCoverageIterator(CD, CD.begin()->Line) {}
1146 
LineCoverageIterator(const CoverageData & CD,unsigned Line)1147   LineCoverageIterator(const CoverageData &CD, unsigned Line)
1148       : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false),
1149         Line(Line) {
1150     this->operator++();
1151   }
1152 
1153   bool operator==(const LineCoverageIterator &R) const {
1154     return &CD == &R.CD && Next == R.Next && Ended == R.Ended;
1155   }
1156 
1157   const LineCoverageStats &operator*() const { return Stats; }
1158 
1159   LLVM_ABI LineCoverageIterator &operator++();
1160 
getEnd()1161   LineCoverageIterator getEnd() const {
1162     auto EndIt = *this;
1163     EndIt.Next = CD.end();
1164     EndIt.Ended = true;
1165     return EndIt;
1166   }
1167 
1168 private:
1169   const CoverageData &CD;
1170   const CoverageSegment *WrappedSegment;
1171   std::vector<CoverageSegment>::const_iterator Next;
1172   bool Ended;
1173   unsigned Line;
1174   SmallVector<const CoverageSegment *, 4> Segments;
1175   LineCoverageStats Stats;
1176 };
1177 
1178 /// Get a \c LineCoverageIterator range for the lines described by \p CD.
1179 static inline iterator_range<LineCoverageIterator>
getLineCoverageStats(const coverage::CoverageData & CD)1180 getLineCoverageStats(const coverage::CoverageData &CD) {
1181   auto Begin = LineCoverageIterator(CD);
1182   auto End = Begin.getEnd();
1183   return make_range(Begin, End);
1184 }
1185 
1186 // Coverage mappping data (V2) has the following layout:
1187 // IPSK_covmap:
1188 //   [CoverageMapFileHeader]
1189 //   [ArrayStart]
1190 //    [CovMapFunctionRecordV2]
1191 //    [CovMapFunctionRecordV2]
1192 //    ...
1193 //   [ArrayEnd]
1194 //   [Encoded Filenames and Region Mapping Data]
1195 //
1196 // Coverage mappping data (V3) has the following layout:
1197 // IPSK_covmap:
1198 //   [CoverageMapFileHeader]
1199 //   [Encoded Filenames]
1200 // IPSK_covfun:
1201 //   [ArrayStart]
1202 //     odr_name_1: [CovMapFunctionRecordV3]
1203 //     odr_name_2: [CovMapFunctionRecordV3]
1204 //     ...
1205 //   [ArrayEnd]
1206 //
1207 // Both versions of the coverage mapping format encode the same information,
1208 // but the V3 format does so more compactly by taking advantage of linkonce_odr
1209 // semantics (it allows exactly 1 function record per name reference).
1210 
1211 /// This namespace defines accessors shared by different versions of coverage
1212 /// mapping records.
1213 namespace accessors {
1214 
1215 /// Return the structural hash associated with the function.
1216 template <class FuncRecordTy, llvm::endianness Endian>
getFuncHash(const FuncRecordTy * Record)1217 uint64_t getFuncHash(const FuncRecordTy *Record) {
1218   return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash);
1219 }
1220 
1221 /// Return the coverage map data size for the function.
1222 template <class FuncRecordTy, llvm::endianness Endian>
getDataSize(const FuncRecordTy * Record)1223 uint64_t getDataSize(const FuncRecordTy *Record) {
1224   return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize);
1225 }
1226 
1227 /// Return the function lookup key. The value is considered opaque.
1228 template <class FuncRecordTy, llvm::endianness Endian>
getFuncNameRef(const FuncRecordTy * Record)1229 uint64_t getFuncNameRef(const FuncRecordTy *Record) {
1230   return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef);
1231 }
1232 
1233 /// Return the PGO name of the function. Used for formats in which the name is
1234 /// a hash.
1235 template <class FuncRecordTy, llvm::endianness Endian>
getFuncNameViaRef(const FuncRecordTy * Record,InstrProfSymtab & ProfileNames,StringRef & FuncName)1236 Error getFuncNameViaRef(const FuncRecordTy *Record,
1237                         InstrProfSymtab &ProfileNames, StringRef &FuncName) {
1238   uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record);
1239   FuncName = ProfileNames.getFuncOrVarName(NameRef);
1240   return Error::success();
1241 }
1242 
1243 /// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the
1244 /// coverage mapping is attached to the file header, instead of to the function
1245 /// record.
1246 template <class FuncRecordTy, llvm::endianness Endian>
getCoverageMappingOutOfLine(const FuncRecordTy * Record,const char * MappingBuf)1247 StringRef getCoverageMappingOutOfLine(const FuncRecordTy *Record,
1248                                       const char *MappingBuf) {
1249   return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))};
1250 }
1251 
1252 /// Advance to the next out-of-line coverage mapping and its associated
1253 /// function record.
1254 template <class FuncRecordTy, llvm::endianness Endian>
1255 std::pair<const char *, const FuncRecordTy *>
advanceByOneOutOfLine(const FuncRecordTy * Record,const char * MappingBuf)1256 advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) {
1257   return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1};
1258 }
1259 
1260 } // end namespace accessors
1261 
1262 LLVM_PACKED_START
1263 template <class IntPtrT>
1264 struct CovMapFunctionRecordV1 {
1265   using ThisT = CovMapFunctionRecordV1<IntPtrT>;
1266 
1267 #define COVMAP_V1
1268 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1269 #include "llvm/ProfileData/InstrProfData.inc"
1270 #undef COVMAP_V1
1271   CovMapFunctionRecordV1() = delete;
1272 
getFuncHashCovMapFunctionRecordV11273   template <llvm::endianness Endian> uint64_t getFuncHash() const {
1274     return accessors::getFuncHash<ThisT, Endian>(this);
1275   }
1276 
getDataSizeCovMapFunctionRecordV11277   template <llvm::endianness Endian> uint64_t getDataSize() const {
1278     return accessors::getDataSize<ThisT, Endian>(this);
1279   }
1280 
1281   /// Return function lookup key. The value is consider opaque.
getFuncNameRefCovMapFunctionRecordV11282   template <llvm::endianness Endian> IntPtrT getFuncNameRef() const {
1283     return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
1284   }
1285 
1286   /// Return the PGO name of the function.
1287   template <llvm::endianness Endian>
getFuncNameCovMapFunctionRecordV11288   Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1289     IntPtrT NameRef = getFuncNameRef<Endian>();
1290     uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
1291     FuncName = ProfileNames.getFuncName(NameRef, NameS);
1292     if (NameS && FuncName.empty())
1293       return make_error<CoverageMapError>(coveragemap_error::malformed,
1294                                           "function name is empty");
1295     return Error::success();
1296   }
1297 
1298   template <llvm::endianness Endian>
1299   std::pair<const char *, const ThisT *>
advanceByOneCovMapFunctionRecordV11300   advanceByOne(const char *MappingBuf) const {
1301     return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
1302   }
1303 
getFilenamesRefCovMapFunctionRecordV11304   template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1305     llvm_unreachable("V1 function format does not contain a filenames ref");
1306   }
1307 
1308   template <llvm::endianness Endian>
getCoverageMappingCovMapFunctionRecordV11309   StringRef getCoverageMapping(const char *MappingBuf) const {
1310     return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
1311                                                                  MappingBuf);
1312   }
1313 };
1314 
1315 struct CovMapFunctionRecordV2 {
1316   using ThisT = CovMapFunctionRecordV2;
1317 
1318 #define COVMAP_V2
1319 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1320 #include "llvm/ProfileData/InstrProfData.inc"
1321 #undef COVMAP_V2
1322   CovMapFunctionRecordV2() = delete;
1323 
getFuncHashCovMapFunctionRecordV21324   template <llvm::endianness Endian> uint64_t getFuncHash() const {
1325     return accessors::getFuncHash<ThisT, Endian>(this);
1326   }
1327 
getDataSizeCovMapFunctionRecordV21328   template <llvm::endianness Endian> uint64_t getDataSize() const {
1329     return accessors::getDataSize<ThisT, Endian>(this);
1330   }
1331 
getFuncNameRefCovMapFunctionRecordV21332   template <llvm::endianness Endian> uint64_t getFuncNameRef() const {
1333     return accessors::getFuncNameRef<ThisT, Endian>(this);
1334   }
1335 
1336   template <llvm::endianness Endian>
getFuncNameCovMapFunctionRecordV21337   Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1338     return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
1339                                                        FuncName);
1340   }
1341 
1342   template <llvm::endianness Endian>
1343   std::pair<const char *, const ThisT *>
advanceByOneCovMapFunctionRecordV21344   advanceByOne(const char *MappingBuf) const {
1345     return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
1346   }
1347 
getFilenamesRefCovMapFunctionRecordV21348   template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1349     llvm_unreachable("V2 function format does not contain a filenames ref");
1350   }
1351 
1352   template <llvm::endianness Endian>
getCoverageMappingCovMapFunctionRecordV21353   StringRef getCoverageMapping(const char *MappingBuf) const {
1354     return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
1355                                                                  MappingBuf);
1356   }
1357 };
1358 
1359 struct CovMapFunctionRecordV3 {
1360   using ThisT = CovMapFunctionRecordV3;
1361 
1362 #define COVMAP_V3
1363 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1364 #include "llvm/ProfileData/InstrProfData.inc"
1365 #undef COVMAP_V3
1366   CovMapFunctionRecordV3() = delete;
1367 
getFuncHashCovMapFunctionRecordV31368   template <llvm::endianness Endian> uint64_t getFuncHash() const {
1369     return accessors::getFuncHash<ThisT, Endian>(this);
1370   }
1371 
getDataSizeCovMapFunctionRecordV31372   template <llvm::endianness Endian> uint64_t getDataSize() const {
1373     return accessors::getDataSize<ThisT, Endian>(this);
1374   }
1375 
getFuncNameRefCovMapFunctionRecordV31376   template <llvm::endianness Endian> uint64_t getFuncNameRef() const {
1377     return accessors::getFuncNameRef<ThisT, Endian>(this);
1378   }
1379 
1380   template <llvm::endianness Endian>
getFuncNameCovMapFunctionRecordV31381   Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1382     return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
1383                                                        FuncName);
1384   }
1385 
1386   /// Get the filename set reference.
getFilenamesRefCovMapFunctionRecordV31387   template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1388     return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef);
1389   }
1390 
1391   /// Read the inline coverage mapping. Ignore the buffer parameter, it is for
1392   /// out-of-line coverage mapping data only.
1393   template <llvm::endianness Endian>
getCoverageMappingCovMapFunctionRecordV31394   StringRef getCoverageMapping(const char *) const {
1395     return StringRef(&CoverageMapping, getDataSize<Endian>());
1396   }
1397 
1398   // Advance to the next inline coverage mapping and its associated function
1399   // record. Ignore the out-of-line coverage mapping buffer.
1400   template <llvm::endianness Endian>
1401   std::pair<const char *, const CovMapFunctionRecordV3 *>
advanceByOneCovMapFunctionRecordV31402   advanceByOne(const char *) const {
1403     assert(isAddrAligned(Align(8), this) && "Function record not aligned");
1404     const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) -
1405                        sizeof(char) + getDataSize<Endian>();
1406     // Each function record has an alignment of 8, so we need to adjust
1407     // alignment before reading the next record.
1408     Next += offsetToAlignedAddr(Next, Align(8));
1409     return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)};
1410   }
1411 };
1412 
1413 // Per module coverage mapping data header, i.e. CoverageMapFileHeader
1414 // documented above.
1415 struct CovMapHeader {
1416 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name;
1417 #include "llvm/ProfileData/InstrProfData.inc"
getNRecordsCovMapHeader1418   template <llvm::endianness Endian> uint32_t getNRecords() const {
1419     return support::endian::byte_swap<uint32_t, Endian>(NRecords);
1420   }
1421 
getFilenamesSizeCovMapHeader1422   template <llvm::endianness Endian> uint32_t getFilenamesSize() const {
1423     return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize);
1424   }
1425 
getCoverageSizeCovMapHeader1426   template <llvm::endianness Endian> uint32_t getCoverageSize() const {
1427     return support::endian::byte_swap<uint32_t, Endian>(CoverageSize);
1428   }
1429 
getVersionCovMapHeader1430   template <llvm::endianness Endian> uint32_t getVersion() const {
1431     return support::endian::byte_swap<uint32_t, Endian>(Version);
1432   }
1433 };
1434 
1435 LLVM_PACKED_END
1436 
1437 enum CovMapVersion {
1438   Version1 = 0,
1439   // Function's name reference from CovMapFuncRecord is changed from raw
1440   // name string pointer to MD5 to support name section compression. Name
1441   // section is also compressed.
1442   Version2 = 1,
1443   // A new interpretation of the columnEnd field is added in order to mark
1444   // regions as gap areas.
1445   Version3 = 2,
1446   // Function records are named, uniqued, and moved to a dedicated section.
1447   Version4 = 3,
1448   // Branch regions referring to two counters are added
1449   Version5 = 4,
1450   // Compilation directory is stored separately and combined with relative
1451   // filenames to produce an absolute file path.
1452   Version6 = 5,
1453   // Branch regions extended and Decision Regions added for MC/DC.
1454   Version7 = 6,
1455   // The current version is Version7.
1456   CurrentVersion = INSTR_PROF_COVMAP_VERSION
1457 };
1458 
1459 // Correspond to "llvmcovm", in little-endian.
1460 constexpr uint64_t TestingFormatMagic = 0x6d766f636d766c6c;
1461 
1462 enum class TestingFormatVersion : uint64_t {
1463   // The first version's number corresponds to the string "testdata" in
1464   // little-endian. This is for a historical reason.
1465   Version1 = 0x6174616474736574,
1466   // Version1 has a defect that it can't store multiple file records. Version2
1467   // fix this problem by adding a new field before the file records section.
1468   Version2 = 1,
1469   // The current testing format version is Version2.
1470   CurrentVersion = Version2
1471 };
1472 
1473 template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
1474   using CovMapFuncRecordType = CovMapFunctionRecordV3;
1475   using NameRefType = uint64_t;
1476 };
1477 
1478 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> {
1479   using CovMapFuncRecordType = CovMapFunctionRecordV2;
1480   using NameRefType = uint64_t;
1481 };
1482 
1483 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> {
1484   using CovMapFuncRecordType = CovMapFunctionRecordV2;
1485   using NameRefType = uint64_t;
1486 };
1487 
1488 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
1489   using CovMapFuncRecordType = CovMapFunctionRecordV1<IntPtrT>;
1490   using NameRefType = IntPtrT;
1491 };
1492 
1493 } // end namespace coverage
1494 
1495 /// Provide DenseMapInfo for CounterExpression
1496 template<> struct DenseMapInfo<coverage::CounterExpression> {
1497   static inline coverage::CounterExpression getEmptyKey() {
1498     using namespace coverage;
1499 
1500     return CounterExpression(CounterExpression::ExprKind::Subtract,
1501                              Counter::getCounter(~0U),
1502                              Counter::getCounter(~0U));
1503   }
1504 
1505   static inline coverage::CounterExpression getTombstoneKey() {
1506     using namespace coverage;
1507 
1508     return CounterExpression(CounterExpression::ExprKind::Add,
1509                              Counter::getCounter(~0U),
1510                              Counter::getCounter(~0U));
1511   }
1512 
1513   static unsigned getHashValue(const coverage::CounterExpression &V) {
1514     return static_cast<unsigned>(
1515         hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(),
1516                      V.RHS.getKind(), V.RHS.getCounterID()));
1517   }
1518 
1519   static bool isEqual(const coverage::CounterExpression &LHS,
1520                       const coverage::CounterExpression &RHS) {
1521     return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS;
1522   }
1523 };
1524 
1525 } // end namespace llvm
1526 
1527 #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
1528