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