42#include <system_error> 
   49#define DEBUG_TYPE "coverage-mapping" 
   52  auto [It, Inserted] = ExpressionIndices.try_emplace(
E, Expressions.size());
 
   54    Expressions.push_back(
E);
 
   58void CounterExpressionBuilder::extractTerms(
Counter C, 
int Factor,
 
   59                                            SmallVectorImpl<Term> &Terms) {
 
   60  switch (
C.getKind()) {
 
   67    const auto &
E = Expressions[
C.getExpressionID()];
 
   68    extractTerms(
E.LHS, Factor, Terms);
 
   75Counter CounterExpressionBuilder::simplify(
Counter ExpressionTree) {
 
   78  extractTerms(ExpressionTree, +1, Terms);
 
   82  if (Terms.
size() == 0)
 
   87    return LHS.CounterID < 
RHS.CounterID;
 
   91  auto Prev = Terms.
begin();
 
   92  for (
auto I = Prev + 1, 
E = Terms.
end(); 
I != 
E; ++
I) {
 
   93    if (
I->CounterID == Prev->CounterID) {
 
   94      Prev->Factor += 
I->Factor;
 
  105  for (
auto T : Terms) {
 
  108    for (
int I = 0; 
I < 
T.Factor; ++
I)
 
  117  for (
auto T : Terms) {
 
  120    for (
int I = 0; 
I < -
T.Factor; ++
I)
 
  129  return Simplify ? 
simplify(Cnt) : Cnt;
 
 
  135  return Simplify ? 
simplify(Cnt) : Cnt;
 
 
  140  if (
auto I = Map.find(
C); 
I != Map.end())
 
  143  if (!
C.isExpression())
 
  146  auto CE = Expressions[
C.getExpressionID()];
 
  147  auto NewLHS = 
subst(CE.LHS, Map);
 
  148  auto NewRHS = 
subst(CE.RHS, Map);
 
  153    C = 
add(NewLHS, NewRHS);
 
 
  164  switch (
C.getKind()) {
 
  169    OS << 
'#' << 
C.getCounterID();
 
  172    if (
C.getExpressionID() >= Expressions.size())
 
  174    const auto &E = Expressions[
C.getExpressionID()];
 
  183  if (CounterValues.empty())
 
  186  if (
auto E = 
Value.takeError()) {
 
  190  OS << 
'[' << *
Value << 
']';
 
 
  201    } VisitCount = KNeverVisited;
 
  204  std::stack<StackElem> CounterStack;
 
  205  CounterStack.push({
C});
 
  207  int64_t LastPoppedValue;
 
  209  while (!CounterStack.empty()) {
 
  210    StackElem &Current = CounterStack.top();
 
  212    switch (Current.ICounter.getKind()) {
 
  218      if (Current.ICounter.getCounterID() >= CounterValues.size())
 
  220      LastPoppedValue = CounterValues[Current.ICounter.getCounterID()];
 
  224      if (Current.ICounter.getExpressionID() >= Expressions.size())
 
  226      const auto &E = Expressions[Current.ICounter.getExpressionID()];
 
  227      if (Current.VisitCount == StackElem::KNeverVisited) {
 
  228        CounterStack.push(StackElem{E.LHS});
 
  229        Current.VisitCount = StackElem::KVisitedOnce;
 
  230      } 
else if (Current.VisitCount == StackElem::KVisitedOnce) {
 
  231        Current.LHS = LastPoppedValue;
 
  232        CounterStack.push(StackElem{E.RHS});
 
  233        Current.VisitCount = StackElem::KVisitedTwice;
 
  235        int64_t LHS = Current.LHS;
 
  236        int64_t RHS = LastPoppedValue;
 
  246  return LastPoppedValue;
 
 
  254  if (IndependencePairs)
 
  257  IndependencePairs.emplace();
 
  259  unsigned NumTVs = TV.size();
 
  261  unsigned TVTrueIdx = std::distance(
 
  264                    [&](
auto I) { return (I.second == MCDCRecord::MCDC_True); })
 
  267  for (
unsigned I = TVTrueIdx; 
I < NumTVs; ++
I) {
 
  268    const auto &[
A, ACond] = TV[
I];
 
  270    for (
unsigned J = 0; J < TVTrueIdx; ++J) {
 
  271      const auto &[
B, BCond] = TV[J];
 
  275      auto AB = 
A.getDifferences(
B);
 
  277        IndependencePairs->insert(
 
  278            {AB.find_first(), std::make_pair(J + 1, 
I + 1)});
 
 
  287  auto N = NextIDs.
size();
 
  289  for (
unsigned ID = 0; 
ID < 
N; ++
ID) {
 
  290    for (
unsigned C = 0; 
C < 2; ++
C) {
 
  294      auto NextID = NextIDs[
ID][
C];
 
  295      Nodes[
ID].NextIDs[
C] = NextID;
 
  297        ++Nodes[NextID].InCount;
 
  311  assert(Nodes[0].InCount == 0);
 
  317    auto IID = Q.
begin();
 
  323    for (
unsigned I = 0; 
I < 2; ++
I) {
 
  324      auto NextID = 
Node.NextIDs[
I];
 
  325      assert(NextID != 0 && 
"NextID should not point to the top");
 
  328        Decisions.emplace_back(-
Node.Width, Ord++, 
ID, 
I);
 
  329        assert(Ord == Decisions.size());
 
  334      auto &NextNode = Nodes[NextID];
 
  335      assert(NextNode.InCount > 0);
 
  340      auto NextWidth = int64_t(NextNode.Width) + 
Node.Width;
 
  345      NextNode.Width = NextWidth;
 
  349      if (--NextNode.InCount == 0)
 
  358  for (
auto [NegWidth, Ord, 
ID, 
C] : Decisions) {
 
  359    int Width = -NegWidth;
 
  375  for (
const auto &Idxs : 
Indices)
 
  376    for (
auto Idx : Idxs)
 
 
  386class NextIDsBuilder {
 
  392      : NextIDs(Branches.
size()) {
 
  396    for (
const auto *Branch : Branches) {
 
  397      const auto &BranchParams = Branch->getBranchParams();
 
  398      assert(SeenIDs.
insert(BranchParams.ID).second && 
"Duplicate CondID");
 
  399      NextIDs[BranchParams.ID] = BranchParams.Conds;
 
  421  unsigned NumConditions;
 
  431  std::array<MCDCRecord::TestVectors, 2> ExecVectorsByCond;
 
  444  MCDCRecordProcessor(
const BitVector &Bitmap,
 
  448      : NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),
 
  450        Branches(Branches), NumConditions(DecisionParams.NumConditions),
 
  452        IndependencePairs(NumConditions), ExecVectors(ExecVectorsByCond[
false]),
 
  453        IsVersion11(IsVersion11) {}
 
  464      TV.
set(
ID, MCDCCond);
 
  465      auto NextID = NextIDs[
ID][MCDCCond];
 
  466      auto NextTVIdx = TVIdx + Indices[
ID][MCDCCond];
 
  467      assert(NextID == SavedNodes[
ID].NextIDs[MCDCCond]);
 
  469        buildTestVector(TV, NextID, NextTVIdx);
 
  473      assert(TVIdx < SavedNodes[
ID].Width);
 
  474      assert(TVIdxs.insert(NextTVIdx).second && 
"Duplicate TVIdx");
 
  476      if (!Bitmap[IsVersion11
 
  477                      ? DecisionParams.BitmapIdx * CHAR_BIT + TV.
getIndex()
 
  478                      : DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])
 
  484      ExecVectorsByCond[MCDCCond].push_back({TV, MCDCCond});
 
  493  void findExecutedTestVectors() {
 
  498    MCDCRecord::TestVector TV(NumConditions);
 
  499    buildTestVector(TV, 0, 0);
 
  500    assert(TVIdxs.size() == 
unsigned(NumTestVectors) &&
 
  501           "TVIdxs wasn't fulfilled");
 
  506    auto &ExecVectorsT = ExecVectorsByCond[
true];
 
  507    ExecVectors.append(std::make_move_iterator(ExecVectorsT.begin()),
 
  508                       std::make_move_iterator(ExecVectorsT.end()));
 
  521  MCDCRecord processMCDCRecord() {
 
  536      const auto &BranchParams = 
B->getBranchParams();
 
  537      PosToID[
I] = BranchParams.ID;
 
  538      CondLoc[
I] = 
B->startLoc();
 
  539      Folded[
false][
I] = 
B->FalseCount.isZero();
 
  540      Folded[
true][
I] = 
B->Count.isZero();
 
  544    findExecutedTestVectors();
 
  547    return MCDCRecord(Region, std::move(ExecVectors), std::move(Folded),
 
  548                      std::move(PosToID), std::move(CondLoc));
 
  558  MCDCRecordProcessor MCDCProcessor(Bitmap, 
Region, Branches, IsVersion11);
 
  559  return MCDCProcessor.processMCDCRecord();
 
 
  570    } VisitCount = KNeverVisited;
 
  573  std::stack<StackElem> CounterStack;
 
  574  CounterStack.push({
C});
 
  576  int64_t LastPoppedValue;
 
  578  while (!CounterStack.empty()) {
 
  579    StackElem &Current = CounterStack.top();
 
  581    switch (Current.ICounter.getKind()) {
 
  587      LastPoppedValue = Current.ICounter.getCounterID();
 
  591      if (Current.ICounter.getExpressionID() >= Expressions.size()) {
 
  595        const auto &E = Expressions[Current.ICounter.getExpressionID()];
 
  596        if (Current.VisitCount == StackElem::KNeverVisited) {
 
  597          CounterStack.push(StackElem{E.LHS});
 
  598          Current.VisitCount = StackElem::KVisitedOnce;
 
  599        } 
else if (Current.VisitCount == StackElem::KVisitedOnce) {
 
  600          Current.LHS = LastPoppedValue;
 
  601          CounterStack.push(StackElem{E.RHS});
 
  602          Current.VisitCount = StackElem::KVisitedTwice;
 
  604          int64_t LHS = Current.LHS;
 
  605          int64_t RHS = LastPoppedValue;
 
  606          LastPoppedValue = std::max(LHS, RHS);
 
  615  return LastPoppedValue;
 
 
  618void FunctionRecordIterator::skipOtherFiles() {
 
  619  while (Current != Records.
end() && !Filename.empty() &&
 
  620         Filename != Current->Filenames[0])
 
  622  if (Current == Records.
end())
 
  629  auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
 
  630  if (RecordIt == FilenameHash2RecordIndices.end())
 
  632  return RecordIt->second;
 
  637  unsigned MaxCounterID = 0;
 
  639    MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(
Region.Count));
 
 
  647  unsigned MaxBitmapIdx = 0;
 
  648  unsigned NumConditions = 0;
 
  655    const auto &DecisionParams = 
Region.getDecisionParams();
 
  656    if (MaxBitmapIdx <= DecisionParams.BitmapIdx) {
 
  657      MaxBitmapIdx = DecisionParams.BitmapIdx;
 
  658      NumConditions = DecisionParams.NumConditions;
 
  663    MaxBitmapIdx = MaxBitmapIdx * CHAR_BIT +
 
 
  672class MCDCDecisionRecorder {
 
  678  struct DecisionRecord {
 
  679    const CounterMappingRegion *DecisionRegion;
 
  682    mcdc::DecisionParameters DecisionParams;
 
  698    DenseSet<unsigned> ExpandedFileIDs;
 
  700    DecisionRecord(
const CounterMappingRegion &Decision)
 
  701        : DecisionRegion(&Decision),
 
  702          DecisionParams(Decision.getDecisionParams()),
 
  703          DecisionStartLoc(Decision.startLoc()),
 
  704          DecisionEndLoc(Decision.endLoc()) {
 
  709    bool dominates(
const CounterMappingRegion &R)
 const {
 
  711      if (
R.FileID == DecisionRegion->
FileID &&
 
  712          R.startLoc() >= DecisionStartLoc && 
R.endLoc() <= DecisionEndLoc)
 
  716      return ExpandedFileIDs.
contains(
R.FileID);
 
  728    Result addBranch(
const CounterMappingRegion &Branch) {
 
  744      if (ConditionID == 0)
 
  745        MCDCBranches.
insert(MCDCBranches.
begin(), &Branch);
 
  760    bool recordExpansion(
const CounterMappingRegion &
Expansion) {
 
  776  ~MCDCDecisionRecorder() {
 
  777    assert(Decisions.
empty() && 
"All Decisions have not been resolved");
 
  781  void registerDecision(
const CounterMappingRegion &Decision) {
 
  785  void recordExpansion(
const CounterMappingRegion &
Expansion) {
 
  787      return Decision.recordExpansion(
Expansion);
 
  791  using DecisionAndBranches =
 
  792      std::pair<
const CounterMappingRegion *,             
 
  800  std::optional<DecisionAndBranches>
 
  801  processBranch(
const CounterMappingRegion &Branch) {
 
  803    for (
auto DecisionIter = Decisions.
begin(), DecisionEnd = Decisions.
end();
 
  804         DecisionIter != DecisionEnd; ++DecisionIter)
 
  805      switch (DecisionIter->addBranch(Branch)) {
 
  806      case DecisionRecord::NotProcessed:
 
  808      case DecisionRecord::Processed:
 
  810      case DecisionRecord::Completed:
 
  811        DecisionAndBranches 
Result =
 
  812            std::make_pair(DecisionIter->DecisionRegion,
 
  813                           std::move(DecisionIter->MCDCBranches));
 
  814        Decisions.
erase(DecisionIter); 
 
  824Error CoverageMapping::loadFunctionRecord(
 
  825    const CoverageMappingRecord &Record,
 
  826    const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
 
  829  if (OrigFuncName.
empty())
 
  831                                        "record function name is empty");
 
  840  std::vector<uint64_t> Counts;
 
  842    if (
Error E = ProfileReader.value().get().getFunctionCounts(
 
  846        FuncHashMismatches.emplace_back(std::string(Record.
FunctionName),
 
  857  Ctx.setCounts(Counts);
 
  860      ProfileReader && ProfileReader.value().get().getVersion() <
 
  865    if (
Error E = ProfileReader.value().get().getFunctionBitmap(
 
  869        FuncHashMismatches.emplace_back(std::string(Record.
FunctionName),
 
  880  Ctx.setBitmap(std::move(Bitmap));
 
  893  MCDCDecisionRecorder MCDCDecisions;
 
  899      MCDCDecisions.registerDecision(Region);
 
  902    Expected<int64_t> ExecutionCount = Ctx.evaluate(
Region.Count);
 
  907    Expected<int64_t> AltExecutionCount = Ctx.evaluate(
Region.FalseCount);
 
  912    Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
 
  916      MCDCDecisions.recordExpansion(Region);
 
  924    auto Result = MCDCDecisions.processBranch(Region);
 
  928    auto MCDCDecision = 
Result->first;
 
  929    auto &MCDCBranches = 
Result->second;
 
  934    Expected<MCDCRecord> Record =
 
  935        Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
 
  942    Function.pushMCDCRecord(std::move(*Record));
 
  947  if (!RecordProvenance[FilenamesHash].insert(
hash_value(OrigFuncName)).second)
 
  950  Functions.push_back(std::move(Function));
 
  955  unsigned RecordIndex = Functions.size() - 1;
 
  956  for (StringRef Filename : Record.Filenames) {
 
  957    auto &RecordIndices = FilenameHash2RecordIndices[
hash_value(Filename)];
 
  961    if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
 
  962      RecordIndices.push_back(RecordIndex);
 
  970Error CoverageMapping::loadFromReaders(
 
  971    ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
 
  972    std::optional<std::reference_wrapper<IndexedInstrProfReader>>
 
  974    CoverageMapping &Coverage) {
 
  977             ProfileReader.value().get().hasSingleByteCoverage());
 
  979      !ProfileReader || ProfileReader.value().get().hasSingleByteCoverage();
 
  980  for (
const auto &CoverageReader : CoverageReaders) {
 
  981    for (
auto RecordOrErr : *CoverageReader) {
 
  982      if (
Error E = RecordOrErr.takeError())
 
  984      const auto &Record = *RecordOrErr;
 
  993    ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
 
  994    std::optional<std::reference_wrapper<IndexedInstrProfReader>>
 
  996  auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
 
  997  if (
Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
 
  999  return std::move(Coverage);
 
 
 1011Error CoverageMapping::loadFromFile(
 
 1012    StringRef Filename, StringRef Arch, StringRef CompilationDir,
 
 1013    std::optional<std::reference_wrapper<IndexedInstrProfReader>>
 
 1015    CoverageMapping &Coverage, 
bool &DataFound,
 
 1016    SmallVectorImpl<object::BuildID> *FoundBinaryIDs) {
 
 1018      Filename, 
false, 
false);
 
 1019  if (std::error_code EC = CovMappingBufOrErr.getError())
 
 1021  MemoryBufferRef CovMappingBufRef =
 
 1022      CovMappingBufOrErr.get()->getMemBufferRef();
 
 1027      CovMappingBufRef, Arch, Buffers, CompilationDir,
 
 1028      FoundBinaryIDs ? &BinaryIDs : 
nullptr);
 
 1029  if (
Error E = CoverageReadersOrErr.takeError()) {
 
 1037  for (
auto &Reader : CoverageReadersOrErr.get())
 
 1039  if (FoundBinaryIDs && !Readers.
empty()) {
 
 1045  DataFound |= !Readers.
empty();
 
 1046  if (
Error E = loadFromReaders(Readers, ProfileReader, Coverage))
 
 1056  std::unique_ptr<IndexedInstrProfReader> ProfileReader;
 
 1057  if (ProfileFilename) {
 
 1058    auto ProfileReaderOrErr =
 
 1060    if (
Error E = ProfileReaderOrErr.takeError())
 
 1062    ProfileReader = std::move(ProfileReaderOrErr.get());
 
 1064  auto ProfileReaderRef =
 
 1066          ? std::optional<std::reference_wrapper<IndexedInstrProfReader>>(
 
 1069  auto Coverage = std::unique_ptr<CoverageMapping>(
new CoverageMapping());
 
 1070  bool DataFound = 
false;
 
 1072  auto GetArch = [&](
size_t Idx) {
 
 1075    if (Arches.
size() == 1)
 
 1076      return Arches.
front();
 
 1082    if (
Error E = loadFromFile(File.value(), GetArch(File.index()),
 
 1083                               CompilationDir, ProfileReaderRef, *Coverage,
 
 1084                               DataFound, &FoundBinaryIDs))
 
 1085      return std::move(E);
 
 1089    std::vector<object::BuildID> ProfileBinaryIDs;
 
 1091      if (
Error E = ProfileReader->readBinaryIds(ProfileBinaryIDs))
 
 1095    if (!ProfileBinaryIDs.empty()) {
 
 1097        return std::lexicographical_compare(
A.begin(), 
A.end(), 
B.begin(),
 
 1101      std::set_difference(
 
 1102          ProfileBinaryIDs.begin(), ProfileBinaryIDs.end(),
 
 1103          FoundBinaryIDs.
begin(), FoundBinaryIDs.
end(),
 
 1104          std::inserter(BinaryIDsToFetch, BinaryIDsToFetch.
end()), Compare);
 
 1108      std::optional<std::string> PathOpt = BIDFetcher->
fetch(BinaryID);
 
 1110        std::string Path = std::move(*PathOpt);
 
 1112        if (
Error E = loadFromFile(Path, Arch, CompilationDir, ProfileReaderRef,
 
 1113                                   *Coverage, DataFound))
 
 1114          return std::move(E);
 
 1115      } 
else if (CheckBinaryIDs) {
 
 1117            ProfileFilename.value(),
 
 1119                              "Missing binary ID: " +
 
 1127        join(ObjectFilenames.
begin(), ObjectFilenames.
end(), 
", "),
 
 1129  return std::move(Coverage);
 
 
 1138class FunctionInstantiationSetCollector {
 
 1139  using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
 
 1140  MapT InstantiatedFunctions;
 
 1145    while (
I != E && 
I->FileID != FileID)
 
 1147    assert(
I != E && 
"function does not cover the given file");
 
 1148    auto &Functions = InstantiatedFunctions[
I->startLoc()];
 
 1152  MapT::iterator begin() { 
return InstantiatedFunctions.begin(); }
 
 1153  MapT::iterator end() { 
return InstantiatedFunctions.end(); }
 
 1156class SegmentBuilder {
 
 1157  std::vector<CoverageSegment> &
Segments;
 
 1160  SegmentBuilder(std::vector<CoverageSegment> &Segments) : 
Segments(
Segments) {}
 
 1166  void startSegment(
const CountedRegion &Region, 
LineColPair StartLoc,
 
 1167                    bool IsRegionEntry, 
bool EmitSkippedRegion = 
false) {
 
 1168    bool HasCount = !EmitSkippedRegion &&
 
 1172    if (!
Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
 
 1174      if (
Last.HasCount == HasCount && 
Last.Count == 
Region.ExecutionCount &&
 
 1175          !
Last.IsRegionEntry)
 
 1180      Segments.emplace_back(StartLoc.first, StartLoc.second,
 
 1181                            Region.ExecutionCount, IsRegionEntry,
 
 1184      Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
 
 1188      dbgs() << 
"Segment at " << 
Last.Line << 
":" << 
Last.Col
 
 1189             << 
" (count = " << 
Last.Count << 
")" 
 1190             << (
Last.IsRegionEntry ? 
", RegionEntry" : 
"")
 
 1191             << (!
Last.HasCount ? 
", Skipped" : 
"")
 
 1192             << (
Last.IsGapRegion ? 
", Gap" : 
"") << 
"\n";
 
 1201  void completeRegionsUntil(std::optional<LineColPair> Loc,
 
 1202                            unsigned FirstCompletedRegion) {
 
 1205    auto CompletedRegionsIt = ActiveRegions.
begin() + FirstCompletedRegion;
 
 1206    std::stable_sort(CompletedRegionsIt, ActiveRegions.
end(),
 
 1207                      [](
const CountedRegion *L, 
const CountedRegion *R) {
 
 1208                        return L->endLoc() < R->endLoc();
 
 1212    for (
unsigned I = FirstCompletedRegion + 1, 
E = ActiveRegions.
size(); 
I < 
E;
 
 1214      const auto *CompletedRegion = ActiveRegions[
I];
 
 1215      assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
 
 1216             "Completed region ends after start of new region");
 
 1218      const auto *PrevCompletedRegion = ActiveRegions[
I - 1];
 
 1219      auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
 
 1222      if (Loc && CompletedSegmentLoc == *Loc)
 
 1227      if (CompletedSegmentLoc == CompletedRegion->endLoc())
 
 1231      for (
unsigned J = 
I + 1; J < 
E; ++J)
 
 1232        if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
 
 1233          CompletedRegion = ActiveRegions[J];
 
 1235      startSegment(*CompletedRegion, CompletedSegmentLoc, 
false);
 
 1239    if (FirstCompletedRegion && 
Last->endLoc() != *Loc) {
 
 1242      startSegment(*ActiveRegions[FirstCompletedRegion - 1], 
Last->endLoc(),
 
 1244    } 
else if (!FirstCompletedRegion && (!Loc || *Loc != 
Last->endLoc())) {
 
 1247      startSegment(*
Last, 
Last->endLoc(), 
false, 
true);
 
 1251    ActiveRegions.
erase(CompletedRegionsIt, ActiveRegions.
end());
 
 1255    for (
const auto &CR : 
enumerate(Regions)) {
 
 1256      auto CurStartLoc = CR.value().startLoc();
 
 1259      auto CompletedRegions =
 
 1260          std::stable_partition(ActiveRegions.
begin(), ActiveRegions.
end(),
 
 1261                                [&](
const CountedRegion *Region) {
 
 1262                                  return !(Region->endLoc() <= CurStartLoc);
 
 1264      if (CompletedRegions != ActiveRegions.
end()) {
 
 1265        unsigned FirstCompletedRegion =
 
 1266            std::distance(ActiveRegions.
begin(), CompletedRegions);
 
 1267        completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
 
 1273      if (CurStartLoc == CR.value().endLoc()) {
 
 1276        const bool Skipped =
 
 1277            (CR.index() + 1) == Regions.
size() ||
 
 1279        startSegment(ActiveRegions.
empty() ? CR.value() : *ActiveRegions.
back(),
 
 1280                     CurStartLoc, !GapRegion, Skipped);
 
 1283        if (Skipped && !ActiveRegions.
empty())
 
 1284          startSegment(*ActiveRegions.
back(), CurStartLoc, 
false);
 
 1287      if (CR.index() + 1 == Regions.
size() ||
 
 1288          CurStartLoc != Regions[CR.index() + 1].startLoc()) {
 
 1291        startSegment(CR.value(), CurStartLoc, !GapRegion);
 
 1299    if (!ActiveRegions.
empty())
 
 1300      completeRegionsUntil(std::nullopt, 0);
 
 1305    llvm::sort(Regions, [](
const CountedRegion &
LHS, 
const CountedRegion &
RHS) {
 
 1306      if (
LHS.startLoc() != 
RHS.startLoc())
 
 1307        return LHS.startLoc() < 
RHS.startLoc();
 
 1308      if (
LHS.endLoc() != 
RHS.endLoc())
 
 1310        return RHS.endLoc() < 
LHS.endLoc();
 
 1320                    "Unexpected order of region kind values");
 
 1321      return LHS.Kind < 
RHS.Kind;
 
 1328    if (Regions.
empty())
 
 1331    auto End = Regions.
end();
 
 1332    for (
auto I = Regions.
begin() + 1; 
I != End; ++
I) {
 
 1333      if (
Active->startLoc() != 
I->startLoc() ||
 
 1334          Active->endLoc() != 
I->endLoc()) {
 
 1354        Active->ExecutionCount += 
I->ExecutionCount;
 
 1356    return Regions.
drop_back(std::distance(++Active, End));
 
 1361  static std::vector<CoverageSegment>
 
 1363    std::vector<CoverageSegment> 
Segments;
 
 1364    SegmentBuilder Builder(Segments);
 
 1366    sortNestedRegions(Regions);
 
 1370      dbgs() << 
"Combined regions:\n";
 
 1371      for (
const auto &CR : CombinedRegions)
 
 1372        dbgs() << 
"  " << CR.LineStart << 
":" << CR.ColumnStart << 
" -> " 
 1373               << CR.LineEnd << 
":" << CR.ColumnEnd
 
 1374               << 
" (count=" << CR.ExecutionCount << 
")\n";
 
 1377    Builder.buildSegmentsImpl(CombinedRegions);
 
 1383      if (!(
L.Line < 
R.Line) && !(
L.Line == 
R.Line && 
L.Col < 
R.Col)) {
 
 1384        if (
L.Line == 
R.Line && 
L.Col == 
R.Col && !
L.HasCount)
 
 1387                          << 
" followed by " << 
R.Line << 
":" << 
R.Col << 
"\n");
 
 1388        assert(
false && 
"Coverage segments not unique or sorted");
 
 1400  std::vector<StringRef> Filenames;
 
 1405  Filenames.erase(
Last, Filenames.end());
 
 
 1413    if (SourceFile == 
Function.Filenames[
I])
 
 1414      FilenameEquivalence[
I] = 
true;
 
 1415  return FilenameEquivalence;
 
 
 1419static std::optional<unsigned>
 
 1422  for (
const auto &CR : 
Function.CountedRegions)
 
 1424      IsNotExpandedFile[CR.ExpandedFileID] = 
false;
 
 1427    return std::nullopt;
 
 
 1434static std::optional<unsigned>
 
 1437  if (
I && SourceFile == 
Function.Filenames[*
I])
 
 1439  return std::nullopt;
 
 
 1447  assert(SingleByteCoverage);
 
 1448  CoverageData FileCoverage(*SingleByteCoverage, Filename);
 
 1449  std::vector<CountedRegion> Regions;
 
 1454      getImpreciseRecordIndicesForFilename(Filename);
 
 1455  for (
unsigned RecordIndex : RecordIndices) {
 
 1459    for (
const auto &CR : 
Function.CountedRegions)
 
 1460      if (FileIDs.test(CR.FileID)) {
 
 1461        Regions.push_back(CR);
 
 1463          FileCoverage.Expansions.emplace_back(CR, 
Function);
 
 1466    for (
const auto &CR : 
Function.CountedBranchRegions)
 
 1467      if (FileIDs.test(CR.FileID))
 
 1468        FileCoverage.BranchRegions.push_back(CR);
 
 1470    for (
const auto &MR : 
Function.MCDCRecords)
 
 1471      if (FileIDs.test(MR.getDecisionRegion().FileID))
 
 1472        FileCoverage.MCDCRecords.push_back(MR);
 
 1475  LLVM_DEBUG(
dbgs() << 
"Emitting segments for file: " << Filename << 
"\n");
 
 1476  FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
 
 1478  return FileCoverage;
 
 
 1481std::vector<InstantiationGroup>
 
 1483  FunctionInstantiationSetCollector InstantiationSetCollector;
 
 1487      getImpreciseRecordIndicesForFilename(Filename);
 
 1488  for (
unsigned RecordIndex : RecordIndices) {
 
 1493    InstantiationSetCollector.insert(
Function, *MainFileID);
 
 1496  std::vector<InstantiationGroup> Result;
 
 1497  for (
auto &InstantiationSet : InstantiationSetCollector) {
 
 1499                          InstantiationSet.first.second,
 
 1500                          std::move(InstantiationSet.second)};
 
 1501    Result.emplace_back(std::move(IG));
 
 
 1512  assert(SingleByteCoverage);
 
 1515  std::vector<CountedRegion> Regions;
 
 1516  for (
const auto &CR : 
Function.CountedRegions)
 
 1517    if (CR.FileID == *MainFileID) {
 
 1518      Regions.push_back(CR);
 
 1520        FunctionCoverage.Expansions.emplace_back(CR, 
Function);
 
 1523  for (
const auto &CR : 
Function.CountedBranchRegions)
 
 1524    if (CR.FileID == *MainFileID)
 
 1525      FunctionCoverage.BranchRegions.push_back(CR);
 
 1528  for (
const auto &MR : 
Function.MCDCRecords)
 
 1529    if (MR.getDecisionRegion().FileID == *MainFileID)
 
 1530      FunctionCoverage.MCDCRecords.push_back(MR);
 
 1534  FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
 
 1536  return FunctionCoverage;
 
 
 1541  assert(SingleByteCoverage);
 
 1544  std::vector<CountedRegion> Regions;
 
 1545  for (
const auto &CR : 
Expansion.Function.CountedRegions)
 
 1547      Regions.push_back(CR);
 
 1549        ExpansionCoverage.Expansions.emplace_back(CR, 
Expansion.Function);
 
 1551  for (
const auto &CR : 
Expansion.Function.CountedBranchRegions)
 
 1554      ExpansionCoverage.BranchRegions.push_back(CR);
 
 1558  ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
 
 1560  return ExpansionCoverage;
 
 
 1563LineCoverageStats::LineCoverageStats(
 
 1566    : ExecutionCount(0), HasMultipleRegions(
false), Mapped(
false), Line(Line),
 
 1567      LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
 
 1569  unsigned MinRegionCount = 0;
 
 1571    return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
 
 1573  for (
unsigned I = 0; 
I < LineSegments.size() && MinRegionCount < 2; ++
I)
 
 1574    if (isStartOfRegion(LineSegments[
I]))
 
 1577  bool StartOfSkippedRegion = !LineSegments.empty() &&
 
 1578                              !LineSegments.front()->HasCount &&
 
 1579                              LineSegments.front()->IsRegionEntry;
 
 1581  HasMultipleRegions = MinRegionCount > 1;
 
 1583      !StartOfSkippedRegion &&
 
 1584      ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
 
 1588  Mapped |= 
any_of(LineSegments, [](
const auto *Seq) {
 
 1589    return Seq->IsRegionEntry && Seq->HasCount;
 
 1599    ExecutionCount = WrappedSegment->Count;
 
 1600  if (!MinRegionCount)
 
 1602  for (
const auto *LS : LineSegments)
 
 1603    if (isStartOfRegion(LS))
 
 1604      ExecutionCount = std::max(ExecutionCount, LS->Count);
 
 
 1608  if (Next == CD.end()) {
 
 1613  if (Segments.size())
 
 1614    WrappedSegment = Segments.back();
 
 1616  while (Next != CD.end() && Next->Line == Line)
 
 1617    Segments.push_back(&*Next++);
 
 
 1624                                           const std::string &ErrMsg = 
"") {
 
 1633    OS << 
"end of File";
 
 1636    OS << 
"no coverage data found";
 
 1639    OS << 
"unsupported coverage format version";
 
 1642    OS << 
"truncated coverage data";
 
 1645    OS << 
"malformed coverage data";
 
 1648    OS << 
"failed to decompress coverage data (zlib)";
 
 1651    OS << 
"`-arch` specifier is invalid or missing for universal binary";
 
 1656  if (!ErrMsg.empty())
 
 1657    OS << 
": " << ErrMsg;
 
 
 1667class CoverageMappingErrorCategoryType : 
public std::error_category {
 
 1668  const char *
name() 
const noexcept
 override { 
return "llvm.coveragemap"; }
 
 1669  std::string message(
int IE)
 const override {
 
 1681  static CoverageMappingErrorCategoryType ErrorCategory;
 
 1682  return ErrorCategory;
 
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a library for handling Build IDs and using them to find debug info.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static SmallBitVector gatherFileIDs(StringRef SourceFile, const FunctionRecord &Function)
static std::optional< unsigned > findMainViewFileID(const FunctionRecord &Function)
Return the ID of the file where the definition of the function is located.
static bool isExpansion(const CountedRegion &R, unsigned FileID)
static Error handleMaybeNoDataFoundError(Error E)
static unsigned getMaxBitmapSize(const CoverageMappingRecord &Record, bool IsVersion11)
Returns the bit count.
static std::string getCoverageMapErrString(coveragemap_error Err, const std::string &ErrMsg="")
static unsigned getMaxCounterID(const CounterMappingContext &Ctx, const CoverageMappingRecord &Record)
This file defines the DenseMap class.
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)
This file implements the SmallBitVector class.
This file defines the SmallVector class.
Defines the virtual file system interface vfs::FileSystem.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")
Factory method to create an indexed reader.
static std::pair< instrprof_error, std::string > take(Error E)
Consume an Error and return the raw enum value contained within it, and the optional error message.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
MutableArrayRef< T > drop_back(size_t N=1) const
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
int find_first() const
Returns the index of the first set bit, -1 if none of the bits are set.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator erase(const_iterator CI)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
LLVM Value Representation.
static Expected< std::vector< std::unique_ptr< BinaryCoverageReader > > > create(MemoryBufferRef ObjectBuffer, StringRef Arch, SmallVectorImpl< std::unique_ptr< MemoryBuffer > > &ObjectFileBuffers, StringRef CompilationDir="", SmallVectorImpl< object::BuildIDRef > *BinaryIDs=nullptr)
LLVM_ABI Counter subtract(Counter LHS, Counter RHS, bool Simplify=true)
Return a counter that represents the expression that subtracts RHS from LHS.
LLVM_ABI Counter add(Counter LHS, Counter RHS, bool Simplify=true)
Return a counter that represents the expression that adds LHS and RHS.
LLVM_ABI Counter subst(Counter C, const SubstMap &Map)
std::map< Counter, Counter > SubstMap
K to V map.
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
LLVM_ABI Expected< MCDCRecord > evaluateMCDCRegion(const CounterMappingRegion &Region, ArrayRef< const CounterMappingRegion * > Branches, bool IsVersion11)
Return an MCDC record that indicates executed test vectors and condition pairs.
LLVM_ABI Expected< int64_t > evaluate(const Counter &C) const
Return the number of times that a region of code associated with this counter was executed.
LLVM_ABI unsigned getMaxCounterID(const Counter &C) const
LLVM_ABI void dump(const Counter &C, raw_ostream &OS) const
Coverage information to be processed or displayed.
std::string message() const override
Return the error message as a string.
coveragemap_error get() const
const std::string & getMessage() const
static LLVM_ABI Expected< std::unique_ptr< CoverageMapping > > load(ArrayRef< std::unique_ptr< CoverageMappingReader > > CoverageReaders, std::optional< std::reference_wrapper< IndexedInstrProfReader > > &ProfileReader)
Load the coverage mapping using the given readers.
LLVM_ABI std::vector< StringRef > getUniqueSourceFiles() const
Returns a lexicographically sorted, unique list of files that are covered.
LLVM_ABI CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const
Get the coverage for an expansion within a coverage set.
iterator_range< FunctionRecordIterator > getCoveredFunctions() const
Gets all of the functions covered by this profile.
LLVM_ABI CoverageData getCoverageForFunction(const FunctionRecord &Function) const
Get the coverage for a particular function.
LLVM_ABI std::vector< InstantiationGroup > getInstantiationGroups(StringRef Filename) const
Get the list of function instantiation groups in a particular file.
LLVM_ABI CoverageData getCoverageForFile(StringRef Filename) const
Get the coverage for a particular file.
Iterator over Functions, optionally filtered to a single file.
An instantiation group contains a FunctionRecord list, such that each record corresponds to a distinc...
LineCoverageIterator(const CoverageData &CD)
LLVM_ABI LineCoverageIterator & operator++()
Coverage statistics for a single line.
auto getIndex() const
Equivalent to buildTestVector's Index.
void set(int I, CondState Val)
Set the condition Val at position I.
Compute TestVector Indices "TVIdx" from the Conds graph.
static constexpr auto HardMaxTVs
Hard limit of test vectors.
LLVM_ABI TVIdxBuilder(const SmallVectorImpl< ConditionIDs > &NextIDs, int Offset=0)
Calculate and assign Indices.
SmallVector< std::array< int, 2 > > Indices
Output: Index for TestVectors bitmap (These are not CondIDs)
int NumTestVectors
Output: The number of test vectors.
SmallVector< MCDCNode > SavedNodes
This is no longer needed after the assignment.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
BuildIDFetcher searches local cache directories for debug info.
virtual std::optional< std::string > fetch(BuildIDRef BuildID) const
Returns the path to the debug file with the given build ID.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
The virtual file system interface.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
int16_t ConditionID
The ID for MCDCBranch.
std::array< ConditionID, 2 > ConditionIDs
LLVM_ABI const std::error_category & coveragemap_category()
std::pair< unsigned, unsigned > LineColPair
@ invalid_or_missing_arch_specifier
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
ArrayRef< uint8_t > BuildIDRef
A reference to a BuildID in binary form.
This is an optimization pass for GlobalISel generic memory operations.
hash_code hash_value(const FixedPointSemantics &Val)
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
LLVM_ABI StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName="<unknown>")
Given a PGO function name, remove the filename prefix and return the original (static) function name.
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
auto unique(Range &&R, Predicate P)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto map_range(ContainerTy &&C, FuncTy F)
@ no_such_file_or_directory
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
void toHex(ArrayRef< uint8_t > Input, bool LowerCase, SmallVectorImpl< char > &Output)
Convert buffer Input to its hexadecimal representation. The returned string is double the size of Inp...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Associates a source range with an execution count.
A Counter expression is a value that represents an arithmetic operation with two counters.
A Counter mapping region associates a source range with a specific counter.
@ ExpansionRegion
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
@ MCDCDecisionRegion
A DecisionRegion represents a top-level boolean expression and is associated with a variable length b...
@ MCDCBranchRegion
A Branch Region can be extended to include IDs to facilitate MC/DC.
@ SkippedRegion
A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...
@ GapRegion
A GapRegion is like a CodeRegion, but its count is only set as the line execution count when its the ...
@ CodeRegion
A CodeRegion associates some code with a counter.
A Counter is an abstract value that describes how to compute the execution count for a region of code...
static Counter getZero()
Return the counter that represents the number zero.
static Counter getCounter(unsigned CounterId)
Return the counter that corresponds to a specific profile counter.
static Counter getExpression(unsigned ExpressionId)
Return the counter that corresponds to a specific addition counter expression.
Coverage mapping information for a single function.
ArrayRef< CounterExpression > Expressions
ArrayRef< CounterMappingRegion > MappingRegions
ArrayRef< StringRef > Filenames
The execution count information starting at a point in a file.
Coverage information for a macro expansion or included file.
Code coverage information for a single function.
llvm::SmallVector< std::pair< TestVector, CondState > > TestVectors
LLVM_ABI void findIndependencePairs()
llvm::DenseMap< unsigned, unsigned > CondIDMap
llvm::DenseMap< unsigned, LineColPair > LineColPairMap
std::array< BitVector, 2 > BoolVector
llvm::DenseMap< unsigned, TVRowPair > TVPairMap
uint16_t NumConditions
Number of Conditions used for a Decision Region.