xref: /freebsd/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===- CoverageMapping.cpp - Code coverage mapping support ----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains support for clang's and llvm's instrumentation based
100b57cec5SDimitry Andric // code coverage.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMapping.h"
150b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
160b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
170b57cec5SDimitry Andric #include "llvm/ADT/None.h"
180b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallBitVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
220b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
230b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
240b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
250b57cec5SDimitry Andric #include "llvm/Support/Errc.h"
260b57cec5SDimitry Andric #include "llvm/Support/Error.h"
270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
280b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h"
290b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
310b57cec5SDimitry Andric #include <algorithm>
320b57cec5SDimitry Andric #include <cassert>
330b57cec5SDimitry Andric #include <cstdint>
340b57cec5SDimitry Andric #include <iterator>
350b57cec5SDimitry Andric #include <map>
360b57cec5SDimitry Andric #include <memory>
370b57cec5SDimitry Andric #include <string>
380b57cec5SDimitry Andric #include <system_error>
390b57cec5SDimitry Andric #include <utility>
400b57cec5SDimitry Andric #include <vector>
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric using namespace llvm;
430b57cec5SDimitry Andric using namespace coverage;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric #define DEBUG_TYPE "coverage-mapping"
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric Counter CounterExpressionBuilder::get(const CounterExpression &E) {
480b57cec5SDimitry Andric   auto It = ExpressionIndices.find(E);
490b57cec5SDimitry Andric   if (It != ExpressionIndices.end())
500b57cec5SDimitry Andric     return Counter::getExpression(It->second);
510b57cec5SDimitry Andric   unsigned I = Expressions.size();
520b57cec5SDimitry Andric   Expressions.push_back(E);
530b57cec5SDimitry Andric   ExpressionIndices[E] = I;
540b57cec5SDimitry Andric   return Counter::getExpression(I);
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric void CounterExpressionBuilder::extractTerms(Counter C, int Factor,
580b57cec5SDimitry Andric                                             SmallVectorImpl<Term> &Terms) {
590b57cec5SDimitry Andric   switch (C.getKind()) {
600b57cec5SDimitry Andric   case Counter::Zero:
610b57cec5SDimitry Andric     break;
620b57cec5SDimitry Andric   case Counter::CounterValueReference:
630b57cec5SDimitry Andric     Terms.emplace_back(C.getCounterID(), Factor);
640b57cec5SDimitry Andric     break;
650b57cec5SDimitry Andric   case Counter::Expression:
660b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
670b57cec5SDimitry Andric     extractTerms(E.LHS, Factor, Terms);
680b57cec5SDimitry Andric     extractTerms(
690b57cec5SDimitry Andric         E.RHS, E.Kind == CounterExpression::Subtract ? -Factor : Factor, Terms);
700b57cec5SDimitry Andric     break;
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
750b57cec5SDimitry Andric   // Gather constant terms.
760b57cec5SDimitry Andric   SmallVector<Term, 32> Terms;
770b57cec5SDimitry Andric   extractTerms(ExpressionTree, +1, Terms);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   // If there are no terms, this is just a zero. The algorithm below assumes at
800b57cec5SDimitry Andric   // least one term.
810b57cec5SDimitry Andric   if (Terms.size() == 0)
820b57cec5SDimitry Andric     return Counter::getZero();
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   // Group the terms by counter ID.
850b57cec5SDimitry Andric   llvm::sort(Terms, [](const Term &LHS, const Term &RHS) {
860b57cec5SDimitry Andric     return LHS.CounterID < RHS.CounterID;
870b57cec5SDimitry Andric   });
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   // Combine terms by counter ID to eliminate counters that sum to zero.
900b57cec5SDimitry Andric   auto Prev = Terms.begin();
910b57cec5SDimitry Andric   for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
920b57cec5SDimitry Andric     if (I->CounterID == Prev->CounterID) {
930b57cec5SDimitry Andric       Prev->Factor += I->Factor;
940b57cec5SDimitry Andric       continue;
950b57cec5SDimitry Andric     }
960b57cec5SDimitry Andric     ++Prev;
970b57cec5SDimitry Andric     *Prev = *I;
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric   Terms.erase(++Prev, Terms.end());
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   Counter C;
1020b57cec5SDimitry Andric   // Create additions. We do this before subtractions to avoid constructs like
1030b57cec5SDimitry Andric   // ((0 - X) + Y), as opposed to (Y - X).
1040b57cec5SDimitry Andric   for (auto T : Terms) {
1050b57cec5SDimitry Andric     if (T.Factor <= 0)
1060b57cec5SDimitry Andric       continue;
1070b57cec5SDimitry Andric     for (int I = 0; I < T.Factor; ++I)
1080b57cec5SDimitry Andric       if (C.isZero())
1090b57cec5SDimitry Andric         C = Counter::getCounter(T.CounterID);
1100b57cec5SDimitry Andric       else
1110b57cec5SDimitry Andric         C = get(CounterExpression(CounterExpression::Add, C,
1120b57cec5SDimitry Andric                                   Counter::getCounter(T.CounterID)));
1130b57cec5SDimitry Andric   }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // Create subtractions.
1160b57cec5SDimitry Andric   for (auto T : Terms) {
1170b57cec5SDimitry Andric     if (T.Factor >= 0)
1180b57cec5SDimitry Andric       continue;
1190b57cec5SDimitry Andric     for (int I = 0; I < -T.Factor; ++I)
1200b57cec5SDimitry Andric       C = get(CounterExpression(CounterExpression::Subtract, C,
1210b57cec5SDimitry Andric                                 Counter::getCounter(T.CounterID)));
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric   return C;
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
1270b57cec5SDimitry Andric   return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
1310b57cec5SDimitry Andric   return simplify(
1320b57cec5SDimitry Andric       get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
1360b57cec5SDimitry Andric   switch (C.getKind()) {
1370b57cec5SDimitry Andric   case Counter::Zero:
1380b57cec5SDimitry Andric     OS << '0';
1390b57cec5SDimitry Andric     return;
1400b57cec5SDimitry Andric   case Counter::CounterValueReference:
1410b57cec5SDimitry Andric     OS << '#' << C.getCounterID();
1420b57cec5SDimitry Andric     break;
1430b57cec5SDimitry Andric   case Counter::Expression: {
1440b57cec5SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
1450b57cec5SDimitry Andric       return;
1460b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
1470b57cec5SDimitry Andric     OS << '(';
1480b57cec5SDimitry Andric     dump(E.LHS, OS);
1490b57cec5SDimitry Andric     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
1500b57cec5SDimitry Andric     dump(E.RHS, OS);
1510b57cec5SDimitry Andric     OS << ')';
1520b57cec5SDimitry Andric     break;
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric   if (CounterValues.empty())
1560b57cec5SDimitry Andric     return;
1570b57cec5SDimitry Andric   Expected<int64_t> Value = evaluate(C);
1580b57cec5SDimitry Andric   if (auto E = Value.takeError()) {
1590b57cec5SDimitry Andric     consumeError(std::move(E));
1600b57cec5SDimitry Andric     return;
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric   OS << '[' << *Value << ']';
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
1660b57cec5SDimitry Andric   switch (C.getKind()) {
1670b57cec5SDimitry Andric   case Counter::Zero:
1680b57cec5SDimitry Andric     return 0;
1690b57cec5SDimitry Andric   case Counter::CounterValueReference:
1700b57cec5SDimitry Andric     if (C.getCounterID() >= CounterValues.size())
1710b57cec5SDimitry Andric       return errorCodeToError(errc::argument_out_of_domain);
1720b57cec5SDimitry Andric     return CounterValues[C.getCounterID()];
1730b57cec5SDimitry Andric   case Counter::Expression: {
1740b57cec5SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
1750b57cec5SDimitry Andric       return errorCodeToError(errc::argument_out_of_domain);
1760b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
1770b57cec5SDimitry Andric     Expected<int64_t> LHS = evaluate(E.LHS);
1780b57cec5SDimitry Andric     if (!LHS)
1790b57cec5SDimitry Andric       return LHS;
1800b57cec5SDimitry Andric     Expected<int64_t> RHS = evaluate(E.RHS);
1810b57cec5SDimitry Andric     if (!RHS)
1820b57cec5SDimitry Andric       return RHS;
1830b57cec5SDimitry Andric     return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric   llvm_unreachable("Unhandled CounterKind");
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric void FunctionRecordIterator::skipOtherFiles() {
1900b57cec5SDimitry Andric   while (Current != Records.end() && !Filename.empty() &&
1910b57cec5SDimitry Andric          Filename != Current->Filenames[0])
1920b57cec5SDimitry Andric     ++Current;
1930b57cec5SDimitry Andric   if (Current == Records.end())
1940b57cec5SDimitry Andric     *this = FunctionRecordIterator();
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1978bcb0991SDimitry Andric ArrayRef<unsigned> CoverageMapping::getImpreciseRecordIndicesForFilename(
1988bcb0991SDimitry Andric     StringRef Filename) const {
1998bcb0991SDimitry Andric   size_t FilenameHash = hash_value(Filename);
2008bcb0991SDimitry Andric   auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
2018bcb0991SDimitry Andric   if (RecordIt == FilenameHash2RecordIndices.end())
2028bcb0991SDimitry Andric     return {};
2038bcb0991SDimitry Andric   return RecordIt->second;
2048bcb0991SDimitry Andric }
2058bcb0991SDimitry Andric 
2060b57cec5SDimitry Andric Error CoverageMapping::loadFunctionRecord(
2070b57cec5SDimitry Andric     const CoverageMappingRecord &Record,
2080b57cec5SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
2090b57cec5SDimitry Andric   StringRef OrigFuncName = Record.FunctionName;
2100b57cec5SDimitry Andric   if (OrigFuncName.empty())
2110b57cec5SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   if (Record.Filenames.empty())
2140b57cec5SDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
2150b57cec5SDimitry Andric   else
2160b57cec5SDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   CounterMappingContext Ctx(Record.Expressions);
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   std::vector<uint64_t> Counts;
2210b57cec5SDimitry Andric   if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName,
2220b57cec5SDimitry Andric                                                 Record.FunctionHash, Counts)) {
2230b57cec5SDimitry Andric     instrprof_error IPE = InstrProfError::take(std::move(E));
2240b57cec5SDimitry Andric     if (IPE == instrprof_error::hash_mismatch) {
225*5ffd83dbSDimitry Andric       FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
226*5ffd83dbSDimitry Andric                                       Record.FunctionHash);
2270b57cec5SDimitry Andric       return Error::success();
2280b57cec5SDimitry Andric     } else if (IPE != instrprof_error::unknown_function)
2290b57cec5SDimitry Andric       return make_error<InstrProfError>(IPE);
2300b57cec5SDimitry Andric     Counts.assign(Record.MappingRegions.size(), 0);
2310b57cec5SDimitry Andric   }
2320b57cec5SDimitry Andric   Ctx.setCounts(Counts);
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   assert(!Record.MappingRegions.empty() && "Function has no regions");
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   // This coverage record is a zero region for a function that's unused in
2370b57cec5SDimitry Andric   // some TU, but used in a different TU. Ignore it. The coverage maps from the
2380b57cec5SDimitry Andric   // the other TU will either be loaded (providing full region counts) or they
2390b57cec5SDimitry Andric   // won't (in which case we don't unintuitively report functions as uncovered
2400b57cec5SDimitry Andric   // when they have non-zero counts in the profile).
2410b57cec5SDimitry Andric   if (Record.MappingRegions.size() == 1 &&
2420b57cec5SDimitry Andric       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
2430b57cec5SDimitry Andric     return Error::success();
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   FunctionRecord Function(OrigFuncName, Record.Filenames);
2460b57cec5SDimitry Andric   for (const auto &Region : Record.MappingRegions) {
2470b57cec5SDimitry Andric     Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
2480b57cec5SDimitry Andric     if (auto E = ExecutionCount.takeError()) {
2490b57cec5SDimitry Andric       consumeError(std::move(E));
2500b57cec5SDimitry Andric       return Error::success();
2510b57cec5SDimitry Andric     }
2520b57cec5SDimitry Andric     Function.pushRegion(Region, *ExecutionCount);
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   // Don't create records for (filenames, function) pairs we've already seen.
2560b57cec5SDimitry Andric   auto FilenamesHash = hash_combine_range(Record.Filenames.begin(),
2570b57cec5SDimitry Andric                                           Record.Filenames.end());
2580b57cec5SDimitry Andric   if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
2590b57cec5SDimitry Andric     return Error::success();
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   Functions.push_back(std::move(Function));
2628bcb0991SDimitry Andric 
2638bcb0991SDimitry Andric   // Performance optimization: keep track of the indices of the function records
2648bcb0991SDimitry Andric   // which correspond to each filename. This can be used to substantially speed
2658bcb0991SDimitry Andric   // up queries for coverage info in a file.
2668bcb0991SDimitry Andric   unsigned RecordIndex = Functions.size() - 1;
2678bcb0991SDimitry Andric   for (StringRef Filename : Record.Filenames) {
2688bcb0991SDimitry Andric     auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
2698bcb0991SDimitry Andric     // Note that there may be duplicates in the filename set for a function
2708bcb0991SDimitry Andric     // record, because of e.g. macro expansions in the function in which both
2718bcb0991SDimitry Andric     // the macro and the function are defined in the same file.
2728bcb0991SDimitry Andric     if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
2738bcb0991SDimitry Andric       RecordIndices.push_back(RecordIndex);
2748bcb0991SDimitry Andric   }
2758bcb0991SDimitry Andric 
2760b57cec5SDimitry Andric   return Error::success();
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
2800b57cec5SDimitry Andric     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
2810b57cec5SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
2820b57cec5SDimitry Andric   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   for (const auto &CoverageReader : CoverageReaders) {
2850b57cec5SDimitry Andric     for (auto RecordOrErr : *CoverageReader) {
2860b57cec5SDimitry Andric       if (Error E = RecordOrErr.takeError())
2870b57cec5SDimitry Andric         return std::move(E);
2880b57cec5SDimitry Andric       const auto &Record = *RecordOrErr;
2890b57cec5SDimitry Andric       if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
2900b57cec5SDimitry Andric         return std::move(E);
2910b57cec5SDimitry Andric     }
2920b57cec5SDimitry Andric   }
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   return std::move(Coverage);
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric 
2978bcb0991SDimitry Andric // If E is a no_data_found error, returns success. Otherwise returns E.
2988bcb0991SDimitry Andric static Error handleMaybeNoDataFoundError(Error E) {
2998bcb0991SDimitry Andric   return handleErrors(
3008bcb0991SDimitry Andric       std::move(E), [](const CoverageMapError &CME) {
3018bcb0991SDimitry Andric         if (CME.get() == coveragemap_error::no_data_found)
3028bcb0991SDimitry Andric           return static_cast<Error>(Error::success());
3038bcb0991SDimitry Andric         return make_error<CoverageMapError>(CME.get());
3048bcb0991SDimitry Andric       });
3058bcb0991SDimitry Andric }
3068bcb0991SDimitry Andric 
3070b57cec5SDimitry Andric Expected<std::unique_ptr<CoverageMapping>>
3080b57cec5SDimitry Andric CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
3090b57cec5SDimitry Andric                       StringRef ProfileFilename, ArrayRef<StringRef> Arches) {
3100b57cec5SDimitry Andric   auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
3110b57cec5SDimitry Andric   if (Error E = ProfileReaderOrErr.takeError())
3120b57cec5SDimitry Andric     return std::move(E);
3130b57cec5SDimitry Andric   auto ProfileReader = std::move(ProfileReaderOrErr.get());
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers;
3160b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
3170b57cec5SDimitry Andric   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
3180b57cec5SDimitry Andric     auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(File.value());
3190b57cec5SDimitry Andric     if (std::error_code EC = CovMappingBufOrErr.getError())
3200b57cec5SDimitry Andric       return errorCodeToError(EC);
3210b57cec5SDimitry Andric     StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()];
3220b57cec5SDimitry Andric     MemoryBufferRef CovMappingBufRef =
3230b57cec5SDimitry Andric         CovMappingBufOrErr.get()->getMemBufferRef();
3240b57cec5SDimitry Andric     auto CoverageReadersOrErr =
3250b57cec5SDimitry Andric         BinaryCoverageReader::create(CovMappingBufRef, Arch, Buffers);
3268bcb0991SDimitry Andric     if (Error E = CoverageReadersOrErr.takeError()) {
3278bcb0991SDimitry Andric       E = handleMaybeNoDataFoundError(std::move(E));
3288bcb0991SDimitry Andric       if (E)
3290b57cec5SDimitry Andric         return std::move(E);
3308bcb0991SDimitry Andric       // E == success (originally a no_data_found error).
3318bcb0991SDimitry Andric       continue;
3328bcb0991SDimitry Andric     }
3330b57cec5SDimitry Andric     for (auto &Reader : CoverageReadersOrErr.get())
3340b57cec5SDimitry Andric       Readers.push_back(std::move(Reader));
3350b57cec5SDimitry Andric     Buffers.push_back(std::move(CovMappingBufOrErr.get()));
3360b57cec5SDimitry Andric   }
3378bcb0991SDimitry Andric   // If no readers were created, either no objects were provided or none of them
3388bcb0991SDimitry Andric   // had coverage data. Return an error in the latter case.
3398bcb0991SDimitry Andric   if (Readers.empty() && !ObjectFilenames.empty())
3408bcb0991SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
3410b57cec5SDimitry Andric   return load(Readers, *ProfileReader);
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric namespace {
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric /// Distributes functions into instantiation sets.
3470b57cec5SDimitry Andric ///
3480b57cec5SDimitry Andric /// An instantiation set is a collection of functions that have the same source
3490b57cec5SDimitry Andric /// code, ie, template functions specializations.
3500b57cec5SDimitry Andric class FunctionInstantiationSetCollector {
3510b57cec5SDimitry Andric   using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
3520b57cec5SDimitry Andric   MapT InstantiatedFunctions;
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric public:
3550b57cec5SDimitry Andric   void insert(const FunctionRecord &Function, unsigned FileID) {
3560b57cec5SDimitry Andric     auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
3570b57cec5SDimitry Andric     while (I != E && I->FileID != FileID)
3580b57cec5SDimitry Andric       ++I;
3590b57cec5SDimitry Andric     assert(I != E && "function does not cover the given file");
3600b57cec5SDimitry Andric     auto &Functions = InstantiatedFunctions[I->startLoc()];
3610b57cec5SDimitry Andric     Functions.push_back(&Function);
3620b57cec5SDimitry Andric   }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   MapT::iterator begin() { return InstantiatedFunctions.begin(); }
3650b57cec5SDimitry Andric   MapT::iterator end() { return InstantiatedFunctions.end(); }
3660b57cec5SDimitry Andric };
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric class SegmentBuilder {
3690b57cec5SDimitry Andric   std::vector<CoverageSegment> &Segments;
3700b57cec5SDimitry Andric   SmallVector<const CountedRegion *, 8> ActiveRegions;
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   /// Emit a segment with the count from \p Region starting at \p StartLoc.
3750b57cec5SDimitry Andric   //
3760b57cec5SDimitry Andric   /// \p IsRegionEntry: The segment is at the start of a new non-gap region.
3770b57cec5SDimitry Andric   /// \p EmitSkippedRegion: The segment must be emitted as a skipped region.
3780b57cec5SDimitry Andric   void startSegment(const CountedRegion &Region, LineColPair StartLoc,
3790b57cec5SDimitry Andric                     bool IsRegionEntry, bool EmitSkippedRegion = false) {
3800b57cec5SDimitry Andric     bool HasCount = !EmitSkippedRegion &&
3810b57cec5SDimitry Andric                     (Region.Kind != CounterMappingRegion::SkippedRegion);
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric     // If the new segment wouldn't affect coverage rendering, skip it.
3840b57cec5SDimitry Andric     if (!Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
3850b57cec5SDimitry Andric       const auto &Last = Segments.back();
3860b57cec5SDimitry Andric       if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount &&
3870b57cec5SDimitry Andric           !Last.IsRegionEntry)
3880b57cec5SDimitry Andric         return;
3890b57cec5SDimitry Andric     }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric     if (HasCount)
3920b57cec5SDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second,
3930b57cec5SDimitry Andric                             Region.ExecutionCount, IsRegionEntry,
3940b57cec5SDimitry Andric                             Region.Kind == CounterMappingRegion::GapRegion);
3950b57cec5SDimitry Andric     else
3960b57cec5SDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     LLVM_DEBUG({
3990b57cec5SDimitry Andric       const auto &Last = Segments.back();
4000b57cec5SDimitry Andric       dbgs() << "Segment at " << Last.Line << ":" << Last.Col
4010b57cec5SDimitry Andric              << " (count = " << Last.Count << ")"
4020b57cec5SDimitry Andric              << (Last.IsRegionEntry ? ", RegionEntry" : "")
4030b57cec5SDimitry Andric              << (!Last.HasCount ? ", Skipped" : "")
4040b57cec5SDimitry Andric              << (Last.IsGapRegion ? ", Gap" : "") << "\n";
4050b57cec5SDimitry Andric     });
4060b57cec5SDimitry Andric   }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   /// Emit segments for active regions which end before \p Loc.
4090b57cec5SDimitry Andric   ///
4100b57cec5SDimitry Andric   /// \p Loc: The start location of the next region. If None, all active
4110b57cec5SDimitry Andric   /// regions are completed.
4120b57cec5SDimitry Andric   /// \p FirstCompletedRegion: Index of the first completed region.
4130b57cec5SDimitry Andric   void completeRegionsUntil(Optional<LineColPair> Loc,
4140b57cec5SDimitry Andric                             unsigned FirstCompletedRegion) {
4150b57cec5SDimitry Andric     // Sort the completed regions by end location. This makes it simple to
4160b57cec5SDimitry Andric     // emit closing segments in sorted order.
4170b57cec5SDimitry Andric     auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;
4180b57cec5SDimitry Andric     std::stable_sort(CompletedRegionsIt, ActiveRegions.end(),
4190b57cec5SDimitry Andric                       [](const CountedRegion *L, const CountedRegion *R) {
4200b57cec5SDimitry Andric                         return L->endLoc() < R->endLoc();
4210b57cec5SDimitry Andric                       });
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric     // Emit segments for all completed regions.
4240b57cec5SDimitry Andric     for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E;
4250b57cec5SDimitry Andric          ++I) {
4260b57cec5SDimitry Andric       const auto *CompletedRegion = ActiveRegions[I];
4270b57cec5SDimitry Andric       assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
4280b57cec5SDimitry Andric              "Completed region ends after start of new region");
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric       const auto *PrevCompletedRegion = ActiveRegions[I - 1];
4310b57cec5SDimitry Andric       auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric       // Don't emit any more segments if they start where the new region begins.
4340b57cec5SDimitry Andric       if (Loc && CompletedSegmentLoc == *Loc)
4350b57cec5SDimitry Andric         break;
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric       // Don't emit a segment if the next completed region ends at the same
4380b57cec5SDimitry Andric       // location as this one.
4390b57cec5SDimitry Andric       if (CompletedSegmentLoc == CompletedRegion->endLoc())
4400b57cec5SDimitry Andric         continue;
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric       // Use the count from the last completed region which ends at this loc.
4430b57cec5SDimitry Andric       for (unsigned J = I + 1; J < E; ++J)
4440b57cec5SDimitry Andric         if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
4450b57cec5SDimitry Andric           CompletedRegion = ActiveRegions[J];
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric       startSegment(*CompletedRegion, CompletedSegmentLoc, false);
4480b57cec5SDimitry Andric     }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric     auto Last = ActiveRegions.back();
4510b57cec5SDimitry Andric     if (FirstCompletedRegion && Last->endLoc() != *Loc) {
4520b57cec5SDimitry Andric       // If there's a gap after the end of the last completed region and the
4530b57cec5SDimitry Andric       // start of the new region, use the last active region to fill the gap.
4540b57cec5SDimitry Andric       startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(),
4550b57cec5SDimitry Andric                    false);
4560b57cec5SDimitry Andric     } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) {
4570b57cec5SDimitry Andric       // Emit a skipped segment if there are no more active regions. This
4580b57cec5SDimitry Andric       // ensures that gaps between functions are marked correctly.
4590b57cec5SDimitry Andric       startSegment(*Last, Last->endLoc(), false, true);
4600b57cec5SDimitry Andric     }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     // Pop the completed regions.
4630b57cec5SDimitry Andric     ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end());
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
4670b57cec5SDimitry Andric     for (const auto &CR : enumerate(Regions)) {
4680b57cec5SDimitry Andric       auto CurStartLoc = CR.value().startLoc();
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric       // Active regions which end before the current region need to be popped.
4710b57cec5SDimitry Andric       auto CompletedRegions =
4720b57cec5SDimitry Andric           std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),
4730b57cec5SDimitry Andric                                 [&](const CountedRegion *Region) {
4740b57cec5SDimitry Andric                                   return !(Region->endLoc() <= CurStartLoc);
4750b57cec5SDimitry Andric                                 });
4760b57cec5SDimitry Andric       if (CompletedRegions != ActiveRegions.end()) {
4770b57cec5SDimitry Andric         unsigned FirstCompletedRegion =
4780b57cec5SDimitry Andric             std::distance(ActiveRegions.begin(), CompletedRegions);
4790b57cec5SDimitry Andric         completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
4800b57cec5SDimitry Andric       }
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric       bool GapRegion = CR.value().Kind == CounterMappingRegion::GapRegion;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric       // Try to emit a segment for the current region.
4850b57cec5SDimitry Andric       if (CurStartLoc == CR.value().endLoc()) {
4860b57cec5SDimitry Andric         // Avoid making zero-length regions active. If it's the last region,
4870b57cec5SDimitry Andric         // emit a skipped segment. Otherwise use its predecessor's count.
4880b57cec5SDimitry Andric         const bool Skipped = (CR.index() + 1) == Regions.size();
4890b57cec5SDimitry Andric         startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),
4900b57cec5SDimitry Andric                      CurStartLoc, !GapRegion, Skipped);
4910b57cec5SDimitry Andric         continue;
4920b57cec5SDimitry Andric       }
4930b57cec5SDimitry Andric       if (CR.index() + 1 == Regions.size() ||
4940b57cec5SDimitry Andric           CurStartLoc != Regions[CR.index() + 1].startLoc()) {
4950b57cec5SDimitry Andric         // Emit a segment if the next region doesn't start at the same location
4960b57cec5SDimitry Andric         // as this one.
4970b57cec5SDimitry Andric         startSegment(CR.value(), CurStartLoc, !GapRegion);
4980b57cec5SDimitry Andric       }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric       // This region is active (i.e not completed).
5010b57cec5SDimitry Andric       ActiveRegions.push_back(&CR.value());
5020b57cec5SDimitry Andric     }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric     // Complete any remaining active regions.
5050b57cec5SDimitry Andric     if (!ActiveRegions.empty())
5060b57cec5SDimitry Andric       completeRegionsUntil(None, 0);
5070b57cec5SDimitry Andric   }
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric   /// Sort a nested sequence of regions from a single file.
5100b57cec5SDimitry Andric   static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
5110b57cec5SDimitry Andric     llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) {
5120b57cec5SDimitry Andric       if (LHS.startLoc() != RHS.startLoc())
5130b57cec5SDimitry Andric         return LHS.startLoc() < RHS.startLoc();
5140b57cec5SDimitry Andric       if (LHS.endLoc() != RHS.endLoc())
5150b57cec5SDimitry Andric         // When LHS completely contains RHS, we sort LHS first.
5160b57cec5SDimitry Andric         return RHS.endLoc() < LHS.endLoc();
5170b57cec5SDimitry Andric       // If LHS and RHS cover the same area, we need to sort them according
5180b57cec5SDimitry Andric       // to their kinds so that the most suitable region will become "active"
5190b57cec5SDimitry Andric       // in combineRegions(). Because we accumulate counter values only from
5200b57cec5SDimitry Andric       // regions of the same kind as the first region of the area, prefer
5210b57cec5SDimitry Andric       // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
5220b57cec5SDimitry Andric       static_assert(CounterMappingRegion::CodeRegion <
5230b57cec5SDimitry Andric                             CounterMappingRegion::ExpansionRegion &&
5240b57cec5SDimitry Andric                         CounterMappingRegion::ExpansionRegion <
5250b57cec5SDimitry Andric                             CounterMappingRegion::SkippedRegion,
5260b57cec5SDimitry Andric                     "Unexpected order of region kind values");
5270b57cec5SDimitry Andric       return LHS.Kind < RHS.Kind;
5280b57cec5SDimitry Andric     });
5290b57cec5SDimitry Andric   }
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   /// Combine counts of regions which cover the same area.
5320b57cec5SDimitry Andric   static ArrayRef<CountedRegion>
5330b57cec5SDimitry Andric   combineRegions(MutableArrayRef<CountedRegion> Regions) {
5340b57cec5SDimitry Andric     if (Regions.empty())
5350b57cec5SDimitry Andric       return Regions;
5360b57cec5SDimitry Andric     auto Active = Regions.begin();
5370b57cec5SDimitry Andric     auto End = Regions.end();
5380b57cec5SDimitry Andric     for (auto I = Regions.begin() + 1; I != End; ++I) {
5390b57cec5SDimitry Andric       if (Active->startLoc() != I->startLoc() ||
5400b57cec5SDimitry Andric           Active->endLoc() != I->endLoc()) {
5410b57cec5SDimitry Andric         // Shift to the next region.
5420b57cec5SDimitry Andric         ++Active;
5430b57cec5SDimitry Andric         if (Active != I)
5440b57cec5SDimitry Andric           *Active = *I;
5450b57cec5SDimitry Andric         continue;
5460b57cec5SDimitry Andric       }
5470b57cec5SDimitry Andric       // Merge duplicate region.
5480b57cec5SDimitry Andric       // If CodeRegions and ExpansionRegions cover the same area, it's probably
5490b57cec5SDimitry Andric       // a macro which is fully expanded to another macro. In that case, we need
5500b57cec5SDimitry Andric       // to accumulate counts only from CodeRegions, or else the area will be
5510b57cec5SDimitry Andric       // counted twice.
5520b57cec5SDimitry Andric       // On the other hand, a macro may have a nested macro in its body. If the
5530b57cec5SDimitry Andric       // outer macro is used several times, the ExpansionRegion for the nested
5540b57cec5SDimitry Andric       // macro will also be added several times. These ExpansionRegions cover
5550b57cec5SDimitry Andric       // the same source locations and have to be combined to reach the correct
5560b57cec5SDimitry Andric       // value for that area.
5570b57cec5SDimitry Andric       // We add counts of the regions of the same kind as the active region
5580b57cec5SDimitry Andric       // to handle the both situations.
5590b57cec5SDimitry Andric       if (I->Kind == Active->Kind)
5600b57cec5SDimitry Andric         Active->ExecutionCount += I->ExecutionCount;
5610b57cec5SDimitry Andric     }
5620b57cec5SDimitry Andric     return Regions.drop_back(std::distance(++Active, End));
5630b57cec5SDimitry Andric   }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric public:
5660b57cec5SDimitry Andric   /// Build a sorted list of CoverageSegments from a list of Regions.
5670b57cec5SDimitry Andric   static std::vector<CoverageSegment>
5680b57cec5SDimitry Andric   buildSegments(MutableArrayRef<CountedRegion> Regions) {
5690b57cec5SDimitry Andric     std::vector<CoverageSegment> Segments;
5700b57cec5SDimitry Andric     SegmentBuilder Builder(Segments);
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric     sortNestedRegions(Regions);
5730b57cec5SDimitry Andric     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric     LLVM_DEBUG({
5760b57cec5SDimitry Andric       dbgs() << "Combined regions:\n";
5770b57cec5SDimitry Andric       for (const auto &CR : CombinedRegions)
5780b57cec5SDimitry Andric         dbgs() << "  " << CR.LineStart << ":" << CR.ColumnStart << " -> "
5790b57cec5SDimitry Andric                << CR.LineEnd << ":" << CR.ColumnEnd
5800b57cec5SDimitry Andric                << " (count=" << CR.ExecutionCount << ")\n";
5810b57cec5SDimitry Andric     });
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric     Builder.buildSegmentsImpl(CombinedRegions);
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric #ifndef NDEBUG
5860b57cec5SDimitry Andric     for (unsigned I = 1, E = Segments.size(); I < E; ++I) {
5870b57cec5SDimitry Andric       const auto &L = Segments[I - 1];
5880b57cec5SDimitry Andric       const auto &R = Segments[I];
5890b57cec5SDimitry Andric       if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) {
5900b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col
5910b57cec5SDimitry Andric                           << " followed by " << R.Line << ":" << R.Col << "\n");
5920b57cec5SDimitry Andric         assert(false && "Coverage segments not unique or sorted");
5930b57cec5SDimitry Andric       }
5940b57cec5SDimitry Andric     }
5950b57cec5SDimitry Andric #endif
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric     return Segments;
5980b57cec5SDimitry Andric   }
5990b57cec5SDimitry Andric };
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric } // end anonymous namespace
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
6040b57cec5SDimitry Andric   std::vector<StringRef> Filenames;
6050b57cec5SDimitry Andric   for (const auto &Function : getCoveredFunctions())
6060b57cec5SDimitry Andric     Filenames.insert(Filenames.end(), Function.Filenames.begin(),
6070b57cec5SDimitry Andric                      Function.Filenames.end());
6080b57cec5SDimitry Andric   llvm::sort(Filenames);
6090b57cec5SDimitry Andric   auto Last = std::unique(Filenames.begin(), Filenames.end());
6100b57cec5SDimitry Andric   Filenames.erase(Last, Filenames.end());
6110b57cec5SDimitry Andric   return Filenames;
6120b57cec5SDimitry Andric }
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric static SmallBitVector gatherFileIDs(StringRef SourceFile,
6150b57cec5SDimitry Andric                                     const FunctionRecord &Function) {
6160b57cec5SDimitry Andric   SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
6170b57cec5SDimitry Andric   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
6180b57cec5SDimitry Andric     if (SourceFile == Function.Filenames[I])
6190b57cec5SDimitry Andric       FilenameEquivalence[I] = true;
6200b57cec5SDimitry Andric   return FilenameEquivalence;
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric /// Return the ID of the file where the definition of the function is located.
6240b57cec5SDimitry Andric static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
6250b57cec5SDimitry Andric   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
6260b57cec5SDimitry Andric   for (const auto &CR : Function.CountedRegions)
6270b57cec5SDimitry Andric     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
6280b57cec5SDimitry Andric       IsNotExpandedFile[CR.ExpandedFileID] = false;
6290b57cec5SDimitry Andric   int I = IsNotExpandedFile.find_first();
6300b57cec5SDimitry Andric   if (I == -1)
6310b57cec5SDimitry Andric     return None;
6320b57cec5SDimitry Andric   return I;
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric /// Check if SourceFile is the file that contains the definition of
6360b57cec5SDimitry Andric /// the Function. Return the ID of the file in that case or None otherwise.
6370b57cec5SDimitry Andric static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
6380b57cec5SDimitry Andric                                              const FunctionRecord &Function) {
6390b57cec5SDimitry Andric   Optional<unsigned> I = findMainViewFileID(Function);
6400b57cec5SDimitry Andric   if (I && SourceFile == Function.Filenames[*I])
6410b57cec5SDimitry Andric     return I;
6420b57cec5SDimitry Andric   return None;
6430b57cec5SDimitry Andric }
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric static bool isExpansion(const CountedRegion &R, unsigned FileID) {
6460b57cec5SDimitry Andric   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
6500b57cec5SDimitry Andric   CoverageData FileCoverage(Filename);
6510b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
6520b57cec5SDimitry Andric 
6538bcb0991SDimitry Andric   // Look up the function records in the given file. Due to hash collisions on
6548bcb0991SDimitry Andric   // the filename, we may get back some records that are not in the file.
6558bcb0991SDimitry Andric   ArrayRef<unsigned> RecordIndices =
6568bcb0991SDimitry Andric       getImpreciseRecordIndicesForFilename(Filename);
6578bcb0991SDimitry Andric   for (unsigned RecordIndex : RecordIndices) {
6588bcb0991SDimitry Andric     const FunctionRecord &Function = Functions[RecordIndex];
6590b57cec5SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
6600b57cec5SDimitry Andric     auto FileIDs = gatherFileIDs(Filename, Function);
6610b57cec5SDimitry Andric     for (const auto &CR : Function.CountedRegions)
6620b57cec5SDimitry Andric       if (FileIDs.test(CR.FileID)) {
6630b57cec5SDimitry Andric         Regions.push_back(CR);
6640b57cec5SDimitry Andric         if (MainFileID && isExpansion(CR, *MainFileID))
6650b57cec5SDimitry Andric           FileCoverage.Expansions.emplace_back(CR, Function);
6660b57cec5SDimitry Andric       }
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
6700b57cec5SDimitry Andric   FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   return FileCoverage;
6730b57cec5SDimitry Andric }
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric std::vector<InstantiationGroup>
6760b57cec5SDimitry Andric CoverageMapping::getInstantiationGroups(StringRef Filename) const {
6770b57cec5SDimitry Andric   FunctionInstantiationSetCollector InstantiationSetCollector;
6788bcb0991SDimitry Andric   // Look up the function records in the given file. Due to hash collisions on
6798bcb0991SDimitry Andric   // the filename, we may get back some records that are not in the file.
6808bcb0991SDimitry Andric   ArrayRef<unsigned> RecordIndices =
6818bcb0991SDimitry Andric       getImpreciseRecordIndicesForFilename(Filename);
6828bcb0991SDimitry Andric   for (unsigned RecordIndex : RecordIndices) {
6838bcb0991SDimitry Andric     const FunctionRecord &Function = Functions[RecordIndex];
6840b57cec5SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
6850b57cec5SDimitry Andric     if (!MainFileID)
6860b57cec5SDimitry Andric       continue;
6870b57cec5SDimitry Andric     InstantiationSetCollector.insert(Function, *MainFileID);
6880b57cec5SDimitry Andric   }
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric   std::vector<InstantiationGroup> Result;
6910b57cec5SDimitry Andric   for (auto &InstantiationSet : InstantiationSetCollector) {
6920b57cec5SDimitry Andric     InstantiationGroup IG{InstantiationSet.first.first,
6930b57cec5SDimitry Andric                           InstantiationSet.first.second,
6940b57cec5SDimitry Andric                           std::move(InstantiationSet.second)};
6950b57cec5SDimitry Andric     Result.emplace_back(std::move(IG));
6960b57cec5SDimitry Andric   }
6970b57cec5SDimitry Andric   return Result;
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric CoverageData
7010b57cec5SDimitry Andric CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
7020b57cec5SDimitry Andric   auto MainFileID = findMainViewFileID(Function);
7030b57cec5SDimitry Andric   if (!MainFileID)
7040b57cec5SDimitry Andric     return CoverageData();
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric   CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
7070b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
7080b57cec5SDimitry Andric   for (const auto &CR : Function.CountedRegions)
7090b57cec5SDimitry Andric     if (CR.FileID == *MainFileID) {
7100b57cec5SDimitry Andric       Regions.push_back(CR);
7110b57cec5SDimitry Andric       if (isExpansion(CR, *MainFileID))
7120b57cec5SDimitry Andric         FunctionCoverage.Expansions.emplace_back(CR, Function);
7130b57cec5SDimitry Andric     }
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
7160b57cec5SDimitry Andric                     << "\n");
7170b57cec5SDimitry Andric   FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric   return FunctionCoverage;
7200b57cec5SDimitry Andric }
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric CoverageData CoverageMapping::getCoverageForExpansion(
7230b57cec5SDimitry Andric     const ExpansionRecord &Expansion) const {
7240b57cec5SDimitry Andric   CoverageData ExpansionCoverage(
7250b57cec5SDimitry Andric       Expansion.Function.Filenames[Expansion.FileID]);
7260b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
7270b57cec5SDimitry Andric   for (const auto &CR : Expansion.Function.CountedRegions)
7280b57cec5SDimitry Andric     if (CR.FileID == Expansion.FileID) {
7290b57cec5SDimitry Andric       Regions.push_back(CR);
7300b57cec5SDimitry Andric       if (isExpansion(CR, Expansion.FileID))
7310b57cec5SDimitry Andric         ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
7320b57cec5SDimitry Andric     }
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
7350b57cec5SDimitry Andric                     << Expansion.FileID << "\n");
7360b57cec5SDimitry Andric   ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   return ExpansionCoverage;
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric LineCoverageStats::LineCoverageStats(
7420b57cec5SDimitry Andric     ArrayRef<const CoverageSegment *> LineSegments,
7430b57cec5SDimitry Andric     const CoverageSegment *WrappedSegment, unsigned Line)
7440b57cec5SDimitry Andric     : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
7450b57cec5SDimitry Andric       LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
7460b57cec5SDimitry Andric   // Find the minimum number of regions which start in this line.
7470b57cec5SDimitry Andric   unsigned MinRegionCount = 0;
7480b57cec5SDimitry Andric   auto isStartOfRegion = [](const CoverageSegment *S) {
7490b57cec5SDimitry Andric     return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
7500b57cec5SDimitry Andric   };
7510b57cec5SDimitry Andric   for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
7520b57cec5SDimitry Andric     if (isStartOfRegion(LineSegments[I]))
7530b57cec5SDimitry Andric       ++MinRegionCount;
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric   bool StartOfSkippedRegion = !LineSegments.empty() &&
7560b57cec5SDimitry Andric                               !LineSegments.front()->HasCount &&
7570b57cec5SDimitry Andric                               LineSegments.front()->IsRegionEntry;
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric   HasMultipleRegions = MinRegionCount > 1;
7600b57cec5SDimitry Andric   Mapped =
7610b57cec5SDimitry Andric       !StartOfSkippedRegion &&
7620b57cec5SDimitry Andric       ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric   if (!Mapped)
7650b57cec5SDimitry Andric     return;
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric   // Pick the max count from the non-gap, region entry segments and the
7680b57cec5SDimitry Andric   // wrapped count.
7690b57cec5SDimitry Andric   if (WrappedSegment)
7700b57cec5SDimitry Andric     ExecutionCount = WrappedSegment->Count;
7710b57cec5SDimitry Andric   if (!MinRegionCount)
7720b57cec5SDimitry Andric     return;
7730b57cec5SDimitry Andric   for (const auto *LS : LineSegments)
7740b57cec5SDimitry Andric     if (isStartOfRegion(LS))
7750b57cec5SDimitry Andric       ExecutionCount = std::max(ExecutionCount, LS->Count);
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric LineCoverageIterator &LineCoverageIterator::operator++() {
7790b57cec5SDimitry Andric   if (Next == CD.end()) {
7800b57cec5SDimitry Andric     Stats = LineCoverageStats();
7810b57cec5SDimitry Andric     Ended = true;
7820b57cec5SDimitry Andric     return *this;
7830b57cec5SDimitry Andric   }
7840b57cec5SDimitry Andric   if (Segments.size())
7850b57cec5SDimitry Andric     WrappedSegment = Segments.back();
7860b57cec5SDimitry Andric   Segments.clear();
7870b57cec5SDimitry Andric   while (Next != CD.end() && Next->Line == Line)
7880b57cec5SDimitry Andric     Segments.push_back(&*Next++);
7890b57cec5SDimitry Andric   Stats = LineCoverageStats(Segments, WrappedSegment, Line);
7900b57cec5SDimitry Andric   ++Line;
7910b57cec5SDimitry Andric   return *this;
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric static std::string getCoverageMapErrString(coveragemap_error Err) {
7950b57cec5SDimitry Andric   switch (Err) {
7960b57cec5SDimitry Andric   case coveragemap_error::success:
7970b57cec5SDimitry Andric     return "Success";
7980b57cec5SDimitry Andric   case coveragemap_error::eof:
7990b57cec5SDimitry Andric     return "End of File";
8000b57cec5SDimitry Andric   case coveragemap_error::no_data_found:
8010b57cec5SDimitry Andric     return "No coverage data found";
8020b57cec5SDimitry Andric   case coveragemap_error::unsupported_version:
8030b57cec5SDimitry Andric     return "Unsupported coverage format version";
8040b57cec5SDimitry Andric   case coveragemap_error::truncated:
8050b57cec5SDimitry Andric     return "Truncated coverage data";
8060b57cec5SDimitry Andric   case coveragemap_error::malformed:
8070b57cec5SDimitry Andric     return "Malformed coverage data";
808*5ffd83dbSDimitry Andric   case coveragemap_error::decompression_failed:
809*5ffd83dbSDimitry Andric     return "Failed to decompress coverage data (zlib)";
8100b57cec5SDimitry Andric   }
8110b57cec5SDimitry Andric   llvm_unreachable("A value of coveragemap_error has no message.");
8120b57cec5SDimitry Andric }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric namespace {
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It
8170b57cec5SDimitry Andric // will be removed once this transition is complete. Clients should prefer to
8180b57cec5SDimitry Andric // deal with the Error value directly, rather than converting to error_code.
8190b57cec5SDimitry Andric class CoverageMappingErrorCategoryType : public std::error_category {
8200b57cec5SDimitry Andric   const char *name() const noexcept override { return "llvm.coveragemap"; }
8210b57cec5SDimitry Andric   std::string message(int IE) const override {
8220b57cec5SDimitry Andric     return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
8230b57cec5SDimitry Andric   }
8240b57cec5SDimitry Andric };
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric } // end anonymous namespace
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric std::string CoverageMapError::message() const {
8290b57cec5SDimitry Andric   return getCoverageMapErrString(Err);
8300b57cec5SDimitry Andric }
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric const std::error_category &llvm::coverage::coveragemap_category() {
8350b57cec5SDimitry Andric   return *ErrorCategory;
8360b57cec5SDimitry Andric }
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric char CoverageMapError::ID = 0;
839