CoverageMapping.cpp revision 303231
12061Sjkh//=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=//
226510Sjfieber//
32061Sjkh//                     The LLVM Compiler Infrastructure
42061Sjkh//
515603Smarkm// This file is distributed under the University of Illinois Open Source
63197Scsgr// License. See LICENSE.TXT for details.
720710Sasami//
820710Sasami//===----------------------------------------------------------------------===//
93197Scsgr//
102061Sjkh// This file contains support for clang's and llvm's instrumentation based
1112483Speter// code coverage.
122160Scsgr//
132834Swollman//===----------------------------------------------------------------------===//
142061Sjkh
152061Sjkh#include "llvm/ProfileData/Coverage/CoverageMapping.h"
162160Scsgr#include "llvm/ADT/DenseMap.h"
1717308Speter#include "llvm/ADT/Optional.h"
1819320Sadam#include "llvm/ADT/SmallBitVector.h"
1921536Sjmacd#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
2025399Sjb#include "llvm/ProfileData/InstrProfReader.h"
2125980Sasami#include "llvm/Support/Debug.h"
221594Srgrimes#include "llvm/Support/Errc.h"
2317308Speter#include "llvm/Support/ErrorHandling.h"
2417308Speter#include "llvm/Support/ManagedStatic.h"
2517308Speter#include "llvm/Support/Path.h"
2617308Speter#include "llvm/Support/raw_ostream.h"
2717308Speter
2817308Speterusing namespace llvm;
2917308Speterusing namespace coverage;
3019175Sbde
3119175Sbde#define DEBUG_TYPE "coverage-mapping"
3219175Sbde
3319175SbdeCounter CounterExpressionBuilder::get(const CounterExpression &E) {
3417308Speter  auto It = ExpressionIndices.find(E);
3525647Sbde  if (It != ExpressionIndices.end())
3617308Speter    return Counter::getExpression(It->second);
372061Sjkh  unsigned I = Expressions.size();
382061Sjkh  Expressions.push_back(E);
391594Srgrimes  ExpressionIndices[E] = I;
4025313Sbde  return Counter::getExpression(I);
4125313Sbde}
4225313Sbde
4325313Sbdevoid CounterExpressionBuilder::extractTerms(
4425313Sbde    Counter C, int Sign, SmallVectorImpl<std::pair<unsigned, int>> &Terms) {
4525313Sbde  switch (C.getKind()) {
4625313Sbde  case Counter::Zero:
4725313Sbde    break;
487407Srgrimes  case Counter::CounterValueReference:
497108Sphk    Terms.push_back(std::make_pair(C.getCounterID(), Sign));
507108Sphk    break;
517108Sphk  case Counter::Expression:
527407Srgrimes    const auto &E = Expressions[C.getExpressionID()];
537407Srgrimes    extractTerms(E.LHS, Sign, Terms);
547407Srgrimes    extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign,
557108Sphk                 Terms);
562061Sjkh    break;
572061Sjkh  }
582061Sjkh}
5917308Speter
602061SjkhCounter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
612061Sjkh  // Gather constant terms.
622061Sjkh  llvm::SmallVector<std::pair<unsigned, int>, 32> Terms;
632061Sjkh  extractTerms(ExpressionTree, +1, Terms);
642061Sjkh
653197Scsgr  // If there are no terms, this is just a zero. The algorithm below assumes at
662626Scsgr  // least one term.
672626Scsgr  if (Terms.size() == 0)
682061Sjkh    return Counter::getZero();
692061Sjkh
702061Sjkh  // Group the terms by counter ID.
712061Sjkh  std::sort(Terms.begin(), Terms.end(),
722061Sjkh            [](const std::pair<unsigned, int> &LHS,
732061Sjkh               const std::pair<unsigned, int> &RHS) {
7419320Sadam    return LHS.first < RHS.first;
752061Sjkh  });
762061Sjkh
772061Sjkh  // Combine terms by counter ID to eliminate counters that sum to zero.
782061Sjkh  auto Prev = Terms.begin();
792061Sjkh  for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
802061Sjkh    if (I->first == Prev->first) {
812061Sjkh      Prev->second += I->second;
822061Sjkh      continue;
832061Sjkh    }
842061Sjkh    ++Prev;
852061Sjkh    *Prev = *I;
862834Swollman  }
872834Swollman  Terms.erase(++Prev, Terms.end());
882834Swollman
892834Swollman  Counter C;
902834Swollman  // Create additions. We do this before subtractions to avoid constructs like
912834Swollman  // ((0 - X) + Y), as opposed to (Y - X).
921594Srgrimes  for (auto Term : Terms) {
934486Sphk    if (Term.second <= 0)
944486Sphk      continue;
954486Sphk    for (int I = 0; I < Term.second; ++I)
964486Sphk      if (C.isZero())
974486Sphk        C = Counter::getCounter(Term.first);
982061Sjkh      else
992061Sjkh        C = get(CounterExpression(CounterExpression::Add, C,
10025979Sjkh                                  Counter::getCounter(Term.first)));
10125979Sjkh  }
10225979Sjkh
10325979Sjkh  // Create subtractions.
1042061Sjkh  for (auto Term : Terms) {
10525979Sjkh    if (Term.second >= 0)
1062061Sjkh      continue;
1072061Sjkh    for (int I = 0; I < -Term.second; ++I)
10817308Speter      C = get(CounterExpression(CounterExpression::Subtract, C,
1092061Sjkh                                Counter::getCounter(Term.first)));
1102061Sjkh  }
1112061Sjkh  return C;
1122061Sjkh}
1132061Sjkh
11412483SpeterCounter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
11512483Speter  return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
11612483Speter}
11712483Speter
1182061SjkhCounter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
1192061Sjkh  return simplify(
1208854Srgrimes      get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
1212061Sjkh}
1222061Sjkh
12312483Spetervoid CounterMappingContext::dump(const Counter &C,
1242061Sjkh                                 llvm::raw_ostream &OS) const {
12518714Sache  switch (C.getKind()) {
12618714Sache  case Counter::Zero:
12718714Sache    OS << '0';
12817308Speter    return;
12917308Speter  case Counter::CounterValueReference:
13017308Speter    OS << '#' << C.getCounterID();
13117308Speter    break;
13221536Sjmacd  case Counter::Expression: {
13315603Smarkm    if (C.getExpressionID() >= Expressions.size())
13417308Speter      return;
13517308Speter    const auto &E = Expressions[C.getExpressionID()];
13617308Speter    OS << '(';
13717308Speter    dump(E.LHS, OS);
13817308Speter    OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
13917308Speter    dump(E.RHS, OS);
14017308Speter    OS << ')';
14117308Speter    break;
14217308Speter  }
14318362Sjkh  }
14419966Sache  if (CounterValues.empty())
14518362Sjkh    return;
14617308Speter  Expected<int64_t> Value = evaluate(C);
14717308Speter  if (auto E = Value.takeError()) {
14817308Speter    llvm::consumeError(std::move(E));
14917308Speter    return;
15017308Speter  }
15117308Speter  OS << '[' << *Value << ']';
15216550Sjkh}
1532061Sjkh
15417308SpeterExpected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
1552061Sjkh  switch (C.getKind()) {
15617308Speter  case Counter::Zero:
1572061Sjkh    return 0;
15817308Speter  case Counter::CounterValueReference:
15917308Speter    if (C.getCounterID() >= CounterValues.size())
16017308Speter      return errorCodeToError(errc::argument_out_of_domain);
16117308Speter    return CounterValues[C.getCounterID()];
16217308Speter  case Counter::Expression: {
16317308Speter    if (C.getExpressionID() >= Expressions.size())
16417466Speter      return errorCodeToError(errc::argument_out_of_domain);
16517308Speter    const auto &E = Expressions[C.getExpressionID()];
16617308Speter    Expected<int64_t> LHS = evaluate(E.LHS);
16717466Speter    if (!LHS)
16817308Speter      return LHS;
16917308Speter    Expected<int64_t> RHS = evaluate(E.RHS);
17017308Speter    if (!RHS)
17117308Speter      return RHS;
17217466Speter    return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
17317308Speter  }
17417308Speter  }
17517308Speter  llvm_unreachable("Unhandled CounterKind");
17617308Speter}
17717308Speter
17817308Spetervoid FunctionRecordIterator::skipOtherFiles() {
17917308Speter  while (Current != Records.end() && !Filename.empty() &&
18017308Speter         Filename != Current->Filenames[0])
18117308Speter    ++Current;
18217308Speter  if (Current == Records.end())
18317308Speter    *this = FunctionRecordIterator();
18417308Speter}
18517308Speter
18617308SpeterExpected<std::unique_ptr<CoverageMapping>>
18717308SpeterCoverageMapping::load(CoverageMappingReader &CoverageReader,
18817308Speter                      IndexedInstrProfReader &ProfileReader) {
18917308Speter  auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
19017308Speter
19117308Speter  std::vector<uint64_t> Counts;
19217308Speter  for (const auto &Record : CoverageReader) {
19317308Speter    CounterMappingContext Ctx(Record.Expressions);
19417308Speter
19517308Speter    Counts.clear();
19617308Speter    if (Error E = ProfileReader.getFunctionCounts(
19717308Speter            Record.FunctionName, Record.FunctionHash, Counts)) {
19817308Speter      instrprof_error IPE = InstrProfError::take(std::move(E));
19917308Speter      if (IPE == instrprof_error::hash_mismatch) {
20026510Sjfieber        Coverage->MismatchedFunctionCount++;
20117308Speter        continue;
20217308Speter      } else if (IPE != instrprof_error::unknown_function)
20317308Speter        return make_error<InstrProfError>(IPE);
20417308Speter      Counts.assign(Record.MappingRegions.size(), 0);
20517962Speter    }
20617308Speter    Ctx.setCounts(Counts);
20717962Speter
20817962Speter    assert(!Record.MappingRegions.empty() && "Function has no regions");
20917962Speter
21017962Speter    StringRef OrigFuncName = Record.FunctionName;
21117962Speter    if (Record.Filenames.empty())
21217962Speter      OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
21317962Speter    else
21417962Speter      OrigFuncName =
21517962Speter          getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
21617962Speter    FunctionRecord Function(OrigFuncName, Record.Filenames);
21717962Speter    for (const auto &Region : Record.MappingRegions) {
21817962Speter      Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
21917962Speter      if (auto E = ExecutionCount.takeError()) {
22017962Speter        llvm::consumeError(std::move(E));
22117962Speter        break;
22217308Speter      }
22316550Sjkh      Function.pushRegion(Region, *ExecutionCount);
22417308Speter    }
22517308Speter    if (Function.CountedRegions.size() != Record.MappingRegions.size()) {
22617308Speter      Coverage->MismatchedFunctionCount++;
22717308Speter      continue;
22816550Sjkh    }
22916550Sjkh
23017308Speter    Coverage->Functions.push_back(std::move(Function));
23117308Speter  }
23219966Sache
23317962Speter  return std::move(Coverage);
2342061Sjkh}
23517308Speter
23617308SpeterExpected<std::unique_ptr<CoverageMapping>>
23717308SpeterCoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename,
23817308Speter                      StringRef Arch) {
23917308Speter  auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
24017308Speter  if (std::error_code EC = CounterMappingBuff.getError())
24117308Speter    return errorCodeToError(EC);
24217308Speter  auto CoverageReaderOrErr =
24312483Speter      BinaryCoverageReader::create(CounterMappingBuff.get(), Arch);
24417308Speter  if (Error E = CoverageReaderOrErr.takeError())
24512483Speter    return std::move(E);
24617308Speter  auto CoverageReader = std::move(CoverageReaderOrErr.get());
24712483Speter  auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
2482061Sjkh  if (Error E = ProfileReaderOrErr.takeError())
24917962Speter    return std::move(E);
25017962Speter  auto ProfileReader = std::move(ProfileReaderOrErr.get());
25117308Speter  return load(*CoverageReader, *ProfileReader);
25217962Speter}
25317962Speter
25417962Speternamespace {
25517962Speter/// \brief Distributes functions into instantiation sets.
25617308Speter///
2572061Sjkh/// An instantiation set is a collection of functions that have the same source
25817308Speter/// code, ie, template functions specializations.
25917308Speterclass FunctionInstantiationSetCollector {
26017308Speter  typedef DenseMap<std::pair<unsigned, unsigned>,
26117308Speter                   std::vector<const FunctionRecord *>> MapT;
26217308Speter  MapT InstantiatedFunctions;
26317308Speter
26417308Speterpublic:
2652302Spaul  void insert(const FunctionRecord &Function, unsigned FileID) {
2662302Spaul    auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
2672302Spaul    while (I != E && I->FileID != FileID)
2682302Spaul      ++I;
2692302Spaul    assert(I != E && "function does not cover the given file");
27018714Sache    auto &Functions = InstantiatedFunctions[I->startLoc()];
27110760Sache    Functions.push_back(&Function);
27218714Sache  }
2732302Spaul
27410760Sache  MapT::iterator begin() { return InstantiatedFunctions.begin(); }
27518714Sache
27610760Sache  MapT::iterator end() { return InstantiatedFunctions.end(); }
27710760Sache};
2782302Spaul
2792302Spaulclass SegmentBuilder {
2802302Spaul  std::vector<CoverageSegment> &Segments;
2812302Spaul  SmallVector<const CountedRegion *, 8> ActiveRegions;
28216591Spst
2832302Spaul  SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
2842302Spaul
28517308Speter  /// Start a segment with no count specified.
28617308Speter  void startSegment(unsigned Line, unsigned Col) {
28717308Speter    DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n");
28817308Speter    Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false);
28917308Speter  }
29017308Speter
29117308Speter  /// Start a segment with the given Region's count.
2922061Sjkh  void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
29317308Speter                    const CountedRegion &Region) {
2942061Sjkh    // Avoid creating empty regions.
29517308Speter    if (!Segments.empty() && Segments.back().Line == Line &&
29617308Speter        Segments.back().Col == Col)
29717308Speter      Segments.pop_back();
29817308Speter    DEBUG(dbgs() << "Segment at " << Line << ":" << Col);
29917308Speter    // Set this region's count.
30017308Speter    if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) {
30117308Speter      DEBUG(dbgs() << " with count " << Region.ExecutionCount);
30217308Speter      Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry);
30317308Speter    } else
30417308Speter      Segments.emplace_back(Line, Col, IsRegionEntry);
30517308Speter    DEBUG(dbgs() << "\n");
30617308Speter  }
30717308Speter
30817308Speter  /// Start a segment for the given region.
3092061Sjkh  void startSegment(const CountedRegion &Region) {
31017308Speter    startSegment(Region.LineStart, Region.ColumnStart, true, Region);
31117308Speter  }
31217308Speter
31317308Speter  /// Pop the top region off of the active stack, starting a new segment with
31417308Speter  /// the containing Region's count.
31517308Speter  void popRegion() {
3163626Swollman    const CountedRegion *Active = ActiveRegions.back();
3173626Swollman    unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
3183626Swollman    ActiveRegions.pop_back();
3193626Swollman    if (ActiveRegions.empty())
3203626Swollman      startSegment(Line, Col);
3213626Swollman    else
3223626Swollman      startSegment(Line, Col, false, *ActiveRegions.back());
3233626Swollman  }
3243626Swollman
3253626Swollman  void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
3263626Swollman    for (const auto &Region : Regions) {
3277059Sroberto      // Pop any regions that end before this one starts.
3283626Swollman      while (!ActiveRegions.empty() &&
3293626Swollman             ActiveRegions.back()->endLoc() <= Region.startLoc())
3303626Swollman        popRegion();
3313626Swollman      // Add this region to the stack.
3323626Swollman      ActiveRegions.push_back(&Region);
3333626Swollman      startSegment(Region);
3343626Swollman    }
33517308Speter    // Pop any regions that are left in the stack.
33617308Speter    while (!ActiveRegions.empty())
33717308Speter      popRegion();
33817308Speter  }
33917308Speter
34017308Speter  /// Sort a nested sequence of regions from a single file.
34117308Speter  static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
34217308Speter    std::sort(Regions.begin(), Regions.end(), [](const CountedRegion &LHS,
34317308Speter                                                 const CountedRegion &RHS) {
34417308Speter      if (LHS.startLoc() != RHS.startLoc())
3453626Swollman        return LHS.startLoc() < RHS.startLoc();
34617308Speter      if (LHS.endLoc() != RHS.endLoc())
34717308Speter        // When LHS completely contains RHS, we sort LHS first.
34817308Speter        return RHS.endLoc() < LHS.endLoc();
34917308Speter      // If LHS and RHS cover the same area, we need to sort them according
35017308Speter      // to their kinds so that the most suitable region will become "active"
35117308Speter      // in combineRegions(). Because we accumulate counter values only from
35217308Speter      // regions of the same kind as the first region of the area, prefer
35317308Speter      // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
35417308Speter      static_assert(coverage::CounterMappingRegion::CodeRegion <
35517308Speter                            coverage::CounterMappingRegion::ExpansionRegion &&
35617308Speter                        coverage::CounterMappingRegion::ExpansionRegion <
35717308Speter                            coverage::CounterMappingRegion::SkippedRegion,
35817820Sjkh                    "Unexpected order of region kind values");
35917308Speter      return LHS.Kind < RHS.Kind;
36017820Sjkh    });
36117308Speter  }
36217820Sjkh
36317467Speter  /// Combine counts of regions which cover the same area.
36417308Speter  static ArrayRef<CountedRegion>
36517308Speter  combineRegions(MutableArrayRef<CountedRegion> Regions) {
36617308Speter    if (Regions.empty())
36717308Speter      return Regions;
36817308Speter    auto Active = Regions.begin();
36917308Speter    auto End = Regions.end();
37017308Speter    for (auto I = Regions.begin() + 1; I != End; ++I) {
37117308Speter      if (Active->startLoc() != I->startLoc() ||
37217820Sjkh          Active->endLoc() != I->endLoc()) {
37317820Sjkh        // Shift to the next region.
37417308Speter        ++Active;
37517308Speter        if (Active != I)
37617308Speter          *Active = *I;
37717308Speter        continue;
37814119Speter      }
3792061Sjkh      // Merge duplicate region.
3807130Srgrimes      // If CodeRegions and ExpansionRegions cover the same area, it's probably
3817130Srgrimes      // a macro which is fully expanded to another macro. In that case, we need
3827130Srgrimes      // to accumulate counts only from CodeRegions, or else the area will be
3832061Sjkh      // counted twice.
38425783Speter      // On the other hand, a macro may have a nested macro in its body. If the
38517308Speter      // outer macro is used several times, the ExpansionRegion for the nested
3862685Srgrimes      // macro will also be added several times. These ExpansionRegions cover
3876927Snate      // the same source locations and have to be combined to reach the correct
38818674Speter      // value for that area.
3892685Srgrimes      // We add counts of the regions of the same kind as the active region
3903518Sache      // to handle the both situations.
39126504Sjhay      if (I->Kind == Active->Kind)
3923197Scsgr        Active->ExecutionCount += I->ExecutionCount;
3933197Scsgr    }
39412166Sjkh    return Regions.drop_back(std::distance(++Active, End));
39512485Sjkh  }
3963197Scsgr
39725313Sbdepublic:
39826152Speter  /// Build a list of CoverageSegments from a list of Regions.
3992061Sjkh  static std::vector<CoverageSegment>
4002061Sjkh  buildSegments(MutableArrayRef<CountedRegion> Regions) {
4012061Sjkh    std::vector<CoverageSegment> Segments;
40216786Snate    SegmentBuilder Builder(Segments);
4032883Sphk
40417308Speter    sortNestedRegions(Regions);
40517308Speter    ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
4067281Srgrimes
4073242Spaul    Builder.buildSegmentsImpl(CombinedRegions);
4083242Spaul    return Segments;
4097171Sats  }
4102061Sjkh};
4113213Spst}
41217308Speter
41317308Speterstd::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
4145749Swollman  std::vector<StringRef> Filenames;
4155772Swollman  for (const auto &Function : getCoveredFunctions())
41617308Speter    Filenames.insert(Filenames.end(), Function.Filenames.begin(),
41717308Speter                     Function.Filenames.end());
41826504Sjhay  std::sort(Filenames.begin(), Filenames.end());
4192061Sjkh  auto Last = std::unique(Filenames.begin(), Filenames.end());
42017308Speter  Filenames.erase(Last, Filenames.end());
42117308Speter  return Filenames;
42217308Speter}
4235366Snate
42417820Sjkhstatic SmallBitVector gatherFileIDs(StringRef SourceFile,
42517467Speter                                    const FunctionRecord &Function) {
42617820Sjkh  SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
42717308Speter  for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
42818674Speter    if (SourceFile == Function.Filenames[I])
42918674Speter      FilenameEquivalence[I] = true;
43017820Sjkh  return FilenameEquivalence;
43117308Speter}
43217820Sjkh
43317308Speter/// Return the ID of the file where the definition of the function is located.
43417820Sjkhstatic Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
43517308Speter  SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
43617820Sjkh  for (const auto &CR : Function.CountedRegions)
43717308Speter    if (CR.Kind == CounterMappingRegion::ExpansionRegion)
43817820Sjkh      IsNotExpandedFile[CR.ExpandedFileID] = false;
43917308Speter  int I = IsNotExpandedFile.find_first();
4405728Swollman  if (I == -1)
44117820Sjkh    return None;
44217308Speter  return I;
44321922Sjkh}
44421922Sjkh
44518392Speter/// Check if SourceFile is the file that contains the definition of
44618392Speter/// the Function. Return the ID of the file in that case or None otherwise.
44718392Speterstatic Optional<unsigned> findMainViewFileID(StringRef SourceFile,
44818392Speter                                             const FunctionRecord &Function) {
44918392Speter  Optional<unsigned> I = findMainViewFileID(Function);
45018392Speter  if (I && SourceFile == Function.Filenames[*I])
4515366Snate    return I;
45217308Speter  return None;
45317308Speter}
45417308Speter
4552061Sjkhstatic bool isExpansion(const CountedRegion &R, unsigned FileID) {
45624754Sjdp  return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
45724754Sjdp}
45824754Sjdp
45924754SjdpCoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
4608295Srgrimes  CoverageData FileCoverage(Filename);
46117820Sjkh  std::vector<coverage::CountedRegion> Regions;
46217308Speter
4638295Srgrimes  for (const auto &Function : Functions) {
4648489Srgrimes    auto MainFileID = findMainViewFileID(Filename, Function);
46517820Sjkh    auto FileIDs = gatherFileIDs(Filename, Function);
46617308Speter    for (const auto &CR : Function.CountedRegions)
4678489Srgrimes      if (FileIDs.test(CR.FileID)) {
4688489Srgrimes        Regions.push_back(CR);
46917820Sjkh        if (MainFileID && isExpansion(CR, *MainFileID))
47017308Speter          FileCoverage.Expansions.emplace_back(CR, Function);
4718489Srgrimes      }
4728295Srgrimes  }
47317820Sjkh
47417308Speter  DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
4758295Srgrimes  FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
4762160Scsgr
47717820Sjkh  return FileCoverage;
47817308Speter}
4792160Scsgr
4802279Spaulstd::vector<const FunctionRecord *>
48117820SjkhCoverageMapping::getInstantiations(StringRef Filename) const {
48217308Speter  FunctionInstantiationSetCollector InstantiationSetCollector;
4832279Spaul  for (const auto &Function : Functions) {
48417234Sjraynard    auto MainFileID = findMainViewFileID(Filename, Function);
48517820Sjkh    if (!MainFileID)
48617308Speter      continue;
48711772Snate    InstantiationSetCollector.insert(Function, *MainFileID);
4883197Scsgr  }
48917820Sjkh
49017308Speter  std::vector<const FunctionRecord *> Result;
4912626Scsgr  for (const auto &InstantiationSet : InstantiationSetCollector) {
4928304Srgrimes    if (InstantiationSet.second.size() < 2)
49317820Sjkh      continue;
49417308Speter    Result.insert(Result.end(), InstantiationSet.second.begin(),
4958304Srgrimes                  InstantiationSet.second.end());
4962061Sjkh  }
49717308Speter  return Result;
49817308Speter}
49917308Speter
50017308SpeterCoverageData
50111806SphkCoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
50219175Sbde  auto MainFileID = findMainViewFileID(Function);
50321673Sjkh  if (!MainFileID)
50421536Sjmacd    return CoverageData();
50519175Sbde
50619175Sbde  CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
50719175Sbde  std::vector<coverage::CountedRegion> Regions;
50819175Sbde  for (const auto &CR : Function.CountedRegions)
50919175Sbde    if (CR.FileID == *MainFileID) {
51017308Speter      Regions.push_back(CR);
51119175Sbde      if (isExpansion(CR, *MainFileID))
5122061Sjkh        FunctionCoverage.Expansions.emplace_back(CR, Function);
5131594Srgrimes    }
514
515  DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n");
516  FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
517
518  return FunctionCoverage;
519}
520
521CoverageData CoverageMapping::getCoverageForExpansion(
522    const ExpansionRecord &Expansion) const {
523  CoverageData ExpansionCoverage(
524      Expansion.Function.Filenames[Expansion.FileID]);
525  std::vector<coverage::CountedRegion> Regions;
526  for (const auto &CR : Expansion.Function.CountedRegions)
527    if (CR.FileID == Expansion.FileID) {
528      Regions.push_back(CR);
529      if (isExpansion(CR, Expansion.FileID))
530        ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
531    }
532
533  DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID
534               << "\n");
535  ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
536
537  return ExpansionCoverage;
538}
539
540namespace {
541std::string getCoverageMapErrString(coveragemap_error Err) {
542  switch (Err) {
543  case coveragemap_error::success:
544    return "Success";
545  case coveragemap_error::eof:
546    return "End of File";
547  case coveragemap_error::no_data_found:
548    return "No coverage data found";
549  case coveragemap_error::unsupported_version:
550    return "Unsupported coverage format version";
551  case coveragemap_error::truncated:
552    return "Truncated coverage data";
553  case coveragemap_error::malformed:
554    return "Malformed coverage data";
555  }
556  llvm_unreachable("A value of coveragemap_error has no message.");
557}
558
559// FIXME: This class is only here to support the transition to llvm::Error. It
560// will be removed once this transition is complete. Clients should prefer to
561// deal with the Error value directly, rather than converting to error_code.
562class CoverageMappingErrorCategoryType : public std::error_category {
563  const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; }
564  std::string message(int IE) const override {
565    return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
566  }
567};
568} // end anonymous namespace
569
570std::string CoverageMapError::message() const {
571  return getCoverageMapErrString(Err);
572}
573
574static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
575
576const std::error_category &llvm::coverage::coveragemap_category() {
577  return *ErrorCategory;
578}
579
580char CoverageMapError::ID = 0;
581