Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:23

0001 //===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Code coverage mapping data is generated by clang and read by
0010 // llvm-cov to show code coverage statistics for a file.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
0015 #define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
0016 
0017 #include "llvm/ADT/ArrayRef.h"
0018 #include "llvm/ADT/BitVector.h"
0019 #include "llvm/ADT/DenseMap.h"
0020 #include "llvm/ADT/DenseSet.h"
0021 #include "llvm/ADT/Hashing.h"
0022 #include "llvm/ADT/StringRef.h"
0023 #include "llvm/ADT/iterator.h"
0024 #include "llvm/ADT/iterator_range.h"
0025 #include "llvm/Object/BuildID.h"
0026 #include "llvm/ProfileData/Coverage/MCDCTypes.h"
0027 #include "llvm/ProfileData/InstrProf.h"
0028 #include "llvm/Support/Alignment.h"
0029 #include "llvm/Support/Compiler.h"
0030 #include "llvm/Support/Debug.h"
0031 #include "llvm/Support/Endian.h"
0032 #include "llvm/Support/Error.h"
0033 #include "llvm/Support/raw_ostream.h"
0034 #include <cassert>
0035 #include <cstdint>
0036 #include <iterator>
0037 #include <map>
0038 #include <memory>
0039 #include <optional>
0040 #include <sstream>
0041 #include <string>
0042 #include <system_error>
0043 #include <utility>
0044 #include <vector>
0045 
0046 namespace llvm {
0047 
0048 class IndexedInstrProfReader;
0049 
0050 namespace object {
0051 class BuildIDFetcher;
0052 } // namespace object
0053 
0054 namespace vfs {
0055 class FileSystem;
0056 } // namespace vfs
0057 
0058 namespace coverage {
0059 
0060 class CoverageMappingReader;
0061 struct CoverageMappingRecord;
0062 
0063 enum class coveragemap_error {
0064   success = 0,
0065   eof,
0066   no_data_found,
0067   unsupported_version,
0068   truncated,
0069   malformed,
0070   decompression_failed,
0071   invalid_or_missing_arch_specifier
0072 };
0073 
0074 const std::error_category &coveragemap_category();
0075 
0076 inline std::error_code make_error_code(coveragemap_error E) {
0077   return std::error_code(static_cast<int>(E), coveragemap_category());
0078 }
0079 
0080 class CoverageMapError : public ErrorInfo<CoverageMapError> {
0081 public:
0082   CoverageMapError(coveragemap_error Err, const Twine &ErrStr = Twine())
0083       : Err(Err), Msg(ErrStr.str()) {
0084     assert(Err != coveragemap_error::success && "Not an error");
0085   }
0086 
0087   std::string message() const override;
0088 
0089   void log(raw_ostream &OS) const override { OS << message(); }
0090 
0091   std::error_code convertToErrorCode() const override {
0092     return make_error_code(Err);
0093   }
0094 
0095   coveragemap_error get() const { return Err; }
0096   const std::string &getMessage() const { return Msg; }
0097 
0098   static char ID;
0099 
0100 private:
0101   coveragemap_error Err;
0102   std::string Msg;
0103 };
0104 
0105 /// A Counter is an abstract value that describes how to compute the
0106 /// execution count for a region of code using the collected profile count data.
0107 struct Counter {
0108   /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to
0109   /// the CounterKind. This means CounterKind has to leave bit 0 free.
0110   enum CounterKind { Zero, CounterValueReference, Expression };
0111   static const unsigned EncodingTagBits = 2;
0112   static const unsigned EncodingTagMask = 0x3;
0113   static const unsigned EncodingCounterTagAndExpansionRegionTagBits =
0114       EncodingTagBits + 1;
0115 
0116 private:
0117   CounterKind Kind = Zero;
0118   unsigned ID = 0;
0119 
0120   Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
0121 
0122 public:
0123   Counter() = default;
0124 
0125   CounterKind getKind() const { return Kind; }
0126 
0127   bool isZero() const { return Kind == Zero; }
0128 
0129   bool isExpression() const { return Kind == Expression; }
0130 
0131   unsigned getCounterID() const { return ID; }
0132 
0133   unsigned getExpressionID() const { return ID; }
0134 
0135   friend bool operator==(const Counter &LHS, const Counter &RHS) {
0136     return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID;
0137   }
0138 
0139   friend bool operator!=(const Counter &LHS, const Counter &RHS) {
0140     return !(LHS == RHS);
0141   }
0142 
0143   friend bool operator<(const Counter &LHS, const Counter &RHS) {
0144     return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID);
0145   }
0146 
0147   /// Return the counter that represents the number zero.
0148   static Counter getZero() { return Counter(); }
0149 
0150   /// Return the counter that corresponds to a specific profile counter.
0151   static Counter getCounter(unsigned CounterId) {
0152     return Counter(CounterValueReference, CounterId);
0153   }
0154 
0155   /// Return the counter that corresponds to a specific addition counter
0156   /// expression.
0157   static Counter getExpression(unsigned ExpressionId) {
0158     return Counter(Expression, ExpressionId);
0159   }
0160 };
0161 
0162 /// A Counter expression is a value that represents an arithmetic operation
0163 /// with two counters.
0164 struct CounterExpression {
0165   enum ExprKind { Subtract, Add };
0166   ExprKind Kind;
0167   Counter LHS, RHS;
0168 
0169   CounterExpression(ExprKind Kind, Counter LHS, Counter RHS)
0170       : Kind(Kind), LHS(LHS), RHS(RHS) {}
0171 };
0172 
0173 /// A Counter expression builder is used to construct the counter expressions.
0174 /// It avoids unnecessary duplication and simplifies algebraic expressions.
0175 class CounterExpressionBuilder {
0176   /// A list of all the counter expressions
0177   std::vector<CounterExpression> Expressions;
0178 
0179   /// A lookup table for the index of a given expression.
0180   DenseMap<CounterExpression, unsigned> ExpressionIndices;
0181 
0182   /// Return the counter which corresponds to the given expression.
0183   ///
0184   /// If the given expression is already stored in the builder, a counter
0185   /// that references that expression is returned. Otherwise, the given
0186   /// expression is added to the builder's collection of expressions.
0187   Counter get(const CounterExpression &E);
0188 
0189   /// Represents a term in a counter expression tree.
0190   struct Term {
0191     unsigned CounterID;
0192     int Factor;
0193 
0194     Term(unsigned CounterID, int Factor)
0195         : CounterID(CounterID), Factor(Factor) {}
0196   };
0197 
0198   /// Gather the terms of the expression tree for processing.
0199   ///
0200   /// This collects each addition and subtraction referenced by the counter into
0201   /// a sequence that can be sorted and combined to build a simplified counter
0202   /// expression.
0203   void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms);
0204 
0205   /// Simplifies the given expression tree
0206   /// by getting rid of algebraically redundant operations.
0207   Counter simplify(Counter ExpressionTree);
0208 
0209 public:
0210   ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
0211 
0212   /// Return a counter that represents the expression that adds LHS and RHS.
0213   Counter add(Counter LHS, Counter RHS, bool Simplify = true);
0214 
0215   /// Return a counter that represents the expression that subtracts RHS from
0216   /// LHS.
0217   Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
0218 
0219   /// K to V map. K will be Counter in most cases. V may be Counter or
0220   /// Expression.
0221   using SubstMap = std::map<Counter, Counter>;
0222 
0223   /// \return A counter equivalent to \C, with each term in its
0224   /// expression replaced with term from \p Map.
0225   Counter subst(Counter C, const SubstMap &Map);
0226 };
0227 
0228 using LineColPair = std::pair<unsigned, unsigned>;
0229 
0230 /// A Counter mapping region associates a source range with a specific counter.
0231 struct CounterMappingRegion {
0232   enum RegionKind {
0233     /// A CodeRegion associates some code with a counter
0234     CodeRegion,
0235 
0236     /// An ExpansionRegion represents a file expansion region that associates
0237     /// a source range with the expansion of a virtual source file, such as
0238     /// for a macro instantiation or #include file.
0239     ExpansionRegion,
0240 
0241     /// A SkippedRegion represents a source range with code that was skipped
0242     /// by a preprocessor or similar means.
0243     SkippedRegion,
0244 
0245     /// A GapRegion is like a CodeRegion, but its count is only set as the
0246     /// line execution count when its the only region in the line.
0247     GapRegion,
0248 
0249     /// A BranchRegion represents leaf-level boolean expressions and is
0250     /// associated with two counters, each representing the number of times the
0251     /// expression evaluates to true or false.
0252     BranchRegion,
0253 
0254     /// A DecisionRegion represents a top-level boolean expression and is
0255     /// associated with a variable length bitmap index and condition number.
0256     MCDCDecisionRegion,
0257 
0258     /// A Branch Region can be extended to include IDs to facilitate MC/DC.
0259     MCDCBranchRegion
0260   };
0261 
0262   /// Primary Counter that is also used for Branch Regions (TrueCount).
0263   Counter Count;
0264 
0265   /// Secondary Counter used for Branch Regions (FalseCount).
0266   Counter FalseCount;
0267 
0268   /// Parameters used for Modified Condition/Decision Coverage
0269   mcdc::Parameters MCDCParams;
0270 
0271   const auto &getDecisionParams() const {
0272     return mcdc::getParams<const mcdc::DecisionParameters>(MCDCParams);
0273   }
0274 
0275   const auto &getBranchParams() const {
0276     return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams);
0277   }
0278 
0279   unsigned FileID = 0;
0280   unsigned ExpandedFileID = 0;
0281   unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
0282 
0283   RegionKind Kind;
0284 
0285   bool isBranch() const {
0286     return (Kind == BranchRegion || Kind == MCDCBranchRegion);
0287   }
0288 
0289   CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID,
0290                        unsigned LineStart, unsigned ColumnStart,
0291                        unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
0292       : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID),
0293         LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd),
0294         ColumnEnd(ColumnEnd), Kind(Kind) {}
0295 
0296   CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID,
0297                        unsigned ExpandedFileID, unsigned LineStart,
0298                        unsigned ColumnStart, unsigned LineEnd,
0299                        unsigned ColumnEnd, RegionKind Kind,
0300                        const mcdc::Parameters &MCDCParams = std::monostate())
0301       : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
0302         FileID(FileID), ExpandedFileID(ExpandedFileID), LineStart(LineStart),
0303         ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
0304         Kind(Kind) {}
0305 
0306   CounterMappingRegion(const mcdc::DecisionParameters &MCDCParams,
0307                        unsigned FileID, unsigned LineStart,
0308                        unsigned ColumnStart, unsigned LineEnd,
0309                        unsigned ColumnEnd, RegionKind Kind)
0310       : MCDCParams(MCDCParams), FileID(FileID), LineStart(LineStart),
0311         ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
0312         Kind(Kind) {}
0313 
0314   static CounterMappingRegion
0315   makeRegion(Counter Count, unsigned FileID, unsigned LineStart,
0316              unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
0317     return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart,
0318                                 LineEnd, ColumnEnd, CodeRegion);
0319   }
0320 
0321   static CounterMappingRegion
0322   makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
0323                 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
0324     return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart,
0325                                 ColumnStart, LineEnd, ColumnEnd,
0326                                 ExpansionRegion);
0327   }
0328 
0329   static CounterMappingRegion
0330   makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
0331               unsigned LineEnd, unsigned ColumnEnd) {
0332     return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart,
0333                                 LineEnd, ColumnEnd, SkippedRegion);
0334   }
0335 
0336   static CounterMappingRegion
0337   makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart,
0338                 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
0339     return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart,
0340                                 LineEnd, (1U << 31) | ColumnEnd, GapRegion);
0341   }
0342 
0343   static CounterMappingRegion
0344   makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID,
0345                    unsigned LineStart, unsigned ColumnStart, unsigned LineEnd,
0346                    unsigned ColumnEnd,
0347                    const mcdc::Parameters &MCDCParams = std::monostate()) {
0348     return CounterMappingRegion(
0349         Count, FalseCount, FileID, 0, LineStart, ColumnStart, LineEnd,
0350         ColumnEnd,
0351         (std::get_if<mcdc::BranchParameters>(&MCDCParams) ? MCDCBranchRegion
0352                                                           : BranchRegion),
0353         MCDCParams);
0354   }
0355 
0356   static CounterMappingRegion
0357   makeDecisionRegion(const mcdc::DecisionParameters &MCDCParams,
0358                      unsigned FileID, unsigned LineStart, unsigned ColumnStart,
0359                      unsigned LineEnd, unsigned ColumnEnd) {
0360     return CounterMappingRegion(MCDCParams, FileID, LineStart, ColumnStart,
0361                                 LineEnd, ColumnEnd, MCDCDecisionRegion);
0362   }
0363 
0364   inline LineColPair startLoc() const {
0365     return LineColPair(LineStart, ColumnStart);
0366   }
0367 
0368   inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); }
0369 };
0370 
0371 /// Associates a source range with an execution count.
0372 struct CountedRegion : public CounterMappingRegion {
0373   uint64_t ExecutionCount;
0374   uint64_t FalseExecutionCount;
0375   bool TrueFolded;
0376   bool FalseFolded;
0377 
0378   CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
0379       : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
0380         FalseExecutionCount(0), TrueFolded(false), FalseFolded(true) {}
0381 
0382   CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
0383                 uint64_t FalseExecutionCount)
0384       : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
0385         FalseExecutionCount(FalseExecutionCount), TrueFolded(false),
0386         FalseFolded(false) {}
0387 };
0388 
0389 /// MCDC Record grouping all information together.
0390 struct MCDCRecord {
0391   /// CondState represents the evaluation of a condition in an executed test
0392   /// vector, which can be True or False. A DontCare is used to mask an
0393   /// unevaluatable condition resulting from short-circuit behavior of logical
0394   /// operators in languages like C/C++. When comparing the evaluation of a
0395   /// condition across executed test vectors, comparisons against a DontCare
0396   /// are effectively ignored.
0397   enum CondState { MCDC_DontCare = -1, MCDC_False = 0, MCDC_True = 1 };
0398 
0399   /// Emulate SmallVector<CondState> with a pair of BitVector.
0400   ///
0401   ///          True  False DontCare (Impossible)
0402   /// Values:  True  False False    True
0403   /// Visited: True  True  False    False
0404   class TestVector {
0405     BitVector Values;  /// True/False (False when DontCare)
0406     BitVector Visited; /// ~DontCare
0407 
0408   public:
0409     /// Default values are filled with DontCare.
0410     TestVector(unsigned N) : Values(N), Visited(N) {}
0411 
0412     /// Emulate RHS SmallVector::operator[]
0413     CondState operator[](int I) const {
0414       return (Visited[I] ? (Values[I] ? MCDC_True : MCDC_False)
0415                          : MCDC_DontCare);
0416     }
0417 
0418     /// Equivalent to buildTestVector's Index.
0419     auto getIndex() const { return Values.getData()[0]; }
0420 
0421     /// Set the condition \p Val at position \p I.
0422     /// This emulates LHS SmallVector::operator[].
0423     void set(int I, CondState Val) {
0424       Visited[I] = (Val != MCDC_DontCare);
0425       Values[I] = (Val == MCDC_True);
0426     }
0427 
0428     /// Emulate SmallVector::push_back.
0429     void push_back(CondState Val) {
0430       Visited.push_back(Val != MCDC_DontCare);
0431       Values.push_back(Val == MCDC_True);
0432       assert(Values.size() == Visited.size());
0433     }
0434 
0435     /// For each element:
0436     /// - False if either is DontCare
0437     /// - False if both have the same value
0438     /// - True if both have the opposite value
0439     /// ((A.Values ^ B.Values) & A.Visited & B.Visited)
0440     /// Dedicated to findIndependencePairs().
0441     auto getDifferences(const TestVector &B) const {
0442       const auto &A = *this;
0443       BitVector AB = A.Values;
0444       AB ^= B.Values;
0445       AB &= A.Visited;
0446       AB &= B.Visited;
0447       return AB;
0448     }
0449   };
0450 
0451   using TestVectors = llvm::SmallVector<std::pair<TestVector, CondState>>;
0452   using BoolVector = std::array<BitVector, 2>;
0453   using TVRowPair = std::pair<unsigned, unsigned>;
0454   using TVPairMap = llvm::DenseMap<unsigned, TVRowPair>;
0455   using CondIDMap = llvm::DenseMap<unsigned, unsigned>;
0456   using LineColPairMap = llvm::DenseMap<unsigned, LineColPair>;
0457 
0458 private:
0459   CounterMappingRegion Region;
0460   TestVectors TV;
0461   std::optional<TVPairMap> IndependencePairs;
0462   BoolVector Folded;
0463   CondIDMap PosToID;
0464   LineColPairMap CondLoc;
0465 
0466 public:
0467   MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV,
0468              BoolVector &&Folded, CondIDMap &&PosToID, LineColPairMap &&CondLoc)
0469       : Region(Region), TV(std::move(TV)), Folded(std::move(Folded)),
0470         PosToID(std::move(PosToID)), CondLoc(std::move(CondLoc)) {
0471     findIndependencePairs();
0472   }
0473 
0474   // Compare executed test vectors against each other to find an independence
0475   // pairs for each condition.  This processing takes the most time.
0476   void findIndependencePairs();
0477 
0478   const CounterMappingRegion &getDecisionRegion() const { return Region; }
0479   unsigned getNumConditions() const {
0480     return Region.getDecisionParams().NumConditions;
0481   }
0482   unsigned getNumTestVectors() const { return TV.size(); }
0483   bool isCondFolded(unsigned Condition) const {
0484     return Folded[false][Condition] || Folded[true][Condition];
0485   }
0486 
0487   /// Return the evaluation of a condition (indicated by Condition) in an
0488   /// executed test vector (indicated by TestVectorIndex), which will be True,
0489   /// False, or DontCare if the condition is unevaluatable. Because condition
0490   /// IDs are not associated based on their position in the expression,
0491   /// accessing conditions in the TestVectors requires a translation from a
0492   /// ordinal position to actual condition ID. This is done via PosToID[].
0493   CondState getTVCondition(unsigned TestVectorIndex, unsigned Condition) {
0494     return TV[TestVectorIndex].first[PosToID[Condition]];
0495   }
0496 
0497   /// Return the Result evaluation for an executed test vector.
0498   /// See MCDCRecordProcessor::RecordTestVector().
0499   CondState getTVResult(unsigned TestVectorIndex) {
0500     return TV[TestVectorIndex].second;
0501   }
0502 
0503   /// Determine whether a given condition (indicated by Condition) is covered
0504   /// by an Independence Pair. Because condition IDs are not associated based
0505   /// on their position in the expression, accessing conditions in the
0506   /// TestVectors requires a translation from a ordinal position to actual
0507   /// condition ID. This is done via PosToID[].
0508   bool isConditionIndependencePairCovered(unsigned Condition) const {
0509     assert(IndependencePairs);
0510     auto It = PosToID.find(Condition);
0511     assert(It != PosToID.end() && "Condition ID without an Ordinal mapping");
0512     return IndependencePairs->contains(It->second);
0513   }
0514 
0515   /// Return the Independence Pair that covers the given condition. Because
0516   /// condition IDs are not associated based on their position in the
0517   /// expression, accessing conditions in the TestVectors requires a
0518   /// translation from a ordinal position to actual condition ID. This is done
0519   /// via PosToID[].
0520   TVRowPair getConditionIndependencePair(unsigned Condition) {
0521     assert(isConditionIndependencePairCovered(Condition));
0522     assert(IndependencePairs);
0523     return (*IndependencePairs)[PosToID[Condition]];
0524   }
0525 
0526   float getPercentCovered() const {
0527     unsigned Folded = 0;
0528     unsigned Covered = 0;
0529     for (unsigned C = 0; C < getNumConditions(); C++) {
0530       if (isCondFolded(C))
0531         Folded++;
0532       else if (isConditionIndependencePairCovered(C))
0533         Covered++;
0534     }
0535 
0536     unsigned Total = getNumConditions() - Folded;
0537     if (Total == 0)
0538       return 0.0;
0539     return (static_cast<double>(Covered) / static_cast<double>(Total)) * 100.0;
0540   }
0541 
0542   std::string getConditionHeaderString(unsigned Condition) {
0543     std::ostringstream OS;
0544     OS << "Condition C" << Condition + 1 << " --> (";
0545     OS << CondLoc[Condition].first << ":" << CondLoc[Condition].second;
0546     OS << ")\n";
0547     return OS.str();
0548   }
0549 
0550   std::string getTestVectorHeaderString() const {
0551     std::ostringstream OS;
0552     if (getNumTestVectors() == 0) {
0553       OS << "None.\n";
0554       return OS.str();
0555     }
0556     const auto NumConditions = getNumConditions();
0557     for (unsigned I = 0; I < NumConditions; I++) {
0558       OS << "C" << I + 1;
0559       if (I != NumConditions - 1)
0560         OS << ", ";
0561     }
0562     OS << "    Result\n";
0563     return OS.str();
0564   }
0565 
0566   std::string getTestVectorString(unsigned TestVectorIndex) {
0567     assert(TestVectorIndex < getNumTestVectors() &&
0568            "TestVector index out of bounds!");
0569     std::ostringstream OS;
0570     const auto NumConditions = getNumConditions();
0571     // Add individual condition values to the string.
0572     OS << "  " << TestVectorIndex + 1 << " { ";
0573     for (unsigned Condition = 0; Condition < NumConditions; Condition++) {
0574       if (isCondFolded(Condition))
0575         OS << "C";
0576       else {
0577         switch (getTVCondition(TestVectorIndex, Condition)) {
0578         case MCDCRecord::MCDC_DontCare:
0579           OS << "-";
0580           break;
0581         case MCDCRecord::MCDC_True:
0582           OS << "T";
0583           break;
0584         case MCDCRecord::MCDC_False:
0585           OS << "F";
0586           break;
0587         }
0588       }
0589       if (Condition != NumConditions - 1)
0590         OS << ",  ";
0591     }
0592 
0593     // Add result value to the string.
0594     OS << "  = ";
0595     if (getTVResult(TestVectorIndex) == MCDC_True)
0596       OS << "T";
0597     else
0598       OS << "F";
0599     OS << "      }\n";
0600 
0601     return OS.str();
0602   }
0603 
0604   std::string getConditionCoverageString(unsigned Condition) {
0605     assert(Condition < getNumConditions() &&
0606            "Condition index is out of bounds!");
0607     std::ostringstream OS;
0608 
0609     OS << "  C" << Condition + 1 << "-Pair: ";
0610     if (isCondFolded(Condition)) {
0611       OS << "constant folded\n";
0612     } else if (isConditionIndependencePairCovered(Condition)) {
0613       TVRowPair rows = getConditionIndependencePair(Condition);
0614       OS << "covered: (" << rows.first << ",";
0615       OS << rows.second << ")\n";
0616     } else
0617       OS << "not covered\n";
0618 
0619     return OS.str();
0620   }
0621 };
0622 
0623 namespace mcdc {
0624 /// Compute TestVector Indices "TVIdx" from the Conds graph.
0625 ///
0626 /// Clang CodeGen handles the bitmap index based on TVIdx.
0627 /// llvm-cov reconstructs conditions from TVIdx.
0628 ///
0629 /// For each leaf "The final decision",
0630 /// - TVIdx should be unique.
0631 /// - TVIdx has the Width.
0632 ///   - The width represents the number of possible paths.
0633 ///   - The minimum width is 1 "deterministic".
0634 /// - The order of leaves are sorted by Width DESC. It expects
0635 ///   latter TVIdx(s) (with Width=1) could be pruned and altered to
0636 ///   other simple branch conditions.
0637 ///
0638 class TVIdxBuilder {
0639 public:
0640   struct MCDCNode {
0641     int InCount = 0; /// Reference count; temporary use
0642     int Width;       /// Number of accumulated paths (>= 1)
0643     ConditionIDs NextIDs;
0644   };
0645 
0646 #ifndef NDEBUG
0647   /// This is no longer needed after the assignment.
0648   /// It may be used in assert() for reconfirmation.
0649   SmallVector<MCDCNode> SavedNodes;
0650 #endif
0651 
0652   /// Output: Index for TestVectors bitmap (These are not CondIDs)
0653   SmallVector<std::array<int, 2>> Indices;
0654 
0655   /// Output: The number of test vectors.
0656   /// Error with HardMaxTVs if the number has exploded.
0657   int NumTestVectors;
0658 
0659   /// Hard limit of test vectors
0660   static constexpr auto HardMaxTVs =
0661       std::numeric_limits<decltype(NumTestVectors)>::max();
0662 
0663 public:
0664   /// Calculate and assign Indices
0665   /// \param NextIDs The list of {FalseID, TrueID} indexed by ID
0666   ///        The first element [0] should be the root node.
0667   /// \param Offset Offset of index to final decisions.
0668   TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs, int Offset = 0);
0669 };
0670 } // namespace mcdc
0671 
0672 /// A Counter mapping context is used to connect the counters, expressions
0673 /// and the obtained counter values.
0674 class CounterMappingContext {
0675   ArrayRef<CounterExpression> Expressions;
0676   ArrayRef<uint64_t> CounterValues;
0677   BitVector Bitmap;
0678 
0679 public:
0680   CounterMappingContext(ArrayRef<CounterExpression> Expressions,
0681                         ArrayRef<uint64_t> CounterValues = {})
0682       : Expressions(Expressions), CounterValues(CounterValues) {}
0683 
0684   void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
0685   void setBitmap(BitVector &&Bitmap_) { Bitmap = std::move(Bitmap_); }
0686 
0687   void dump(const Counter &C, raw_ostream &OS) const;
0688   void dump(const Counter &C) const { dump(C, dbgs()); }
0689 
0690   /// Return the number of times that a region of code associated with this
0691   /// counter was executed.
0692   Expected<int64_t> evaluate(const Counter &C) const;
0693 
0694   /// Return an MCDC record that indicates executed test vectors and condition
0695   /// pairs.
0696   Expected<MCDCRecord>
0697   evaluateMCDCRegion(const CounterMappingRegion &Region,
0698                      ArrayRef<const CounterMappingRegion *> Branches,
0699                      bool IsVersion11);
0700 
0701   unsigned getMaxCounterID(const Counter &C) const;
0702 };
0703 
0704 /// Code coverage information for a single function.
0705 struct FunctionRecord {
0706   /// Raw function name.
0707   std::string Name;
0708   /// Mapping from FileID (i.e. vector index) to filename. Used to support
0709   /// macro expansions within a function in which the macro and function are
0710   /// defined in separate files.
0711   ///
0712   /// TODO: Uniquing filenames across all function records may be a performance
0713   /// optimization.
0714   std::vector<std::string> Filenames;
0715   /// Regions in the function along with their counts.
0716   std::vector<CountedRegion> CountedRegions;
0717   /// Branch Regions in the function along with their counts.
0718   std::vector<CountedRegion> CountedBranchRegions;
0719   /// MCDC Records record a DecisionRegion and associated BranchRegions.
0720   std::vector<MCDCRecord> MCDCRecords;
0721   /// The number of times this function was executed.
0722   uint64_t ExecutionCount = 0;
0723 
0724   FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
0725       : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
0726 
0727   FunctionRecord(FunctionRecord &&FR) = default;
0728   FunctionRecord &operator=(FunctionRecord &&) = default;
0729 
0730   void pushMCDCRecord(MCDCRecord &&Record) {
0731     MCDCRecords.push_back(std::move(Record));
0732   }
0733 
0734   void pushRegion(CounterMappingRegion Region, uint64_t Count,
0735                   uint64_t FalseCount) {
0736     if (Region.isBranch()) {
0737       CountedBranchRegions.emplace_back(Region, Count, FalseCount);
0738       // If either counter is hard-coded to zero, then this region represents a
0739       // constant-folded branch.
0740       CountedBranchRegions.back().TrueFolded = Region.Count.isZero();
0741       CountedBranchRegions.back().FalseFolded = Region.FalseCount.isZero();
0742       return;
0743     }
0744     if (CountedRegions.empty())
0745       ExecutionCount = Count;
0746     CountedRegions.emplace_back(Region, Count, FalseCount);
0747   }
0748 };
0749 
0750 /// Iterator over Functions, optionally filtered to a single file.
0751 /// When filtering to a single file, the iterator requires a list of potential
0752 /// indices where to find the desired records to avoid quadratic behavior when
0753 /// repeatedly iterating over functions from different files.
0754 class FunctionRecordIterator
0755     : public iterator_facade_base<FunctionRecordIterator,
0756                                   std::forward_iterator_tag, FunctionRecord> {
0757   ArrayRef<FunctionRecord> Records;
0758   ArrayRef<unsigned> RecordIndices;
0759   ArrayRef<unsigned>::iterator CurrentIndex;
0760   ArrayRef<FunctionRecord>::iterator Current;
0761   StringRef Filename;
0762 
0763   /// Skip records whose primary file is not \c Filename.
0764   void skipOtherFiles();
0765 
0766 public:
0767   FunctionRecordIterator(ArrayRef<FunctionRecord> Records_,
0768                          StringRef Filename = "",
0769                          ArrayRef<unsigned> RecordIndices_ = {})
0770       : Records(Records_), RecordIndices(RecordIndices_),
0771         CurrentIndex(RecordIndices.begin()),
0772         // If `RecordIndices` is provided, we can skip directly to the first
0773         // index it provides.
0774         Current(CurrentIndex == RecordIndices.end() ? Records.begin()
0775                                                     : &Records[*CurrentIndex]),
0776         Filename(Filename) {
0777     assert(Filename.empty() == RecordIndices_.empty() &&
0778            "If `Filename` is specified, `RecordIndices` must also be provided");
0779     skipOtherFiles();
0780   }
0781 
0782   FunctionRecordIterator() : Current(Records.begin()) {}
0783 
0784   bool operator==(const FunctionRecordIterator &RHS) const {
0785     return Current == RHS.Current && Filename == RHS.Filename;
0786   }
0787 
0788   const FunctionRecord &operator*() const { return *Current; }
0789 
0790   FunctionRecordIterator &operator++() {
0791     advanceOne();
0792     skipOtherFiles();
0793     return *this;
0794   }
0795 
0796 private:
0797   void advanceOne() {
0798     if (RecordIndices.empty()) {
0799       // Iteration over all entries, advance in the list of records.
0800       assert(Current != Records.end() && "incremented past end");
0801       ++Current;
0802     } else {
0803       // Iterator over entries filtered by file name. Advance in the list of
0804       // indices, and adjust the cursor in the list of records accordingly.
0805       assert(CurrentIndex != RecordIndices.end() && "incremented past end");
0806       ++CurrentIndex;
0807       if (CurrentIndex == RecordIndices.end()) {
0808         Current = Records.end();
0809       } else {
0810         Current = &Records[*CurrentIndex];
0811       }
0812     }
0813   }
0814 };
0815 
0816 /// Coverage information for a macro expansion or #included file.
0817 ///
0818 /// When covered code has pieces that can be expanded for more detail, such as a
0819 /// preprocessor macro use and its definition, these are represented as
0820 /// expansions whose coverage can be looked up independently.
0821 struct ExpansionRecord {
0822   /// The abstract file this expansion covers.
0823   unsigned FileID;
0824   /// The region that expands to this record.
0825   const CountedRegion &Region;
0826   /// Coverage for the expansion.
0827   const FunctionRecord &Function;
0828 
0829   ExpansionRecord(const CountedRegion &Region,
0830                   const FunctionRecord &Function)
0831       : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
0832 };
0833 
0834 /// The execution count information starting at a point in a file.
0835 ///
0836 /// A sequence of CoverageSegments gives execution counts for a file in format
0837 /// that's simple to iterate through for processing.
0838 struct CoverageSegment {
0839   /// The line where this segment begins.
0840   unsigned Line;
0841   /// The column where this segment begins.
0842   unsigned Col;
0843   /// The execution count, or zero if no count was recorded.
0844   uint64_t Count;
0845   /// When false, the segment was uninstrumented or skipped.
0846   bool HasCount;
0847   /// Whether this enters a new region or returns to a previous count.
0848   bool IsRegionEntry;
0849   /// Whether this enters a gap region.
0850   bool IsGapRegion;
0851 
0852   CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
0853       : Line(Line), Col(Col), Count(0), HasCount(false),
0854         IsRegionEntry(IsRegionEntry), IsGapRegion(false) {}
0855 
0856   CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
0857                   bool IsRegionEntry, bool IsGapRegion = false,
0858                   bool IsBranchRegion = false)
0859       : Line(Line), Col(Col), Count(Count), HasCount(true),
0860         IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {}
0861 
0862   friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) {
0863     return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry,
0864                     L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count,
0865                                                R.HasCount, R.IsRegionEntry,
0866                                                R.IsGapRegion);
0867   }
0868 };
0869 
0870 /// An instantiation group contains a \c FunctionRecord list, such that each
0871 /// record corresponds to a distinct instantiation of the same function.
0872 ///
0873 /// Note that it's possible for a function to have more than one instantiation
0874 /// (consider C++ template specializations or static inline functions).
0875 class InstantiationGroup {
0876   friend class CoverageMapping;
0877 
0878   unsigned Line;
0879   unsigned Col;
0880   std::vector<const FunctionRecord *> Instantiations;
0881 
0882   InstantiationGroup(unsigned Line, unsigned Col,
0883                      std::vector<const FunctionRecord *> Instantiations)
0884       : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {}
0885 
0886 public:
0887   InstantiationGroup(const InstantiationGroup &) = delete;
0888   InstantiationGroup(InstantiationGroup &&) = default;
0889 
0890   /// Get the number of instantiations in this group.
0891   size_t size() const { return Instantiations.size(); }
0892 
0893   /// Get the line where the common function was defined.
0894   unsigned getLine() const { return Line; }
0895 
0896   /// Get the column where the common function was defined.
0897   unsigned getColumn() const { return Col; }
0898 
0899   /// Check if the instantiations in this group have a common mangled name.
0900   bool hasName() const {
0901     for (unsigned I = 1, E = Instantiations.size(); I < E; ++I)
0902       if (Instantiations[I]->Name != Instantiations[0]->Name)
0903         return false;
0904     return true;
0905   }
0906 
0907   /// Get the common mangled name for instantiations in this group.
0908   StringRef getName() const {
0909     assert(hasName() && "Instantiations don't have a shared name");
0910     return Instantiations[0]->Name;
0911   }
0912 
0913   /// Get the total execution count of all instantiations in this group.
0914   uint64_t getTotalExecutionCount() const {
0915     uint64_t Count = 0;
0916     for (const FunctionRecord *F : Instantiations)
0917       Count += F->ExecutionCount;
0918     return Count;
0919   }
0920 
0921   /// Get the instantiations in this group.
0922   ArrayRef<const FunctionRecord *> getInstantiations() const {
0923     return Instantiations;
0924   }
0925 };
0926 
0927 /// Coverage information to be processed or displayed.
0928 ///
0929 /// This represents the coverage of an entire file, expansion, or function. It
0930 /// provides a sequence of CoverageSegments to iterate through, as well as the
0931 /// list of expansions that can be further processed.
0932 class CoverageData {
0933   friend class CoverageMapping;
0934 
0935   std::string Filename;
0936   std::vector<CoverageSegment> Segments;
0937   std::vector<ExpansionRecord> Expansions;
0938   std::vector<CountedRegion> BranchRegions;
0939   std::vector<MCDCRecord> MCDCRecords;
0940 
0941   bool SingleByteCoverage = false;
0942 
0943 public:
0944   CoverageData() = default;
0945 
0946   CoverageData(bool Single, StringRef Filename)
0947       : Filename(Filename), SingleByteCoverage(Single) {}
0948 
0949   /// Get the name of the file this data covers.
0950   StringRef getFilename() const { return Filename; }
0951 
0952   bool getSingleByteCoverage() const { return SingleByteCoverage; }
0953 
0954   /// Get an iterator over the coverage segments for this object. The segments
0955   /// are guaranteed to be uniqued and sorted by location.
0956   std::vector<CoverageSegment>::const_iterator begin() const {
0957     return Segments.begin();
0958   }
0959 
0960   std::vector<CoverageSegment>::const_iterator end() const {
0961     return Segments.end();
0962   }
0963 
0964   bool empty() const { return Segments.empty(); }
0965 
0966   /// Expansions that can be further processed.
0967   ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; }
0968 
0969   /// Branches that can be further processed.
0970   ArrayRef<CountedRegion> getBranches() const { return BranchRegions; }
0971 
0972   /// MCDC Records that can be further processed.
0973   ArrayRef<MCDCRecord> getMCDCRecords() const { return MCDCRecords; }
0974 };
0975 
0976 /// The mapping of profile information to coverage data.
0977 ///
0978 /// This is the main interface to get coverage information, using a profile to
0979 /// fill out execution counts.
0980 class CoverageMapping {
0981   DenseMap<size_t, DenseSet<size_t>> RecordProvenance;
0982   std::vector<FunctionRecord> Functions;
0983   DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
0984   std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
0985 
0986   std::optional<bool> SingleByteCoverage;
0987 
0988   CoverageMapping() = default;
0989 
0990   // Load coverage records from readers.
0991   static Error loadFromReaders(
0992       ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
0993       IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage);
0994 
0995   // Load coverage records from file.
0996   static Error
0997   loadFromFile(StringRef Filename, StringRef Arch, StringRef CompilationDir,
0998                IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage,
0999                bool &DataFound,
1000                SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr);
1001 
1002   /// Add a function record corresponding to \p Record.
1003   Error loadFunctionRecord(const CoverageMappingRecord &Record,
1004                            IndexedInstrProfReader &ProfileReader);
1005 
1006   /// Look up the indices for function records which are at least partially
1007   /// defined in the specified file. This is guaranteed to return a superset of
1008   /// such records: extra records not in the file may be included if there is
1009   /// a hash collision on the filename. Clients must be robust to collisions.
1010   ArrayRef<unsigned>
1011   getImpreciseRecordIndicesForFilename(StringRef Filename) const;
1012 
1013 public:
1014   CoverageMapping(const CoverageMapping &) = delete;
1015   CoverageMapping &operator=(const CoverageMapping &) = delete;
1016 
1017   /// Load the coverage mapping using the given readers.
1018   static Expected<std::unique_ptr<CoverageMapping>>
1019   load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
1020        IndexedInstrProfReader &ProfileReader);
1021 
1022   /// Load the coverage mapping from the given object files and profile. If
1023   /// \p Arches is non-empty, it must specify an architecture for each object.
1024   /// Ignores non-instrumented object files unless all are not instrumented.
1025   static Expected<std::unique_ptr<CoverageMapping>>
1026   load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
1027        vfs::FileSystem &FS, ArrayRef<StringRef> Arches = {},
1028        StringRef CompilationDir = "",
1029        const object::BuildIDFetcher *BIDFetcher = nullptr,
1030        bool CheckBinaryIDs = false);
1031 
1032   /// The number of functions that couldn't have their profiles mapped.
1033   ///
1034   /// This is a count of functions whose profile is out of date or otherwise
1035   /// can't be associated with any coverage information.
1036   unsigned getMismatchedCount() const { return FuncHashMismatches.size(); }
1037 
1038   /// A hash mismatch occurs when a profile record for a symbol does not have
1039   /// the same hash as a coverage mapping record for the same symbol. This
1040   /// returns a list of hash mismatches, where each mismatch is a pair of the
1041   /// symbol name and its coverage mapping hash.
1042   ArrayRef<std::pair<std::string, uint64_t>> getHashMismatches() const {
1043     return FuncHashMismatches;
1044   }
1045 
1046   /// Returns a lexicographically sorted, unique list of files that are
1047   /// covered.
1048   std::vector<StringRef> getUniqueSourceFiles() const;
1049 
1050   /// Get the coverage for a particular file.
1051   ///
1052   /// The given filename must be the name as recorded in the coverage
1053   /// information. That is, only names returned from getUniqueSourceFiles will
1054   /// yield a result.
1055   CoverageData getCoverageForFile(StringRef Filename) const;
1056 
1057   /// Get the coverage for a particular function.
1058   CoverageData getCoverageForFunction(const FunctionRecord &Function) const;
1059 
1060   /// Get the coverage for an expansion within a coverage set.
1061   CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const;
1062 
1063   /// Gets all of the functions covered by this profile.
1064   iterator_range<FunctionRecordIterator> getCoveredFunctions() const {
1065     return make_range(FunctionRecordIterator(Functions),
1066                       FunctionRecordIterator());
1067   }
1068 
1069   /// Gets all of the functions in a particular file.
1070   iterator_range<FunctionRecordIterator>
1071   getCoveredFunctions(StringRef Filename) const {
1072     return make_range(
1073         FunctionRecordIterator(Functions, Filename,
1074                                getImpreciseRecordIndicesForFilename(Filename)),
1075         FunctionRecordIterator());
1076   }
1077 
1078   /// Get the list of function instantiation groups in a particular file.
1079   ///
1080   /// Every instantiation group in a program is attributed to exactly one file:
1081   /// the file in which the definition for the common function begins.
1082   std::vector<InstantiationGroup>
1083   getInstantiationGroups(StringRef Filename) const;
1084 };
1085 
1086 /// Coverage statistics for a single line.
1087 class LineCoverageStats {
1088   uint64_t ExecutionCount;
1089   bool HasMultipleRegions;
1090   bool Mapped;
1091   unsigned Line;
1092   ArrayRef<const CoverageSegment *> LineSegments;
1093   const CoverageSegment *WrappedSegment;
1094 
1095   friend class LineCoverageIterator;
1096   LineCoverageStats() = default;
1097 
1098 public:
1099   LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments,
1100                     const CoverageSegment *WrappedSegment, unsigned Line);
1101 
1102   uint64_t getExecutionCount() const { return ExecutionCount; }
1103 
1104   bool hasMultipleRegions() const { return HasMultipleRegions; }
1105 
1106   bool isMapped() const { return Mapped; }
1107 
1108   unsigned getLine() const { return Line; }
1109 
1110   ArrayRef<const CoverageSegment *> getLineSegments() const {
1111     return LineSegments;
1112   }
1113 
1114   const CoverageSegment *getWrappedSegment() const { return WrappedSegment; }
1115 };
1116 
1117 /// An iterator over the \c LineCoverageStats objects for lines described by
1118 /// a \c CoverageData instance.
1119 class LineCoverageIterator
1120     : public iterator_facade_base<LineCoverageIterator,
1121                                   std::forward_iterator_tag,
1122                                   const LineCoverageStats> {
1123 public:
1124   LineCoverageIterator(const CoverageData &CD)
1125       : LineCoverageIterator(CD, CD.begin()->Line) {}
1126 
1127   LineCoverageIterator(const CoverageData &CD, unsigned Line)
1128       : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false),
1129         Line(Line) {
1130     this->operator++();
1131   }
1132 
1133   bool operator==(const LineCoverageIterator &R) const {
1134     return &CD == &R.CD && Next == R.Next && Ended == R.Ended;
1135   }
1136 
1137   const LineCoverageStats &operator*() const { return Stats; }
1138 
1139   LineCoverageIterator &operator++();
1140 
1141   LineCoverageIterator getEnd() const {
1142     auto EndIt = *this;
1143     EndIt.Next = CD.end();
1144     EndIt.Ended = true;
1145     return EndIt;
1146   }
1147 
1148 private:
1149   const CoverageData &CD;
1150   const CoverageSegment *WrappedSegment;
1151   std::vector<CoverageSegment>::const_iterator Next;
1152   bool Ended;
1153   unsigned Line;
1154   SmallVector<const CoverageSegment *, 4> Segments;
1155   LineCoverageStats Stats;
1156 };
1157 
1158 /// Get a \c LineCoverageIterator range for the lines described by \p CD.
1159 static inline iterator_range<LineCoverageIterator>
1160 getLineCoverageStats(const coverage::CoverageData &CD) {
1161   auto Begin = LineCoverageIterator(CD);
1162   auto End = Begin.getEnd();
1163   return make_range(Begin, End);
1164 }
1165 
1166 // Coverage mappping data (V2) has the following layout:
1167 // IPSK_covmap:
1168 //   [CoverageMapFileHeader]
1169 //   [ArrayStart]
1170 //    [CovMapFunctionRecordV2]
1171 //    [CovMapFunctionRecordV2]
1172 //    ...
1173 //   [ArrayEnd]
1174 //   [Encoded Filenames and Region Mapping Data]
1175 //
1176 // Coverage mappping data (V3) has the following layout:
1177 // IPSK_covmap:
1178 //   [CoverageMapFileHeader]
1179 //   [Encoded Filenames]
1180 // IPSK_covfun:
1181 //   [ArrayStart]
1182 //     odr_name_1: [CovMapFunctionRecordV3]
1183 //     odr_name_2: [CovMapFunctionRecordV3]
1184 //     ...
1185 //   [ArrayEnd]
1186 //
1187 // Both versions of the coverage mapping format encode the same information,
1188 // but the V3 format does so more compactly by taking advantage of linkonce_odr
1189 // semantics (it allows exactly 1 function record per name reference).
1190 
1191 /// This namespace defines accessors shared by different versions of coverage
1192 /// mapping records.
1193 namespace accessors {
1194 
1195 /// Return the structural hash associated with the function.
1196 template <class FuncRecordTy, llvm::endianness Endian>
1197 uint64_t getFuncHash(const FuncRecordTy *Record) {
1198   return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash);
1199 }
1200 
1201 /// Return the coverage map data size for the function.
1202 template <class FuncRecordTy, llvm::endianness Endian>
1203 uint64_t getDataSize(const FuncRecordTy *Record) {
1204   return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize);
1205 }
1206 
1207 /// Return the function lookup key. The value is considered opaque.
1208 template <class FuncRecordTy, llvm::endianness Endian>
1209 uint64_t getFuncNameRef(const FuncRecordTy *Record) {
1210   return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef);
1211 }
1212 
1213 /// Return the PGO name of the function. Used for formats in which the name is
1214 /// a hash.
1215 template <class FuncRecordTy, llvm::endianness Endian>
1216 Error getFuncNameViaRef(const FuncRecordTy *Record,
1217                         InstrProfSymtab &ProfileNames, StringRef &FuncName) {
1218   uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record);
1219   FuncName = ProfileNames.getFuncOrVarName(NameRef);
1220   return Error::success();
1221 }
1222 
1223 /// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the
1224 /// coverage mapping is attached to the file header, instead of to the function
1225 /// record.
1226 template <class FuncRecordTy, llvm::endianness Endian>
1227 StringRef getCoverageMappingOutOfLine(const FuncRecordTy *Record,
1228                                       const char *MappingBuf) {
1229   return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))};
1230 }
1231 
1232 /// Advance to the next out-of-line coverage mapping and its associated
1233 /// function record.
1234 template <class FuncRecordTy, llvm::endianness Endian>
1235 std::pair<const char *, const FuncRecordTy *>
1236 advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) {
1237   return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1};
1238 }
1239 
1240 } // end namespace accessors
1241 
1242 LLVM_PACKED_START
1243 template <class IntPtrT>
1244 struct CovMapFunctionRecordV1 {
1245   using ThisT = CovMapFunctionRecordV1<IntPtrT>;
1246 
1247 #define COVMAP_V1
1248 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1249 #include "llvm/ProfileData/InstrProfData.inc"
1250 #undef COVMAP_V1
1251   CovMapFunctionRecordV1() = delete;
1252 
1253   template <llvm::endianness Endian> uint64_t getFuncHash() const {
1254     return accessors::getFuncHash<ThisT, Endian>(this);
1255   }
1256 
1257   template <llvm::endianness Endian> uint64_t getDataSize() const {
1258     return accessors::getDataSize<ThisT, Endian>(this);
1259   }
1260 
1261   /// Return function lookup key. The value is consider opaque.
1262   template <llvm::endianness Endian> IntPtrT getFuncNameRef() const {
1263     return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
1264   }
1265 
1266   /// Return the PGO name of the function.
1267   template <llvm::endianness Endian>
1268   Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1269     IntPtrT NameRef = getFuncNameRef<Endian>();
1270     uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
1271     FuncName = ProfileNames.getFuncName(NameRef, NameS);
1272     if (NameS && FuncName.empty())
1273       return make_error<CoverageMapError>(coveragemap_error::malformed,
1274                                           "function name is empty");
1275     return Error::success();
1276   }
1277 
1278   template <llvm::endianness Endian>
1279   std::pair<const char *, const ThisT *>
1280   advanceByOne(const char *MappingBuf) const {
1281     return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
1282   }
1283 
1284   template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1285     llvm_unreachable("V1 function format does not contain a filenames ref");
1286   }
1287 
1288   template <llvm::endianness Endian>
1289   StringRef getCoverageMapping(const char *MappingBuf) const {
1290     return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
1291                                                                  MappingBuf);
1292   }
1293 };
1294 
1295 struct CovMapFunctionRecordV2 {
1296   using ThisT = CovMapFunctionRecordV2;
1297 
1298 #define COVMAP_V2
1299 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1300 #include "llvm/ProfileData/InstrProfData.inc"
1301 #undef COVMAP_V2
1302   CovMapFunctionRecordV2() = delete;
1303 
1304   template <llvm::endianness Endian> uint64_t getFuncHash() const {
1305     return accessors::getFuncHash<ThisT, Endian>(this);
1306   }
1307 
1308   template <llvm::endianness Endian> uint64_t getDataSize() const {
1309     return accessors::getDataSize<ThisT, Endian>(this);
1310   }
1311 
1312   template <llvm::endianness Endian> uint64_t getFuncNameRef() const {
1313     return accessors::getFuncNameRef<ThisT, Endian>(this);
1314   }
1315 
1316   template <llvm::endianness Endian>
1317   Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1318     return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
1319                                                        FuncName);
1320   }
1321 
1322   template <llvm::endianness Endian>
1323   std::pair<const char *, const ThisT *>
1324   advanceByOne(const char *MappingBuf) const {
1325     return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
1326   }
1327 
1328   template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1329     llvm_unreachable("V2 function format does not contain a filenames ref");
1330   }
1331 
1332   template <llvm::endianness Endian>
1333   StringRef getCoverageMapping(const char *MappingBuf) const {
1334     return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
1335                                                                  MappingBuf);
1336   }
1337 };
1338 
1339 struct CovMapFunctionRecordV3 {
1340   using ThisT = CovMapFunctionRecordV3;
1341 
1342 #define COVMAP_V3
1343 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
1344 #include "llvm/ProfileData/InstrProfData.inc"
1345 #undef COVMAP_V3
1346   CovMapFunctionRecordV3() = delete;
1347 
1348   template <llvm::endianness Endian> uint64_t getFuncHash() const {
1349     return accessors::getFuncHash<ThisT, Endian>(this);
1350   }
1351 
1352   template <llvm::endianness Endian> uint64_t getDataSize() const {
1353     return accessors::getDataSize<ThisT, Endian>(this);
1354   }
1355 
1356   template <llvm::endianness Endian> uint64_t getFuncNameRef() const {
1357     return accessors::getFuncNameRef<ThisT, Endian>(this);
1358   }
1359 
1360   template <llvm::endianness Endian>
1361   Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
1362     return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
1363                                                        FuncName);
1364   }
1365 
1366   /// Get the filename set reference.
1367   template <llvm::endianness Endian> uint64_t getFilenamesRef() const {
1368     return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef);
1369   }
1370 
1371   /// Read the inline coverage mapping. Ignore the buffer parameter, it is for
1372   /// out-of-line coverage mapping data only.
1373   template <llvm::endianness Endian>
1374   StringRef getCoverageMapping(const char *) const {
1375     return StringRef(&CoverageMapping, getDataSize<Endian>());
1376   }
1377 
1378   // Advance to the next inline coverage mapping and its associated function
1379   // record. Ignore the out-of-line coverage mapping buffer.
1380   template <llvm::endianness Endian>
1381   std::pair<const char *, const CovMapFunctionRecordV3 *>
1382   advanceByOne(const char *) const {
1383     assert(isAddrAligned(Align(8), this) && "Function record not aligned");
1384     const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) -
1385                        sizeof(char) + getDataSize<Endian>();
1386     // Each function record has an alignment of 8, so we need to adjust
1387     // alignment before reading the next record.
1388     Next += offsetToAlignedAddr(Next, Align(8));
1389     return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)};
1390   }
1391 };
1392 
1393 // Per module coverage mapping data header, i.e. CoverageMapFileHeader
1394 // documented above.
1395 struct CovMapHeader {
1396 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name;
1397 #include "llvm/ProfileData/InstrProfData.inc"
1398   template <llvm::endianness Endian> uint32_t getNRecords() const {
1399     return support::endian::byte_swap<uint32_t, Endian>(NRecords);
1400   }
1401 
1402   template <llvm::endianness Endian> uint32_t getFilenamesSize() const {
1403     return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize);
1404   }
1405 
1406   template <llvm::endianness Endian> uint32_t getCoverageSize() const {
1407     return support::endian::byte_swap<uint32_t, Endian>(CoverageSize);
1408   }
1409 
1410   template <llvm::endianness Endian> uint32_t getVersion() const {
1411     return support::endian::byte_swap<uint32_t, Endian>(Version);
1412   }
1413 };
1414 
1415 LLVM_PACKED_END
1416 
1417 enum CovMapVersion {
1418   Version1 = 0,
1419   // Function's name reference from CovMapFuncRecord is changed from raw
1420   // name string pointer to MD5 to support name section compression. Name
1421   // section is also compressed.
1422   Version2 = 1,
1423   // A new interpretation of the columnEnd field is added in order to mark
1424   // regions as gap areas.
1425   Version3 = 2,
1426   // Function records are named, uniqued, and moved to a dedicated section.
1427   Version4 = 3,
1428   // Branch regions referring to two counters are added
1429   Version5 = 4,
1430   // Compilation directory is stored separately and combined with relative
1431   // filenames to produce an absolute file path.
1432   Version6 = 5,
1433   // Branch regions extended and Decision Regions added for MC/DC.
1434   Version7 = 6,
1435   // The current version is Version7.
1436   CurrentVersion = INSTR_PROF_COVMAP_VERSION
1437 };
1438 
1439 // Correspond to "llvmcovm", in little-endian.
1440 constexpr uint64_t TestingFormatMagic = 0x6d766f636d766c6c;
1441 
1442 enum class TestingFormatVersion : uint64_t {
1443   // The first version's number corresponds to the string "testdata" in
1444   // little-endian. This is for a historical reason.
1445   Version1 = 0x6174616474736574,
1446   // Version1 has a defect that it can't store multiple file records. Version2
1447   // fix this problem by adding a new field before the file records section.
1448   Version2 = 1,
1449   // The current testing format version is Version2.
1450   CurrentVersion = Version2
1451 };
1452 
1453 template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
1454   using CovMapFuncRecordType = CovMapFunctionRecordV3;
1455   using NameRefType = uint64_t;
1456 };
1457 
1458 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> {
1459   using CovMapFuncRecordType = CovMapFunctionRecordV2;
1460   using NameRefType = uint64_t;
1461 };
1462 
1463 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> {
1464   using CovMapFuncRecordType = CovMapFunctionRecordV2;
1465   using NameRefType = uint64_t;
1466 };
1467 
1468 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
1469   using CovMapFuncRecordType = CovMapFunctionRecordV1<IntPtrT>;
1470   using NameRefType = IntPtrT;
1471 };
1472 
1473 } // end namespace coverage
1474 
1475 /// Provide DenseMapInfo for CounterExpression
1476 template<> struct DenseMapInfo<coverage::CounterExpression> {
1477   static inline coverage::CounterExpression getEmptyKey() {
1478     using namespace coverage;
1479 
1480     return CounterExpression(CounterExpression::ExprKind::Subtract,
1481                              Counter::getCounter(~0U),
1482                              Counter::getCounter(~0U));
1483   }
1484 
1485   static inline coverage::CounterExpression getTombstoneKey() {
1486     using namespace coverage;
1487 
1488     return CounterExpression(CounterExpression::ExprKind::Add,
1489                              Counter::getCounter(~0U),
1490                              Counter::getCounter(~0U));
1491   }
1492 
1493   static unsigned getHashValue(const coverage::CounterExpression &V) {
1494     return static_cast<unsigned>(
1495         hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(),
1496                      V.RHS.getKind(), V.RHS.getCounterID()));
1497   }
1498 
1499   static bool isEqual(const coverage::CounterExpression &LHS,
1500                       const coverage::CounterExpression &RHS) {
1501     return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS;
1502   }
1503 };
1504 
1505 } // end namespace llvm
1506 
1507 #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H