1edd7eaddSDimitry Andric //===- CoverageMapping.cpp - Code coverage mapping support ----------------===//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric //                     The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric //
103ca95b02SDimitry Andric // This file contains support for clang's and llvm's instrumentation based
113ca95b02SDimitry Andric // code coverage.
123ca95b02SDimitry Andric //
133ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
143ca95b02SDimitry Andric 
15db17bf38SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMapping.h"
167a7e6055SDimitry Andric #include "llvm/ADT/ArrayRef.h"
173ca95b02SDimitry Andric #include "llvm/ADT/DenseMap.h"
187a7e6055SDimitry Andric #include "llvm/ADT/None.h"
193ca95b02SDimitry Andric #include "llvm/ADT/Optional.h"
203ca95b02SDimitry Andric #include "llvm/ADT/SmallBitVector.h"
217a7e6055SDimitry Andric #include "llvm/ADT/SmallVector.h"
227a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
233ca95b02SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
243ca95b02SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
253ca95b02SDimitry Andric #include "llvm/Support/Debug.h"
263ca95b02SDimitry Andric #include "llvm/Support/Errc.h"
277a7e6055SDimitry Andric #include "llvm/Support/Error.h"
283ca95b02SDimitry Andric #include "llvm/Support/ErrorHandling.h"
293ca95b02SDimitry Andric #include "llvm/Support/ManagedStatic.h"
307a7e6055SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
313ca95b02SDimitry Andric #include "llvm/Support/raw_ostream.h"
327a7e6055SDimitry Andric #include <algorithm>
337a7e6055SDimitry Andric #include <cassert>
347a7e6055SDimitry Andric #include <cstdint>
357a7e6055SDimitry Andric #include <iterator>
362cab237bSDimitry Andric #include <map>
377a7e6055SDimitry Andric #include <memory>
387a7e6055SDimitry Andric #include <string>
397a7e6055SDimitry Andric #include <system_error>
407a7e6055SDimitry Andric #include <utility>
417a7e6055SDimitry Andric #include <vector>
423ca95b02SDimitry Andric 
433ca95b02SDimitry Andric using namespace llvm;
443ca95b02SDimitry Andric using namespace coverage;
453ca95b02SDimitry Andric 
463ca95b02SDimitry Andric #define DEBUG_TYPE "coverage-mapping"
473ca95b02SDimitry Andric 
get(const CounterExpression & E)483ca95b02SDimitry Andric Counter CounterExpressionBuilder::get(const CounterExpression &E) {
493ca95b02SDimitry Andric   auto It = ExpressionIndices.find(E);
503ca95b02SDimitry Andric   if (It != ExpressionIndices.end())
513ca95b02SDimitry Andric     return Counter::getExpression(It->second);
523ca95b02SDimitry Andric   unsigned I = Expressions.size();
533ca95b02SDimitry Andric   Expressions.push_back(E);
543ca95b02SDimitry Andric   ExpressionIndices[E] = I;
553ca95b02SDimitry Andric   return Counter::getExpression(I);
563ca95b02SDimitry Andric }
573ca95b02SDimitry Andric 
extractTerms(Counter C,int Factor,SmallVectorImpl<Term> & Terms)58a580b014SDimitry Andric void CounterExpressionBuilder::extractTerms(Counter C, int Factor,
59a580b014SDimitry Andric                                             SmallVectorImpl<Term> &Terms) {
603ca95b02SDimitry Andric   switch (C.getKind()) {
613ca95b02SDimitry Andric   case Counter::Zero:
623ca95b02SDimitry Andric     break;
633ca95b02SDimitry Andric   case Counter::CounterValueReference:
64a580b014SDimitry Andric     Terms.emplace_back(C.getCounterID(), Factor);
653ca95b02SDimitry Andric     break;
663ca95b02SDimitry Andric   case Counter::Expression:
673ca95b02SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
68a580b014SDimitry Andric     extractTerms(E.LHS, Factor, Terms);
69a580b014SDimitry Andric     extractTerms(
70a580b014SDimitry Andric         E.RHS, E.Kind == CounterExpression::Subtract ? -Factor : Factor, Terms);
713ca95b02SDimitry Andric     break;
723ca95b02SDimitry Andric   }
733ca95b02SDimitry Andric }
743ca95b02SDimitry Andric 
simplify(Counter ExpressionTree)753ca95b02SDimitry Andric Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
763ca95b02SDimitry Andric   // Gather constant terms.
77a580b014SDimitry Andric   SmallVector<Term, 32> Terms;
783ca95b02SDimitry Andric   extractTerms(ExpressionTree, +1, Terms);
793ca95b02SDimitry Andric 
803ca95b02SDimitry Andric   // If there are no terms, this is just a zero. The algorithm below assumes at
813ca95b02SDimitry Andric   // least one term.
823ca95b02SDimitry Andric   if (Terms.size() == 0)
833ca95b02SDimitry Andric     return Counter::getZero();
843ca95b02SDimitry Andric 
853ca95b02SDimitry Andric   // Group the terms by counter ID.
86*b5893f02SDimitry Andric   llvm::sort(Terms, [](const Term &LHS, const Term &RHS) {
87a580b014SDimitry Andric     return LHS.CounterID < RHS.CounterID;
883ca95b02SDimitry Andric   });
893ca95b02SDimitry Andric 
903ca95b02SDimitry Andric   // Combine terms by counter ID to eliminate counters that sum to zero.
913ca95b02SDimitry Andric   auto Prev = Terms.begin();
923ca95b02SDimitry Andric   for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
93a580b014SDimitry Andric     if (I->CounterID == Prev->CounterID) {
94a580b014SDimitry Andric       Prev->Factor += I->Factor;
953ca95b02SDimitry Andric       continue;
963ca95b02SDimitry Andric     }
973ca95b02SDimitry Andric     ++Prev;
983ca95b02SDimitry Andric     *Prev = *I;
993ca95b02SDimitry Andric   }
1003ca95b02SDimitry Andric   Terms.erase(++Prev, Terms.end());
1013ca95b02SDimitry Andric 
1023ca95b02SDimitry Andric   Counter C;
1033ca95b02SDimitry Andric   // Create additions. We do this before subtractions to avoid constructs like
1043ca95b02SDimitry Andric   // ((0 - X) + Y), as opposed to (Y - X).
105a580b014SDimitry Andric   for (auto T : Terms) {
106a580b014SDimitry Andric     if (T.Factor <= 0)
1073ca95b02SDimitry Andric       continue;
108a580b014SDimitry Andric     for (int I = 0; I < T.Factor; ++I)
1093ca95b02SDimitry Andric       if (C.isZero())
110a580b014SDimitry Andric         C = Counter::getCounter(T.CounterID);
1113ca95b02SDimitry Andric       else
1123ca95b02SDimitry Andric         C = get(CounterExpression(CounterExpression::Add, C,
113a580b014SDimitry Andric                                   Counter::getCounter(T.CounterID)));
1143ca95b02SDimitry Andric   }
1153ca95b02SDimitry Andric 
1163ca95b02SDimitry Andric   // Create subtractions.
117a580b014SDimitry Andric   for (auto T : Terms) {
118a580b014SDimitry Andric     if (T.Factor >= 0)
1193ca95b02SDimitry Andric       continue;
120a580b014SDimitry Andric     for (int I = 0; I < -T.Factor; ++I)
1213ca95b02SDimitry Andric       C = get(CounterExpression(CounterExpression::Subtract, C,
122a580b014SDimitry Andric                                 Counter::getCounter(T.CounterID)));
1233ca95b02SDimitry Andric   }
1243ca95b02SDimitry Andric   return C;
1253ca95b02SDimitry Andric }
1263ca95b02SDimitry Andric 
add(Counter LHS,Counter RHS)1273ca95b02SDimitry Andric Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
1283ca95b02SDimitry Andric   return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
1293ca95b02SDimitry Andric }
1303ca95b02SDimitry Andric 
subtract(Counter LHS,Counter RHS)1313ca95b02SDimitry Andric Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
1323ca95b02SDimitry Andric   return simplify(
1333ca95b02SDimitry Andric       get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
1343ca95b02SDimitry Andric }
1353ca95b02SDimitry Andric 
dump(const Counter & C,raw_ostream & OS) const1367a7e6055SDimitry Andric void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
1373ca95b02SDimitry Andric   switch (C.getKind()) {
1383ca95b02SDimitry Andric   case Counter::Zero:
1393ca95b02SDimitry Andric     OS << '0';
1403ca95b02SDimitry Andric     return;
1413ca95b02SDimitry Andric   case Counter::CounterValueReference:
1423ca95b02SDimitry Andric     OS << '#' << C.getCounterID();
1433ca95b02SDimitry Andric     break;
1443ca95b02SDimitry Andric   case Counter::Expression: {
1453ca95b02SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
1463ca95b02SDimitry Andric       return;
1473ca95b02SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
1483ca95b02SDimitry Andric     OS << '(';
1493ca95b02SDimitry Andric     dump(E.LHS, OS);
1503ca95b02SDimitry Andric     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
1513ca95b02SDimitry Andric     dump(E.RHS, OS);
1523ca95b02SDimitry Andric     OS << ')';
1533ca95b02SDimitry Andric     break;
1543ca95b02SDimitry Andric   }
1553ca95b02SDimitry Andric   }
1563ca95b02SDimitry Andric   if (CounterValues.empty())
1573ca95b02SDimitry Andric     return;
1583ca95b02SDimitry Andric   Expected<int64_t> Value = evaluate(C);
1593ca95b02SDimitry Andric   if (auto E = Value.takeError()) {
1607a7e6055SDimitry Andric     consumeError(std::move(E));
1613ca95b02SDimitry Andric     return;
1623ca95b02SDimitry Andric   }
1633ca95b02SDimitry Andric   OS << '[' << *Value << ']';
1643ca95b02SDimitry Andric }
1653ca95b02SDimitry Andric 
evaluate(const Counter & C) const1663ca95b02SDimitry Andric Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
1673ca95b02SDimitry Andric   switch (C.getKind()) {
1683ca95b02SDimitry Andric   case Counter::Zero:
1693ca95b02SDimitry Andric     return 0;
1703ca95b02SDimitry Andric   case Counter::CounterValueReference:
1713ca95b02SDimitry Andric     if (C.getCounterID() >= CounterValues.size())
1723ca95b02SDimitry Andric       return errorCodeToError(errc::argument_out_of_domain);
1733ca95b02SDimitry Andric     return CounterValues[C.getCounterID()];
1743ca95b02SDimitry Andric   case Counter::Expression: {
1753ca95b02SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
1763ca95b02SDimitry Andric       return errorCodeToError(errc::argument_out_of_domain);
1773ca95b02SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
1783ca95b02SDimitry Andric     Expected<int64_t> LHS = evaluate(E.LHS);
1793ca95b02SDimitry Andric     if (!LHS)
1803ca95b02SDimitry Andric       return LHS;
1813ca95b02SDimitry Andric     Expected<int64_t> RHS = evaluate(E.RHS);
1823ca95b02SDimitry Andric     if (!RHS)
1833ca95b02SDimitry Andric       return RHS;
1843ca95b02SDimitry Andric     return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
1853ca95b02SDimitry Andric   }
1863ca95b02SDimitry Andric   }
1873ca95b02SDimitry Andric   llvm_unreachable("Unhandled CounterKind");
1883ca95b02SDimitry Andric }
1893ca95b02SDimitry Andric 
skipOtherFiles()1903ca95b02SDimitry Andric void FunctionRecordIterator::skipOtherFiles() {
1913ca95b02SDimitry Andric   while (Current != Records.end() && !Filename.empty() &&
1923ca95b02SDimitry Andric          Filename != Current->Filenames[0])
1933ca95b02SDimitry Andric     ++Current;
1943ca95b02SDimitry Andric   if (Current == Records.end())
1953ca95b02SDimitry Andric     *this = FunctionRecordIterator();
1963ca95b02SDimitry Andric }
1973ca95b02SDimitry Andric 
loadFunctionRecord(const CoverageMappingRecord & Record,IndexedInstrProfReader & ProfileReader)198d88c1a5aSDimitry Andric Error CoverageMapping::loadFunctionRecord(
199d88c1a5aSDimitry Andric     const CoverageMappingRecord &Record,
2003ca95b02SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
201d88c1a5aSDimitry Andric   StringRef OrigFuncName = Record.FunctionName;
202edd7eaddSDimitry Andric   if (OrigFuncName.empty())
203edd7eaddSDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
204edd7eaddSDimitry Andric 
205d88c1a5aSDimitry Andric   if (Record.Filenames.empty())
206d88c1a5aSDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
207d88c1a5aSDimitry Andric   else
208d88c1a5aSDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
2093ca95b02SDimitry Andric 
2103ca95b02SDimitry Andric   CounterMappingContext Ctx(Record.Expressions);
2113ca95b02SDimitry Andric 
212d88c1a5aSDimitry Andric   std::vector<uint64_t> Counts;
213d88c1a5aSDimitry Andric   if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName,
214d88c1a5aSDimitry Andric                                                 Record.FunctionHash, Counts)) {
2153ca95b02SDimitry Andric     instrprof_error IPE = InstrProfError::take(std::move(E));
2163ca95b02SDimitry Andric     if (IPE == instrprof_error::hash_mismatch) {
2172cab237bSDimitry Andric       FuncHashMismatches.emplace_back(Record.FunctionName, Record.FunctionHash);
218d88c1a5aSDimitry Andric       return Error::success();
2193ca95b02SDimitry Andric     } else if (IPE != instrprof_error::unknown_function)
2203ca95b02SDimitry Andric       return make_error<InstrProfError>(IPE);
2213ca95b02SDimitry Andric     Counts.assign(Record.MappingRegions.size(), 0);
2223ca95b02SDimitry Andric   }
2233ca95b02SDimitry Andric   Ctx.setCounts(Counts);
2243ca95b02SDimitry Andric 
2253ca95b02SDimitry Andric   assert(!Record.MappingRegions.empty() && "Function has no regions");
2263ca95b02SDimitry Andric 
227*b5893f02SDimitry Andric   // This coverage record is a zero region for a function that's unused in
228*b5893f02SDimitry Andric   // some TU, but used in a different TU. Ignore it. The coverage maps from the
229*b5893f02SDimitry Andric   // the other TU will either be loaded (providing full region counts) or they
230*b5893f02SDimitry Andric   // won't (in which case we don't unintuitively report functions as uncovered
231*b5893f02SDimitry Andric   // when they have non-zero counts in the profile).
232*b5893f02SDimitry Andric   if (Record.MappingRegions.size() == 1 &&
233*b5893f02SDimitry Andric       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
234*b5893f02SDimitry Andric     return Error::success();
235*b5893f02SDimitry Andric 
2363ca95b02SDimitry Andric   FunctionRecord Function(OrigFuncName, Record.Filenames);
2373ca95b02SDimitry Andric   for (const auto &Region : Record.MappingRegions) {
2383ca95b02SDimitry Andric     Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
2393ca95b02SDimitry Andric     if (auto E = ExecutionCount.takeError()) {
2407a7e6055SDimitry Andric       consumeError(std::move(E));
241d88c1a5aSDimitry Andric       return Error::success();
2423ca95b02SDimitry Andric     }
2433ca95b02SDimitry Andric     Function.pushRegion(Region, *ExecutionCount);
2443ca95b02SDimitry Andric   }
245*b5893f02SDimitry Andric 
246*b5893f02SDimitry Andric   // Don't create records for (filenames, function) pairs we've already seen.
247*b5893f02SDimitry Andric   auto FilenamesHash = hash_combine_range(Record.Filenames.begin(),
248*b5893f02SDimitry Andric                                           Record.Filenames.end());
249*b5893f02SDimitry Andric   if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
250d88c1a5aSDimitry Andric     return Error::success();
2513ca95b02SDimitry Andric 
252d88c1a5aSDimitry Andric   Functions.push_back(std::move(Function));
253d88c1a5aSDimitry Andric   return Error::success();
2543ca95b02SDimitry Andric }
2553ca95b02SDimitry Andric 
load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,IndexedInstrProfReader & ProfileReader)256d88c1a5aSDimitry Andric Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
257d88c1a5aSDimitry Andric     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
258d88c1a5aSDimitry Andric     IndexedInstrProfReader &ProfileReader) {
259d88c1a5aSDimitry Andric   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
260d88c1a5aSDimitry Andric 
2612cab237bSDimitry Andric   for (const auto &CoverageReader : CoverageReaders) {
2622cab237bSDimitry Andric     for (auto RecordOrErr : *CoverageReader) {
2632cab237bSDimitry Andric       if (Error E = RecordOrErr.takeError())
2642cab237bSDimitry Andric         return std::move(E);
2652cab237bSDimitry Andric       const auto &Record = *RecordOrErr;
266d88c1a5aSDimitry Andric       if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
267d88c1a5aSDimitry Andric         return std::move(E);
2682cab237bSDimitry Andric     }
2692cab237bSDimitry Andric   }
270d88c1a5aSDimitry Andric 
2713ca95b02SDimitry Andric   return std::move(Coverage);
2723ca95b02SDimitry Andric }
2733ca95b02SDimitry Andric 
2743ca95b02SDimitry Andric Expected<std::unique_ptr<CoverageMapping>>
load(ArrayRef<StringRef> ObjectFilenames,StringRef ProfileFilename,ArrayRef<StringRef> Arches)275d88c1a5aSDimitry Andric CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
2762cab237bSDimitry Andric                       StringRef ProfileFilename, ArrayRef<StringRef> Arches) {
2773ca95b02SDimitry Andric   auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
2783ca95b02SDimitry Andric   if (Error E = ProfileReaderOrErr.takeError())
2793ca95b02SDimitry Andric     return std::move(E);
2803ca95b02SDimitry Andric   auto ProfileReader = std::move(ProfileReaderOrErr.get());
281d88c1a5aSDimitry Andric 
282d88c1a5aSDimitry Andric   SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers;
283d88c1a5aSDimitry Andric   SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
2842cab237bSDimitry Andric   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
2852cab237bSDimitry Andric     auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(File.value());
286d88c1a5aSDimitry Andric     if (std::error_code EC = CovMappingBufOrErr.getError())
287d88c1a5aSDimitry Andric       return errorCodeToError(EC);
2882cab237bSDimitry Andric     StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()];
289d88c1a5aSDimitry Andric     auto CoverageReaderOrErr =
290d88c1a5aSDimitry Andric         BinaryCoverageReader::create(CovMappingBufOrErr.get(), Arch);
291d88c1a5aSDimitry Andric     if (Error E = CoverageReaderOrErr.takeError())
292d88c1a5aSDimitry Andric       return std::move(E);
293d88c1a5aSDimitry Andric     Readers.push_back(std::move(CoverageReaderOrErr.get()));
294d88c1a5aSDimitry Andric     Buffers.push_back(std::move(CovMappingBufOrErr.get()));
295d88c1a5aSDimitry Andric   }
296d88c1a5aSDimitry Andric   return load(Readers, *ProfileReader);
2973ca95b02SDimitry Andric }
2983ca95b02SDimitry Andric 
2993ca95b02SDimitry Andric namespace {
3007a7e6055SDimitry Andric 
3014ba319b5SDimitry Andric /// Distributes functions into instantiation sets.
3023ca95b02SDimitry Andric ///
3033ca95b02SDimitry Andric /// An instantiation set is a collection of functions that have the same source
3043ca95b02SDimitry Andric /// code, ie, template functions specializations.
3053ca95b02SDimitry Andric class FunctionInstantiationSetCollector {
3062cab237bSDimitry Andric   using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
3073ca95b02SDimitry Andric   MapT InstantiatedFunctions;
3083ca95b02SDimitry Andric 
3093ca95b02SDimitry Andric public:
insert(const FunctionRecord & Function,unsigned FileID)3103ca95b02SDimitry Andric   void insert(const FunctionRecord &Function, unsigned FileID) {
3113ca95b02SDimitry Andric     auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
3123ca95b02SDimitry Andric     while (I != E && I->FileID != FileID)
3133ca95b02SDimitry Andric       ++I;
3143ca95b02SDimitry Andric     assert(I != E && "function does not cover the given file");
3153ca95b02SDimitry Andric     auto &Functions = InstantiatedFunctions[I->startLoc()];
3163ca95b02SDimitry Andric     Functions.push_back(&Function);
3173ca95b02SDimitry Andric   }
3183ca95b02SDimitry Andric 
begin()3193ca95b02SDimitry Andric   MapT::iterator begin() { return InstantiatedFunctions.begin(); }
end()3203ca95b02SDimitry Andric   MapT::iterator end() { return InstantiatedFunctions.end(); }
3213ca95b02SDimitry Andric };
3223ca95b02SDimitry Andric 
3233ca95b02SDimitry Andric class SegmentBuilder {
3243ca95b02SDimitry Andric   std::vector<CoverageSegment> &Segments;
3253ca95b02SDimitry Andric   SmallVector<const CountedRegion *, 8> ActiveRegions;
3263ca95b02SDimitry Andric 
SegmentBuilder(std::vector<CoverageSegment> & Segments)3273ca95b02SDimitry Andric   SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
3283ca95b02SDimitry Andric 
3292cab237bSDimitry Andric   /// Emit a segment with the count from \p Region starting at \p StartLoc.
3302cab237bSDimitry Andric   //
3312cab237bSDimitry Andric   /// \p IsRegionEntry: The segment is at the start of a new non-gap region.
3322cab237bSDimitry Andric   /// \p EmitSkippedRegion: The segment must be emitted as a skipped region.
startSegment(const CountedRegion & Region,LineColPair StartLoc,bool IsRegionEntry,bool EmitSkippedRegion=false)3332cab237bSDimitry Andric   void startSegment(const CountedRegion &Region, LineColPair StartLoc,
3342cab237bSDimitry Andric                     bool IsRegionEntry, bool EmitSkippedRegion = false) {
3352cab237bSDimitry Andric     bool HasCount = !EmitSkippedRegion &&
3362cab237bSDimitry Andric                     (Region.Kind != CounterMappingRegion::SkippedRegion);
3372cab237bSDimitry Andric 
3382cab237bSDimitry Andric     // If the new segment wouldn't affect coverage rendering, skip it.
3392cab237bSDimitry Andric     if (!Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
3402cab237bSDimitry Andric       const auto &Last = Segments.back();
3412cab237bSDimitry Andric       if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount &&
3422cab237bSDimitry Andric           !Last.IsRegionEntry)
3432cab237bSDimitry Andric         return;
3443ca95b02SDimitry Andric     }
3453ca95b02SDimitry Andric 
3462cab237bSDimitry Andric     if (HasCount)
3472cab237bSDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second,
3482cab237bSDimitry Andric                             Region.ExecutionCount, IsRegionEntry,
3492cab237bSDimitry Andric                             Region.Kind == CounterMappingRegion::GapRegion);
3503ca95b02SDimitry Andric     else
3512cab237bSDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
3522cab237bSDimitry Andric 
3534ba319b5SDimitry Andric     LLVM_DEBUG({
3542cab237bSDimitry Andric       const auto &Last = Segments.back();
3552cab237bSDimitry Andric       dbgs() << "Segment at " << Last.Line << ":" << Last.Col
3562cab237bSDimitry Andric              << " (count = " << Last.Count << ")"
3572cab237bSDimitry Andric              << (Last.IsRegionEntry ? ", RegionEntry" : "")
3582cab237bSDimitry Andric              << (!Last.HasCount ? ", Skipped" : "")
3592cab237bSDimitry Andric              << (Last.IsGapRegion ? ", Gap" : "") << "\n";
3602cab237bSDimitry Andric     });
3612cab237bSDimitry Andric   }
3622cab237bSDimitry Andric 
3632cab237bSDimitry Andric   /// Emit segments for active regions which end before \p Loc.
3642cab237bSDimitry Andric   ///
3652cab237bSDimitry Andric   /// \p Loc: The start location of the next region. If None, all active
3662cab237bSDimitry Andric   /// regions are completed.
3672cab237bSDimitry Andric   /// \p FirstCompletedRegion: Index of the first completed region.
completeRegionsUntil(Optional<LineColPair> Loc,unsigned FirstCompletedRegion)3682cab237bSDimitry Andric   void completeRegionsUntil(Optional<LineColPair> Loc,
3692cab237bSDimitry Andric                             unsigned FirstCompletedRegion) {
3702cab237bSDimitry Andric     // Sort the completed regions by end location. This makes it simple to
3712cab237bSDimitry Andric     // emit closing segments in sorted order.
3722cab237bSDimitry Andric     auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;
3732cab237bSDimitry Andric     std::stable_sort(CompletedRegionsIt, ActiveRegions.end(),
3742cab237bSDimitry Andric                       [](const CountedRegion *L, const CountedRegion *R) {
3752cab237bSDimitry Andric                         return L->endLoc() < R->endLoc();
3762cab237bSDimitry Andric                       });
3772cab237bSDimitry Andric 
3782cab237bSDimitry Andric     // Emit segments for all completed regions.
3792cab237bSDimitry Andric     for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E;
3802cab237bSDimitry Andric          ++I) {
3812cab237bSDimitry Andric       const auto *CompletedRegion = ActiveRegions[I];
3822cab237bSDimitry Andric       assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
3832cab237bSDimitry Andric              "Completed region ends after start of new region");
3842cab237bSDimitry Andric 
3852cab237bSDimitry Andric       const auto *PrevCompletedRegion = ActiveRegions[I - 1];
3862cab237bSDimitry Andric       auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
3872cab237bSDimitry Andric 
3882cab237bSDimitry Andric       // Don't emit any more segments if they start where the new region begins.
3892cab237bSDimitry Andric       if (Loc && CompletedSegmentLoc == *Loc)
3902cab237bSDimitry Andric         break;
3912cab237bSDimitry Andric 
3922cab237bSDimitry Andric       // Don't emit a segment if the next completed region ends at the same
3932cab237bSDimitry Andric       // location as this one.
3942cab237bSDimitry Andric       if (CompletedSegmentLoc == CompletedRegion->endLoc())
3952cab237bSDimitry Andric         continue;
3962cab237bSDimitry Andric 
3972cab237bSDimitry Andric       // Use the count from the last completed region which ends at this loc.
3982cab237bSDimitry Andric       for (unsigned J = I + 1; J < E; ++J)
3992cab237bSDimitry Andric         if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
4002cab237bSDimitry Andric           CompletedRegion = ActiveRegions[J];
4012cab237bSDimitry Andric 
4022cab237bSDimitry Andric       startSegment(*CompletedRegion, CompletedSegmentLoc, false);
4032cab237bSDimitry Andric     }
4042cab237bSDimitry Andric 
4052cab237bSDimitry Andric     auto Last = ActiveRegions.back();
4062cab237bSDimitry Andric     if (FirstCompletedRegion && Last->endLoc() != *Loc) {
4072cab237bSDimitry Andric       // If there's a gap after the end of the last completed region and the
4082cab237bSDimitry Andric       // start of the new region, use the last active region to fill the gap.
4092cab237bSDimitry Andric       startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(),
4102cab237bSDimitry Andric                    false);
4112cab237bSDimitry Andric     } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) {
4122cab237bSDimitry Andric       // Emit a skipped segment if there are no more active regions. This
4132cab237bSDimitry Andric       // ensures that gaps between functions are marked correctly.
4142cab237bSDimitry Andric       startSegment(*Last, Last->endLoc(), false, true);
4152cab237bSDimitry Andric     }
4162cab237bSDimitry Andric 
4172cab237bSDimitry Andric     // Pop the completed regions.
4182cab237bSDimitry Andric     ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end());
4193ca95b02SDimitry Andric   }
4203ca95b02SDimitry Andric 
buildSegmentsImpl(ArrayRef<CountedRegion> Regions)4213ca95b02SDimitry Andric   void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
4222cab237bSDimitry Andric     for (const auto &CR : enumerate(Regions)) {
4232cab237bSDimitry Andric       auto CurStartLoc = CR.value().startLoc();
4242cab237bSDimitry Andric 
4252cab237bSDimitry Andric       // Active regions which end before the current region need to be popped.
4262cab237bSDimitry Andric       auto CompletedRegions =
4272cab237bSDimitry Andric           std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),
4282cab237bSDimitry Andric                                 [&](const CountedRegion *Region) {
4292cab237bSDimitry Andric                                   return !(Region->endLoc() <= CurStartLoc);
4302cab237bSDimitry Andric                                 });
4312cab237bSDimitry Andric       if (CompletedRegions != ActiveRegions.end()) {
4322cab237bSDimitry Andric         unsigned FirstCompletedRegion =
4332cab237bSDimitry Andric             std::distance(ActiveRegions.begin(), CompletedRegions);
4342cab237bSDimitry Andric         completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
4353ca95b02SDimitry Andric       }
4362cab237bSDimitry Andric 
4372cab237bSDimitry Andric       bool GapRegion = CR.value().Kind == CounterMappingRegion::GapRegion;
4382cab237bSDimitry Andric 
4392cab237bSDimitry Andric       // Try to emit a segment for the current region.
4402cab237bSDimitry Andric       if (CurStartLoc == CR.value().endLoc()) {
4412cab237bSDimitry Andric         // Avoid making zero-length regions active. If it's the last region,
4422cab237bSDimitry Andric         // emit a skipped segment. Otherwise use its predecessor's count.
4432cab237bSDimitry Andric         const bool Skipped = (CR.index() + 1) == Regions.size();
4442cab237bSDimitry Andric         startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),
4452cab237bSDimitry Andric                      CurStartLoc, !GapRegion, Skipped);
4462cab237bSDimitry Andric         continue;
4472cab237bSDimitry Andric       }
4482cab237bSDimitry Andric       if (CR.index() + 1 == Regions.size() ||
4492cab237bSDimitry Andric           CurStartLoc != Regions[CR.index() + 1].startLoc()) {
4502cab237bSDimitry Andric         // Emit a segment if the next region doesn't start at the same location
4512cab237bSDimitry Andric         // as this one.
4522cab237bSDimitry Andric         startSegment(CR.value(), CurStartLoc, !GapRegion);
4532cab237bSDimitry Andric       }
4542cab237bSDimitry Andric 
4552cab237bSDimitry Andric       // This region is active (i.e not completed).
4562cab237bSDimitry Andric       ActiveRegions.push_back(&CR.value());
4572cab237bSDimitry Andric     }
4582cab237bSDimitry Andric 
4592cab237bSDimitry Andric     // Complete any remaining active regions.
4602cab237bSDimitry Andric     if (!ActiveRegions.empty())
4612cab237bSDimitry Andric       completeRegionsUntil(None, 0);
4623ca95b02SDimitry Andric   }
4633ca95b02SDimitry Andric 
4643ca95b02SDimitry Andric   /// Sort a nested sequence of regions from a single file.
sortNestedRegions(MutableArrayRef<CountedRegion> Regions)4653ca95b02SDimitry Andric   static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
466*b5893f02SDimitry Andric     llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) {
4673ca95b02SDimitry Andric       if (LHS.startLoc() != RHS.startLoc())
4683ca95b02SDimitry Andric         return LHS.startLoc() < RHS.startLoc();
4693ca95b02SDimitry Andric       if (LHS.endLoc() != RHS.endLoc())
4703ca95b02SDimitry Andric         // When LHS completely contains RHS, we sort LHS first.
4713ca95b02SDimitry Andric         return RHS.endLoc() < LHS.endLoc();
4723ca95b02SDimitry Andric       // If LHS and RHS cover the same area, we need to sort them according
4733ca95b02SDimitry Andric       // to their kinds so that the most suitable region will become "active"
4743ca95b02SDimitry Andric       // in combineRegions(). Because we accumulate counter values only from
4753ca95b02SDimitry Andric       // regions of the same kind as the first region of the area, prefer
4763ca95b02SDimitry Andric       // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
4777a7e6055SDimitry Andric       static_assert(CounterMappingRegion::CodeRegion <
4787a7e6055SDimitry Andric                             CounterMappingRegion::ExpansionRegion &&
4797a7e6055SDimitry Andric                         CounterMappingRegion::ExpansionRegion <
4807a7e6055SDimitry Andric                             CounterMappingRegion::SkippedRegion,
4813ca95b02SDimitry Andric                     "Unexpected order of region kind values");
4823ca95b02SDimitry Andric       return LHS.Kind < RHS.Kind;
4833ca95b02SDimitry Andric     });
4843ca95b02SDimitry Andric   }
4853ca95b02SDimitry Andric 
4863ca95b02SDimitry Andric   /// Combine counts of regions which cover the same area.
4873ca95b02SDimitry Andric   static ArrayRef<CountedRegion>
combineRegions(MutableArrayRef<CountedRegion> Regions)4883ca95b02SDimitry Andric   combineRegions(MutableArrayRef<CountedRegion> Regions) {
4893ca95b02SDimitry Andric     if (Regions.empty())
4903ca95b02SDimitry Andric       return Regions;
4913ca95b02SDimitry Andric     auto Active = Regions.begin();
4923ca95b02SDimitry Andric     auto End = Regions.end();
4933ca95b02SDimitry Andric     for (auto I = Regions.begin() + 1; I != End; ++I) {
4943ca95b02SDimitry Andric       if (Active->startLoc() != I->startLoc() ||
4953ca95b02SDimitry Andric           Active->endLoc() != I->endLoc()) {
4963ca95b02SDimitry Andric         // Shift to the next region.
4973ca95b02SDimitry Andric         ++Active;
4983ca95b02SDimitry Andric         if (Active != I)
4993ca95b02SDimitry Andric           *Active = *I;
5003ca95b02SDimitry Andric         continue;
5013ca95b02SDimitry Andric       }
5023ca95b02SDimitry Andric       // Merge duplicate region.
5033ca95b02SDimitry Andric       // If CodeRegions and ExpansionRegions cover the same area, it's probably
5043ca95b02SDimitry Andric       // a macro which is fully expanded to another macro. In that case, we need
5053ca95b02SDimitry Andric       // to accumulate counts only from CodeRegions, or else the area will be
5063ca95b02SDimitry Andric       // counted twice.
5073ca95b02SDimitry Andric       // On the other hand, a macro may have a nested macro in its body. If the
5083ca95b02SDimitry Andric       // outer macro is used several times, the ExpansionRegion for the nested
5093ca95b02SDimitry Andric       // macro will also be added several times. These ExpansionRegions cover
5103ca95b02SDimitry Andric       // the same source locations and have to be combined to reach the correct
5113ca95b02SDimitry Andric       // value for that area.
5123ca95b02SDimitry Andric       // We add counts of the regions of the same kind as the active region
5133ca95b02SDimitry Andric       // to handle the both situations.
5143ca95b02SDimitry Andric       if (I->Kind == Active->Kind)
5153ca95b02SDimitry Andric         Active->ExecutionCount += I->ExecutionCount;
5163ca95b02SDimitry Andric     }
5173ca95b02SDimitry Andric     return Regions.drop_back(std::distance(++Active, End));
5183ca95b02SDimitry Andric   }
5193ca95b02SDimitry Andric 
5203ca95b02SDimitry Andric public:
5212cab237bSDimitry Andric   /// Build a sorted list of CoverageSegments from a list of Regions.
5223ca95b02SDimitry Andric   static std::vector<CoverageSegment>
buildSegments(MutableArrayRef<CountedRegion> Regions)5233ca95b02SDimitry Andric   buildSegments(MutableArrayRef<CountedRegion> Regions) {
5243ca95b02SDimitry Andric     std::vector<CoverageSegment> Segments;
5253ca95b02SDimitry Andric     SegmentBuilder Builder(Segments);
5263ca95b02SDimitry Andric 
5273ca95b02SDimitry Andric     sortNestedRegions(Regions);
5283ca95b02SDimitry Andric     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
5293ca95b02SDimitry Andric 
5304ba319b5SDimitry Andric     LLVM_DEBUG({
5312cab237bSDimitry Andric       dbgs() << "Combined regions:\n";
5322cab237bSDimitry Andric       for (const auto &CR : CombinedRegions)
5332cab237bSDimitry Andric         dbgs() << "  " << CR.LineStart << ":" << CR.ColumnStart << " -> "
5342cab237bSDimitry Andric                << CR.LineEnd << ":" << CR.ColumnEnd
5352cab237bSDimitry Andric                << " (count=" << CR.ExecutionCount << ")\n";
5362cab237bSDimitry Andric     });
5372cab237bSDimitry Andric 
5383ca95b02SDimitry Andric     Builder.buildSegmentsImpl(CombinedRegions);
5392cab237bSDimitry Andric 
5402cab237bSDimitry Andric #ifndef NDEBUG
5412cab237bSDimitry Andric     for (unsigned I = 1, E = Segments.size(); I < E; ++I) {
5422cab237bSDimitry Andric       const auto &L = Segments[I - 1];
5432cab237bSDimitry Andric       const auto &R = Segments[I];
5442cab237bSDimitry Andric       if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) {
5454ba319b5SDimitry Andric         LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col
5462cab237bSDimitry Andric                           << " followed by " << R.Line << ":" << R.Col << "\n");
5472cab237bSDimitry Andric         assert(false && "Coverage segments not unique or sorted");
5482cab237bSDimitry Andric       }
5492cab237bSDimitry Andric     }
5502cab237bSDimitry Andric #endif
5512cab237bSDimitry Andric 
5523ca95b02SDimitry Andric     return Segments;
5533ca95b02SDimitry Andric   }
5543ca95b02SDimitry Andric };
5557a7e6055SDimitry Andric 
5567a7e6055SDimitry Andric } // end anonymous namespace
5573ca95b02SDimitry Andric 
getUniqueSourceFiles() const5583ca95b02SDimitry Andric std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
5593ca95b02SDimitry Andric   std::vector<StringRef> Filenames;
5603ca95b02SDimitry Andric   for (const auto &Function : getCoveredFunctions())
5613ca95b02SDimitry Andric     Filenames.insert(Filenames.end(), Function.Filenames.begin(),
5623ca95b02SDimitry Andric                      Function.Filenames.end());
563*b5893f02SDimitry Andric   llvm::sort(Filenames);
5643ca95b02SDimitry Andric   auto Last = std::unique(Filenames.begin(), Filenames.end());
5653ca95b02SDimitry Andric   Filenames.erase(Last, Filenames.end());
5663ca95b02SDimitry Andric   return Filenames;
5673ca95b02SDimitry Andric }
5683ca95b02SDimitry Andric 
gatherFileIDs(StringRef SourceFile,const FunctionRecord & Function)5693ca95b02SDimitry Andric static SmallBitVector gatherFileIDs(StringRef SourceFile,
5703ca95b02SDimitry Andric                                     const FunctionRecord &Function) {
5713ca95b02SDimitry Andric   SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
5723ca95b02SDimitry Andric   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
5733ca95b02SDimitry Andric     if (SourceFile == Function.Filenames[I])
5743ca95b02SDimitry Andric       FilenameEquivalence[I] = true;
5753ca95b02SDimitry Andric   return FilenameEquivalence;
5763ca95b02SDimitry Andric }
5773ca95b02SDimitry Andric 
5783ca95b02SDimitry Andric /// Return the ID of the file where the definition of the function is located.
findMainViewFileID(const FunctionRecord & Function)5793ca95b02SDimitry Andric static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
5803ca95b02SDimitry Andric   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
5813ca95b02SDimitry Andric   for (const auto &CR : Function.CountedRegions)
5823ca95b02SDimitry Andric     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
5833ca95b02SDimitry Andric       IsNotExpandedFile[CR.ExpandedFileID] = false;
5843ca95b02SDimitry Andric   int I = IsNotExpandedFile.find_first();
5853ca95b02SDimitry Andric   if (I == -1)
5863ca95b02SDimitry Andric     return None;
5873ca95b02SDimitry Andric   return I;
5883ca95b02SDimitry Andric }
5893ca95b02SDimitry Andric 
5903ca95b02SDimitry Andric /// Check if SourceFile is the file that contains the definition of
5913ca95b02SDimitry Andric /// the Function. Return the ID of the file in that case or None otherwise.
findMainViewFileID(StringRef SourceFile,const FunctionRecord & Function)5923ca95b02SDimitry Andric static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
5933ca95b02SDimitry Andric                                              const FunctionRecord &Function) {
5943ca95b02SDimitry Andric   Optional<unsigned> I = findMainViewFileID(Function);
5953ca95b02SDimitry Andric   if (I && SourceFile == Function.Filenames[*I])
5963ca95b02SDimitry Andric     return I;
5973ca95b02SDimitry Andric   return None;
5983ca95b02SDimitry Andric }
5993ca95b02SDimitry Andric 
isExpansion(const CountedRegion & R,unsigned FileID)6003ca95b02SDimitry Andric static bool isExpansion(const CountedRegion &R, unsigned FileID) {
6013ca95b02SDimitry Andric   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
6023ca95b02SDimitry Andric }
6033ca95b02SDimitry Andric 
getCoverageForFile(StringRef Filename) const6043ca95b02SDimitry Andric CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
6053ca95b02SDimitry Andric   CoverageData FileCoverage(Filename);
6067a7e6055SDimitry Andric   std::vector<CountedRegion> Regions;
6073ca95b02SDimitry Andric 
6083ca95b02SDimitry Andric   for (const auto &Function : Functions) {
6093ca95b02SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
6103ca95b02SDimitry Andric     auto FileIDs = gatherFileIDs(Filename, Function);
6113ca95b02SDimitry Andric     for (const auto &CR : Function.CountedRegions)
6123ca95b02SDimitry Andric       if (FileIDs.test(CR.FileID)) {
6133ca95b02SDimitry Andric         Regions.push_back(CR);
6143ca95b02SDimitry Andric         if (MainFileID && isExpansion(CR, *MainFileID))
6153ca95b02SDimitry Andric           FileCoverage.Expansions.emplace_back(CR, Function);
6163ca95b02SDimitry Andric       }
6173ca95b02SDimitry Andric   }
6183ca95b02SDimitry Andric 
6194ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
6203ca95b02SDimitry Andric   FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
6213ca95b02SDimitry Andric 
6223ca95b02SDimitry Andric   return FileCoverage;
6233ca95b02SDimitry Andric }
6243ca95b02SDimitry Andric 
6252cab237bSDimitry Andric std::vector<InstantiationGroup>
getInstantiationGroups(StringRef Filename) const6262cab237bSDimitry Andric CoverageMapping::getInstantiationGroups(StringRef Filename) const {
6273ca95b02SDimitry Andric   FunctionInstantiationSetCollector InstantiationSetCollector;
6283ca95b02SDimitry Andric   for (const auto &Function : Functions) {
6293ca95b02SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
6303ca95b02SDimitry Andric     if (!MainFileID)
6313ca95b02SDimitry Andric       continue;
6323ca95b02SDimitry Andric     InstantiationSetCollector.insert(Function, *MainFileID);
6333ca95b02SDimitry Andric   }
6343ca95b02SDimitry Andric 
6352cab237bSDimitry Andric   std::vector<InstantiationGroup> Result;
636fe4fed2eSDimitry Andric   for (auto &InstantiationSet : InstantiationSetCollector) {
6372cab237bSDimitry Andric     InstantiationGroup IG{InstantiationSet.first.first,
6382cab237bSDimitry Andric                           InstantiationSet.first.second,
6392cab237bSDimitry Andric                           std::move(InstantiationSet.second)};
6402cab237bSDimitry Andric     Result.emplace_back(std::move(IG));
6413ca95b02SDimitry Andric   }
6423ca95b02SDimitry Andric   return Result;
6433ca95b02SDimitry Andric }
6443ca95b02SDimitry Andric 
6453ca95b02SDimitry Andric CoverageData
getCoverageForFunction(const FunctionRecord & Function) const6463ca95b02SDimitry Andric CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
6473ca95b02SDimitry Andric   auto MainFileID = findMainViewFileID(Function);
6483ca95b02SDimitry Andric   if (!MainFileID)
6493ca95b02SDimitry Andric     return CoverageData();
6503ca95b02SDimitry Andric 
6513ca95b02SDimitry Andric   CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
6527a7e6055SDimitry Andric   std::vector<CountedRegion> Regions;
6533ca95b02SDimitry Andric   for (const auto &CR : Function.CountedRegions)
6543ca95b02SDimitry Andric     if (CR.FileID == *MainFileID) {
6553ca95b02SDimitry Andric       Regions.push_back(CR);
6563ca95b02SDimitry Andric       if (isExpansion(CR, *MainFileID))
6573ca95b02SDimitry Andric         FunctionCoverage.Expansions.emplace_back(CR, Function);
6583ca95b02SDimitry Andric     }
6593ca95b02SDimitry Andric 
6604ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
6614ba319b5SDimitry Andric                     << "\n");
6623ca95b02SDimitry Andric   FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
6633ca95b02SDimitry Andric 
6643ca95b02SDimitry Andric   return FunctionCoverage;
6653ca95b02SDimitry Andric }
6663ca95b02SDimitry Andric 
getCoverageForExpansion(const ExpansionRecord & Expansion) const6673ca95b02SDimitry Andric CoverageData CoverageMapping::getCoverageForExpansion(
6683ca95b02SDimitry Andric     const ExpansionRecord &Expansion) const {
6693ca95b02SDimitry Andric   CoverageData ExpansionCoverage(
6703ca95b02SDimitry Andric       Expansion.Function.Filenames[Expansion.FileID]);
6717a7e6055SDimitry Andric   std::vector<CountedRegion> Regions;
6723ca95b02SDimitry Andric   for (const auto &CR : Expansion.Function.CountedRegions)
6733ca95b02SDimitry Andric     if (CR.FileID == Expansion.FileID) {
6743ca95b02SDimitry Andric       Regions.push_back(CR);
6753ca95b02SDimitry Andric       if (isExpansion(CR, Expansion.FileID))
6763ca95b02SDimitry Andric         ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
6773ca95b02SDimitry Andric     }
6783ca95b02SDimitry Andric 
6794ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
6804ba319b5SDimitry Andric                     << Expansion.FileID << "\n");
6813ca95b02SDimitry Andric   ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
6823ca95b02SDimitry Andric 
6833ca95b02SDimitry Andric   return ExpansionCoverage;
6843ca95b02SDimitry Andric }
6853ca95b02SDimitry Andric 
LineCoverageStats(ArrayRef<const CoverageSegment * > LineSegments,const CoverageSegment * WrappedSegment,unsigned Line)6862cab237bSDimitry Andric LineCoverageStats::LineCoverageStats(
6872cab237bSDimitry Andric     ArrayRef<const CoverageSegment *> LineSegments,
6882cab237bSDimitry Andric     const CoverageSegment *WrappedSegment, unsigned Line)
6892cab237bSDimitry Andric     : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
6902cab237bSDimitry Andric       LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
6912cab237bSDimitry Andric   // Find the minimum number of regions which start in this line.
6922cab237bSDimitry Andric   unsigned MinRegionCount = 0;
6932cab237bSDimitry Andric   auto isStartOfRegion = [](const CoverageSegment *S) {
6942cab237bSDimitry Andric     return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
6952cab237bSDimitry Andric   };
6962cab237bSDimitry Andric   for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
6972cab237bSDimitry Andric     if (isStartOfRegion(LineSegments[I]))
6982cab237bSDimitry Andric       ++MinRegionCount;
6992cab237bSDimitry Andric 
7002cab237bSDimitry Andric   bool StartOfSkippedRegion = !LineSegments.empty() &&
7012cab237bSDimitry Andric                               !LineSegments.front()->HasCount &&
7022cab237bSDimitry Andric                               LineSegments.front()->IsRegionEntry;
7032cab237bSDimitry Andric 
7042cab237bSDimitry Andric   HasMultipleRegions = MinRegionCount > 1;
7052cab237bSDimitry Andric   Mapped =
7062cab237bSDimitry Andric       !StartOfSkippedRegion &&
7072cab237bSDimitry Andric       ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
7082cab237bSDimitry Andric 
7092cab237bSDimitry Andric   if (!Mapped)
7102cab237bSDimitry Andric     return;
7112cab237bSDimitry Andric 
7122cab237bSDimitry Andric   // Pick the max count from the non-gap, region entry segments and the
7132cab237bSDimitry Andric   // wrapped count.
7142cab237bSDimitry Andric   if (WrappedSegment)
7152cab237bSDimitry Andric     ExecutionCount = WrappedSegment->Count;
7162cab237bSDimitry Andric   if (!MinRegionCount)
7172cab237bSDimitry Andric     return;
7182cab237bSDimitry Andric   for (const auto *LS : LineSegments)
7192cab237bSDimitry Andric     if (isStartOfRegion(LS))
7202cab237bSDimitry Andric       ExecutionCount = std::max(ExecutionCount, LS->Count);
7212cab237bSDimitry Andric }
7222cab237bSDimitry Andric 
operator ++()7232cab237bSDimitry Andric LineCoverageIterator &LineCoverageIterator::operator++() {
7242cab237bSDimitry Andric   if (Next == CD.end()) {
7252cab237bSDimitry Andric     Stats = LineCoverageStats();
7262cab237bSDimitry Andric     Ended = true;
7272cab237bSDimitry Andric     return *this;
7282cab237bSDimitry Andric   }
7292cab237bSDimitry Andric   if (Segments.size())
7302cab237bSDimitry Andric     WrappedSegment = Segments.back();
7312cab237bSDimitry Andric   Segments.clear();
7322cab237bSDimitry Andric   while (Next != CD.end() && Next->Line == Line)
7332cab237bSDimitry Andric     Segments.push_back(&*Next++);
7342cab237bSDimitry Andric   Stats = LineCoverageStats(Segments, WrappedSegment, Line);
7352cab237bSDimitry Andric   ++Line;
7362cab237bSDimitry Andric   return *this;
7372cab237bSDimitry Andric }
7382cab237bSDimitry Andric 
getCoverageMapErrString(coveragemap_error Err)7397a7e6055SDimitry Andric static std::string getCoverageMapErrString(coveragemap_error Err) {
7403ca95b02SDimitry Andric   switch (Err) {
7413ca95b02SDimitry Andric   case coveragemap_error::success:
7423ca95b02SDimitry Andric     return "Success";
7433ca95b02SDimitry Andric   case coveragemap_error::eof:
7443ca95b02SDimitry Andric     return "End of File";
7453ca95b02SDimitry Andric   case coveragemap_error::no_data_found:
7463ca95b02SDimitry Andric     return "No coverage data found";
7473ca95b02SDimitry Andric   case coveragemap_error::unsupported_version:
7483ca95b02SDimitry Andric     return "Unsupported coverage format version";
7493ca95b02SDimitry Andric   case coveragemap_error::truncated:
7503ca95b02SDimitry Andric     return "Truncated coverage data";
7513ca95b02SDimitry Andric   case coveragemap_error::malformed:
7523ca95b02SDimitry Andric     return "Malformed coverage data";
7533ca95b02SDimitry Andric   }
7543ca95b02SDimitry Andric   llvm_unreachable("A value of coveragemap_error has no message.");
7553ca95b02SDimitry Andric }
7563ca95b02SDimitry Andric 
7577a7e6055SDimitry Andric namespace {
7587a7e6055SDimitry Andric 
7593ca95b02SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It
7603ca95b02SDimitry Andric // will be removed once this transition is complete. Clients should prefer to
7613ca95b02SDimitry Andric // deal with the Error value directly, rather than converting to error_code.
7623ca95b02SDimitry Andric class CoverageMappingErrorCategoryType : public std::error_category {
name() const763d88c1a5aSDimitry Andric   const char *name() const noexcept override { return "llvm.coveragemap"; }
message(int IE) const7643ca95b02SDimitry Andric   std::string message(int IE) const override {
7653ca95b02SDimitry Andric     return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
7663ca95b02SDimitry Andric   }
7673ca95b02SDimitry Andric };
7687a7e6055SDimitry Andric 
7693ca95b02SDimitry Andric } // end anonymous namespace
7703ca95b02SDimitry Andric 
message() const7713ca95b02SDimitry Andric std::string CoverageMapError::message() const {
7723ca95b02SDimitry Andric   return getCoverageMapErrString(Err);
7733ca95b02SDimitry Andric }
7743ca95b02SDimitry Andric 
7753ca95b02SDimitry Andric static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
7763ca95b02SDimitry Andric 
coveragemap_category()7773ca95b02SDimitry Andric const std::error_category &llvm::coverage::coveragemap_category() {
7783ca95b02SDimitry Andric   return *ErrorCategory;
7793ca95b02SDimitry Andric }
7803ca95b02SDimitry Andric 
7813ca95b02SDimitry Andric char CoverageMapError::ID = 0;
782