xref: /freebsd/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp (revision 753f127f3ace09432b2baeffd71a308760641a62)
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/MemoryBuffer.h"
290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
300b57cec5SDimitry Andric #include <algorithm>
310b57cec5SDimitry Andric #include <cassert>
320b57cec5SDimitry Andric #include <cstdint>
330b57cec5SDimitry Andric #include <iterator>
340b57cec5SDimitry Andric #include <map>
350b57cec5SDimitry Andric #include <memory>
360b57cec5SDimitry Andric #include <string>
370b57cec5SDimitry Andric #include <system_error>
380b57cec5SDimitry Andric #include <utility>
390b57cec5SDimitry Andric #include <vector>
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric using namespace llvm;
420b57cec5SDimitry Andric using namespace coverage;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric #define DEBUG_TYPE "coverage-mapping"
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric Counter CounterExpressionBuilder::get(const CounterExpression &E) {
470b57cec5SDimitry Andric   auto It = ExpressionIndices.find(E);
480b57cec5SDimitry Andric   if (It != ExpressionIndices.end())
490b57cec5SDimitry Andric     return Counter::getExpression(It->second);
500b57cec5SDimitry Andric   unsigned I = Expressions.size();
510b57cec5SDimitry Andric   Expressions.push_back(E);
520b57cec5SDimitry Andric   ExpressionIndices[E] = I;
530b57cec5SDimitry Andric   return Counter::getExpression(I);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric void CounterExpressionBuilder::extractTerms(Counter C, int Factor,
570b57cec5SDimitry Andric                                             SmallVectorImpl<Term> &Terms) {
580b57cec5SDimitry Andric   switch (C.getKind()) {
590b57cec5SDimitry Andric   case Counter::Zero:
600b57cec5SDimitry Andric     break;
610b57cec5SDimitry Andric   case Counter::CounterValueReference:
620b57cec5SDimitry Andric     Terms.emplace_back(C.getCounterID(), Factor);
630b57cec5SDimitry Andric     break;
640b57cec5SDimitry Andric   case Counter::Expression:
650b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
660b57cec5SDimitry Andric     extractTerms(E.LHS, Factor, Terms);
670b57cec5SDimitry Andric     extractTerms(
680b57cec5SDimitry Andric         E.RHS, E.Kind == CounterExpression::Subtract ? -Factor : Factor, Terms);
690b57cec5SDimitry Andric     break;
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
740b57cec5SDimitry Andric   // Gather constant terms.
750b57cec5SDimitry Andric   SmallVector<Term, 32> Terms;
760b57cec5SDimitry Andric   extractTerms(ExpressionTree, +1, Terms);
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   // If there are no terms, this is just a zero. The algorithm below assumes at
790b57cec5SDimitry Andric   // least one term.
800b57cec5SDimitry Andric   if (Terms.size() == 0)
810b57cec5SDimitry Andric     return Counter::getZero();
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   // Group the terms by counter ID.
840b57cec5SDimitry Andric   llvm::sort(Terms, [](const Term &LHS, const Term &RHS) {
850b57cec5SDimitry Andric     return LHS.CounterID < RHS.CounterID;
860b57cec5SDimitry Andric   });
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   // Combine terms by counter ID to eliminate counters that sum to zero.
890b57cec5SDimitry Andric   auto Prev = Terms.begin();
900b57cec5SDimitry Andric   for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
910b57cec5SDimitry Andric     if (I->CounterID == Prev->CounterID) {
920b57cec5SDimitry Andric       Prev->Factor += I->Factor;
930b57cec5SDimitry Andric       continue;
940b57cec5SDimitry Andric     }
950b57cec5SDimitry Andric     ++Prev;
960b57cec5SDimitry Andric     *Prev = *I;
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric   Terms.erase(++Prev, Terms.end());
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   Counter C;
1010b57cec5SDimitry Andric   // Create additions. We do this before subtractions to avoid constructs like
1020b57cec5SDimitry Andric   // ((0 - X) + Y), as opposed to (Y - X).
1030b57cec5SDimitry Andric   for (auto T : Terms) {
1040b57cec5SDimitry Andric     if (T.Factor <= 0)
1050b57cec5SDimitry Andric       continue;
1060b57cec5SDimitry Andric     for (int I = 0; I < T.Factor; ++I)
1070b57cec5SDimitry Andric       if (C.isZero())
1080b57cec5SDimitry Andric         C = Counter::getCounter(T.CounterID);
1090b57cec5SDimitry Andric       else
1100b57cec5SDimitry Andric         C = get(CounterExpression(CounterExpression::Add, C,
1110b57cec5SDimitry Andric                                   Counter::getCounter(T.CounterID)));
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   // Create subtractions.
1150b57cec5SDimitry Andric   for (auto T : Terms) {
1160b57cec5SDimitry Andric     if (T.Factor >= 0)
1170b57cec5SDimitry Andric       continue;
1180b57cec5SDimitry Andric     for (int I = 0; I < -T.Factor; ++I)
1190b57cec5SDimitry Andric       C = get(CounterExpression(CounterExpression::Subtract, C,
1200b57cec5SDimitry Andric                                 Counter::getCounter(T.CounterID)));
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric   return C;
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
12581ad6265SDimitry Andric Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS, bool Simplify) {
12681ad6265SDimitry Andric   auto Cnt = get(CounterExpression(CounterExpression::Add, LHS, RHS));
12781ad6265SDimitry Andric   return Simplify ? simplify(Cnt) : Cnt;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
13081ad6265SDimitry Andric Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS,
13181ad6265SDimitry Andric                                            bool Simplify) {
13281ad6265SDimitry Andric   auto Cnt = get(CounterExpression(CounterExpression::Subtract, LHS, RHS));
13381ad6265SDimitry Andric   return Simplify ? simplify(Cnt) : Cnt;
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
1370b57cec5SDimitry Andric   switch (C.getKind()) {
1380b57cec5SDimitry Andric   case Counter::Zero:
1390b57cec5SDimitry Andric     OS << '0';
1400b57cec5SDimitry Andric     return;
1410b57cec5SDimitry Andric   case Counter::CounterValueReference:
1420b57cec5SDimitry Andric     OS << '#' << C.getCounterID();
1430b57cec5SDimitry Andric     break;
1440b57cec5SDimitry Andric   case Counter::Expression: {
1450b57cec5SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
1460b57cec5SDimitry Andric       return;
1470b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
1480b57cec5SDimitry Andric     OS << '(';
1490b57cec5SDimitry Andric     dump(E.LHS, OS);
1500b57cec5SDimitry Andric     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
1510b57cec5SDimitry Andric     dump(E.RHS, OS);
1520b57cec5SDimitry Andric     OS << ')';
1530b57cec5SDimitry Andric     break;
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric   if (CounterValues.empty())
1570b57cec5SDimitry Andric     return;
1580b57cec5SDimitry Andric   Expected<int64_t> Value = evaluate(C);
1590b57cec5SDimitry Andric   if (auto E = Value.takeError()) {
1600b57cec5SDimitry Andric     consumeError(std::move(E));
1610b57cec5SDimitry Andric     return;
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric   OS << '[' << *Value << ']';
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
1670b57cec5SDimitry Andric   switch (C.getKind()) {
1680b57cec5SDimitry Andric   case Counter::Zero:
1690b57cec5SDimitry Andric     return 0;
1700b57cec5SDimitry Andric   case Counter::CounterValueReference:
1710b57cec5SDimitry Andric     if (C.getCounterID() >= CounterValues.size())
1720b57cec5SDimitry Andric       return errorCodeToError(errc::argument_out_of_domain);
1730b57cec5SDimitry Andric     return CounterValues[C.getCounterID()];
1740b57cec5SDimitry Andric   case Counter::Expression: {
1750b57cec5SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
1760b57cec5SDimitry Andric       return errorCodeToError(errc::argument_out_of_domain);
1770b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
1780b57cec5SDimitry Andric     Expected<int64_t> LHS = evaluate(E.LHS);
1790b57cec5SDimitry Andric     if (!LHS)
1800b57cec5SDimitry Andric       return LHS;
1810b57cec5SDimitry Andric     Expected<int64_t> RHS = evaluate(E.RHS);
1820b57cec5SDimitry Andric     if (!RHS)
1830b57cec5SDimitry Andric       return RHS;
1840b57cec5SDimitry Andric     return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric   llvm_unreachable("Unhandled CounterKind");
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
190fe6060f1SDimitry Andric unsigned CounterMappingContext::getMaxCounterID(const Counter &C) const {
191fe6060f1SDimitry Andric   switch (C.getKind()) {
192fe6060f1SDimitry Andric   case Counter::Zero:
193fe6060f1SDimitry Andric     return 0;
194fe6060f1SDimitry Andric   case Counter::CounterValueReference:
195fe6060f1SDimitry Andric     return C.getCounterID();
196fe6060f1SDimitry Andric   case Counter::Expression: {
197fe6060f1SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
198fe6060f1SDimitry Andric       return 0;
199fe6060f1SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
200fe6060f1SDimitry Andric     return std::max(getMaxCounterID(E.LHS), getMaxCounterID(E.RHS));
201fe6060f1SDimitry Andric   }
202fe6060f1SDimitry Andric   }
203fe6060f1SDimitry Andric   llvm_unreachable("Unhandled CounterKind");
204fe6060f1SDimitry Andric }
205fe6060f1SDimitry Andric 
2060b57cec5SDimitry Andric void FunctionRecordIterator::skipOtherFiles() {
2070b57cec5SDimitry Andric   while (Current != Records.end() && !Filename.empty() &&
2080b57cec5SDimitry Andric          Filename != Current->Filenames[0])
2090b57cec5SDimitry Andric     ++Current;
2100b57cec5SDimitry Andric   if (Current == Records.end())
2110b57cec5SDimitry Andric     *this = FunctionRecordIterator();
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
2148bcb0991SDimitry Andric ArrayRef<unsigned> CoverageMapping::getImpreciseRecordIndicesForFilename(
2158bcb0991SDimitry Andric     StringRef Filename) const {
2168bcb0991SDimitry Andric   size_t FilenameHash = hash_value(Filename);
2178bcb0991SDimitry Andric   auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
2188bcb0991SDimitry Andric   if (RecordIt == FilenameHash2RecordIndices.end())
2198bcb0991SDimitry Andric     return {};
2208bcb0991SDimitry Andric   return RecordIt->second;
2218bcb0991SDimitry Andric }
2228bcb0991SDimitry Andric 
223fe6060f1SDimitry Andric static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
224fe6060f1SDimitry Andric                                 const CoverageMappingRecord &Record) {
225fe6060f1SDimitry Andric   unsigned MaxCounterID = 0;
226fe6060f1SDimitry Andric   for (const auto &Region : Record.MappingRegions) {
227fe6060f1SDimitry Andric     MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count));
228fe6060f1SDimitry Andric   }
229fe6060f1SDimitry Andric   return MaxCounterID;
230fe6060f1SDimitry Andric }
231fe6060f1SDimitry Andric 
2320b57cec5SDimitry Andric Error CoverageMapping::loadFunctionRecord(
2330b57cec5SDimitry Andric     const CoverageMappingRecord &Record,
2340b57cec5SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
2350b57cec5SDimitry Andric   StringRef OrigFuncName = Record.FunctionName;
2360b57cec5SDimitry Andric   if (OrigFuncName.empty())
2370b57cec5SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   if (Record.Filenames.empty())
2400b57cec5SDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
2410b57cec5SDimitry Andric   else
2420b57cec5SDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   CounterMappingContext Ctx(Record.Expressions);
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   std::vector<uint64_t> Counts;
2470b57cec5SDimitry Andric   if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName,
2480b57cec5SDimitry Andric                                                 Record.FunctionHash, Counts)) {
2490b57cec5SDimitry Andric     instrprof_error IPE = InstrProfError::take(std::move(E));
2500b57cec5SDimitry Andric     if (IPE == instrprof_error::hash_mismatch) {
2515ffd83dbSDimitry Andric       FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
2525ffd83dbSDimitry Andric                                       Record.FunctionHash);
2530b57cec5SDimitry Andric       return Error::success();
2540b57cec5SDimitry Andric     } else if (IPE != instrprof_error::unknown_function)
2550b57cec5SDimitry Andric       return make_error<InstrProfError>(IPE);
256fe6060f1SDimitry Andric     Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
2570b57cec5SDimitry Andric   }
2580b57cec5SDimitry Andric   Ctx.setCounts(Counts);
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   assert(!Record.MappingRegions.empty() && "Function has no regions");
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   // This coverage record is a zero region for a function that's unused in
2630b57cec5SDimitry Andric   // some TU, but used in a different TU. Ignore it. The coverage maps from the
2640b57cec5SDimitry Andric   // the other TU will either be loaded (providing full region counts) or they
2650b57cec5SDimitry Andric   // won't (in which case we don't unintuitively report functions as uncovered
2660b57cec5SDimitry Andric   // when they have non-zero counts in the profile).
2670b57cec5SDimitry Andric   if (Record.MappingRegions.size() == 1 &&
2680b57cec5SDimitry Andric       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
2690b57cec5SDimitry Andric     return Error::success();
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   FunctionRecord Function(OrigFuncName, Record.Filenames);
2720b57cec5SDimitry Andric   for (const auto &Region : Record.MappingRegions) {
2730b57cec5SDimitry Andric     Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
2740b57cec5SDimitry Andric     if (auto E = ExecutionCount.takeError()) {
2750b57cec5SDimitry Andric       consumeError(std::move(E));
2760b57cec5SDimitry Andric       return Error::success();
2770b57cec5SDimitry Andric     }
278e8d8bef9SDimitry Andric     Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
279e8d8bef9SDimitry Andric     if (auto E = AltExecutionCount.takeError()) {
280e8d8bef9SDimitry Andric       consumeError(std::move(E));
281e8d8bef9SDimitry Andric       return Error::success();
282e8d8bef9SDimitry Andric     }
283e8d8bef9SDimitry Andric     Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   // Don't create records for (filenames, function) pairs we've already seen.
2870b57cec5SDimitry Andric   auto FilenamesHash = hash_combine_range(Record.Filenames.begin(),
2880b57cec5SDimitry Andric                                           Record.Filenames.end());
2890b57cec5SDimitry Andric   if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
2900b57cec5SDimitry Andric     return Error::success();
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   Functions.push_back(std::move(Function));
2938bcb0991SDimitry Andric 
2948bcb0991SDimitry Andric   // Performance optimization: keep track of the indices of the function records
2958bcb0991SDimitry Andric   // which correspond to each filename. This can be used to substantially speed
2968bcb0991SDimitry Andric   // up queries for coverage info in a file.
2978bcb0991SDimitry Andric   unsigned RecordIndex = Functions.size() - 1;
2988bcb0991SDimitry Andric   for (StringRef Filename : Record.Filenames) {
2998bcb0991SDimitry Andric     auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
3008bcb0991SDimitry Andric     // Note that there may be duplicates in the filename set for a function
3018bcb0991SDimitry Andric     // record, because of e.g. macro expansions in the function in which both
3028bcb0991SDimitry Andric     // the macro and the function are defined in the same file.
3038bcb0991SDimitry Andric     if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
3048bcb0991SDimitry Andric       RecordIndices.push_back(RecordIndex);
3058bcb0991SDimitry Andric   }
3068bcb0991SDimitry Andric 
3070b57cec5SDimitry Andric   return Error::success();
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric 
310fe6060f1SDimitry Andric // This function is for memory optimization by shortening the lifetimes
311fe6060f1SDimitry Andric // of CoverageMappingReader instances.
312fe6060f1SDimitry Andric Error CoverageMapping::loadFromReaders(
313fe6060f1SDimitry Andric     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
314fe6060f1SDimitry Andric     IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage) {
315fe6060f1SDimitry Andric   for (const auto &CoverageReader : CoverageReaders) {
316fe6060f1SDimitry Andric     for (auto RecordOrErr : *CoverageReader) {
317fe6060f1SDimitry Andric       if (Error E = RecordOrErr.takeError())
318fe6060f1SDimitry Andric         return E;
319fe6060f1SDimitry Andric       const auto &Record = *RecordOrErr;
320fe6060f1SDimitry Andric       if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader))
321fe6060f1SDimitry Andric         return E;
322fe6060f1SDimitry Andric     }
323fe6060f1SDimitry Andric   }
324fe6060f1SDimitry Andric   return Error::success();
325fe6060f1SDimitry Andric }
326fe6060f1SDimitry Andric 
3270b57cec5SDimitry Andric Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
3280b57cec5SDimitry Andric     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
3290b57cec5SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
3300b57cec5SDimitry Andric   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
331fe6060f1SDimitry Andric   if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
3320b57cec5SDimitry Andric     return std::move(E);
3330b57cec5SDimitry Andric   return std::move(Coverage);
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
3368bcb0991SDimitry Andric // If E is a no_data_found error, returns success. Otherwise returns E.
3378bcb0991SDimitry Andric static Error handleMaybeNoDataFoundError(Error E) {
3388bcb0991SDimitry Andric   return handleErrors(
3398bcb0991SDimitry Andric       std::move(E), [](const CoverageMapError &CME) {
3408bcb0991SDimitry Andric         if (CME.get() == coveragemap_error::no_data_found)
3418bcb0991SDimitry Andric           return static_cast<Error>(Error::success());
3428bcb0991SDimitry Andric         return make_error<CoverageMapError>(CME.get());
3438bcb0991SDimitry Andric       });
3448bcb0991SDimitry Andric }
3458bcb0991SDimitry Andric 
3460b57cec5SDimitry Andric Expected<std::unique_ptr<CoverageMapping>>
3470b57cec5SDimitry Andric CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
348fe6060f1SDimitry Andric                       StringRef ProfileFilename, ArrayRef<StringRef> Arches,
349fe6060f1SDimitry Andric                       StringRef CompilationDir) {
3500b57cec5SDimitry Andric   auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
3510b57cec5SDimitry Andric   if (Error E = ProfileReaderOrErr.takeError())
3520b57cec5SDimitry Andric     return std::move(E);
3530b57cec5SDimitry Andric   auto ProfileReader = std::move(ProfileReaderOrErr.get());
354fe6060f1SDimitry Andric   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
355fe6060f1SDimitry Andric   bool DataFound = false;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
358fe6060f1SDimitry Andric     auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(
359fe6060f1SDimitry Andric         File.value(), /*IsText=*/false, /*RequiresNullTerminator=*/false);
3600b57cec5SDimitry Andric     if (std::error_code EC = CovMappingBufOrErr.getError())
3610b57cec5SDimitry Andric       return errorCodeToError(EC);
3620b57cec5SDimitry Andric     StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()];
3630b57cec5SDimitry Andric     MemoryBufferRef CovMappingBufRef =
3640b57cec5SDimitry Andric         CovMappingBufOrErr.get()->getMemBufferRef();
365fe6060f1SDimitry Andric     SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
366fe6060f1SDimitry Andric     auto CoverageReadersOrErr = BinaryCoverageReader::create(
367fe6060f1SDimitry Andric         CovMappingBufRef, Arch, Buffers, CompilationDir);
3688bcb0991SDimitry Andric     if (Error E = CoverageReadersOrErr.takeError()) {
3698bcb0991SDimitry Andric       E = handleMaybeNoDataFoundError(std::move(E));
3708bcb0991SDimitry Andric       if (E)
3710b57cec5SDimitry Andric         return std::move(E);
3728bcb0991SDimitry Andric       // E == success (originally a no_data_found error).
3738bcb0991SDimitry Andric       continue;
3748bcb0991SDimitry Andric     }
375fe6060f1SDimitry Andric 
376fe6060f1SDimitry Andric     SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers;
3770b57cec5SDimitry Andric     for (auto &Reader : CoverageReadersOrErr.get())
3780b57cec5SDimitry Andric       Readers.push_back(std::move(Reader));
379fe6060f1SDimitry Andric     DataFound |= !Readers.empty();
380fe6060f1SDimitry Andric     if (Error E = loadFromReaders(Readers, *ProfileReader, *Coverage))
381fe6060f1SDimitry Andric       return std::move(E);
3820b57cec5SDimitry Andric   }
3838bcb0991SDimitry Andric   // If no readers were created, either no objects were provided or none of them
3848bcb0991SDimitry Andric   // had coverage data. Return an error in the latter case.
385fe6060f1SDimitry Andric   if (!DataFound && !ObjectFilenames.empty())
3868bcb0991SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
387fe6060f1SDimitry Andric   return std::move(Coverage);
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric namespace {
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric /// Distributes functions into instantiation sets.
3930b57cec5SDimitry Andric ///
3940b57cec5SDimitry Andric /// An instantiation set is a collection of functions that have the same source
3950b57cec5SDimitry Andric /// code, ie, template functions specializations.
3960b57cec5SDimitry Andric class FunctionInstantiationSetCollector {
3970b57cec5SDimitry Andric   using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
3980b57cec5SDimitry Andric   MapT InstantiatedFunctions;
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric public:
4010b57cec5SDimitry Andric   void insert(const FunctionRecord &Function, unsigned FileID) {
4020b57cec5SDimitry Andric     auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
4030b57cec5SDimitry Andric     while (I != E && I->FileID != FileID)
4040b57cec5SDimitry Andric       ++I;
4050b57cec5SDimitry Andric     assert(I != E && "function does not cover the given file");
4060b57cec5SDimitry Andric     auto &Functions = InstantiatedFunctions[I->startLoc()];
4070b57cec5SDimitry Andric     Functions.push_back(&Function);
4080b57cec5SDimitry Andric   }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   MapT::iterator begin() { return InstantiatedFunctions.begin(); }
4110b57cec5SDimitry Andric   MapT::iterator end() { return InstantiatedFunctions.end(); }
4120b57cec5SDimitry Andric };
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric class SegmentBuilder {
4150b57cec5SDimitry Andric   std::vector<CoverageSegment> &Segments;
4160b57cec5SDimitry Andric   SmallVector<const CountedRegion *, 8> ActiveRegions;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   /// Emit a segment with the count from \p Region starting at \p StartLoc.
4210b57cec5SDimitry Andric   //
4220b57cec5SDimitry Andric   /// \p IsRegionEntry: The segment is at the start of a new non-gap region.
4230b57cec5SDimitry Andric   /// \p EmitSkippedRegion: The segment must be emitted as a skipped region.
4240b57cec5SDimitry Andric   void startSegment(const CountedRegion &Region, LineColPair StartLoc,
4250b57cec5SDimitry Andric                     bool IsRegionEntry, bool EmitSkippedRegion = false) {
4260b57cec5SDimitry Andric     bool HasCount = !EmitSkippedRegion &&
4270b57cec5SDimitry Andric                     (Region.Kind != CounterMappingRegion::SkippedRegion);
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric     // If the new segment wouldn't affect coverage rendering, skip it.
4300b57cec5SDimitry Andric     if (!Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
4310b57cec5SDimitry Andric       const auto &Last = Segments.back();
4320b57cec5SDimitry Andric       if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount &&
4330b57cec5SDimitry Andric           !Last.IsRegionEntry)
4340b57cec5SDimitry Andric         return;
4350b57cec5SDimitry Andric     }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric     if (HasCount)
4380b57cec5SDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second,
4390b57cec5SDimitry Andric                             Region.ExecutionCount, IsRegionEntry,
4400b57cec5SDimitry Andric                             Region.Kind == CounterMappingRegion::GapRegion);
4410b57cec5SDimitry Andric     else
4420b57cec5SDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric     LLVM_DEBUG({
4450b57cec5SDimitry Andric       const auto &Last = Segments.back();
4460b57cec5SDimitry Andric       dbgs() << "Segment at " << Last.Line << ":" << Last.Col
4470b57cec5SDimitry Andric              << " (count = " << Last.Count << ")"
4480b57cec5SDimitry Andric              << (Last.IsRegionEntry ? ", RegionEntry" : "")
4490b57cec5SDimitry Andric              << (!Last.HasCount ? ", Skipped" : "")
4500b57cec5SDimitry Andric              << (Last.IsGapRegion ? ", Gap" : "") << "\n";
4510b57cec5SDimitry Andric     });
4520b57cec5SDimitry Andric   }
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   /// Emit segments for active regions which end before \p Loc.
4550b57cec5SDimitry Andric   ///
4560b57cec5SDimitry Andric   /// \p Loc: The start location of the next region. If None, all active
4570b57cec5SDimitry Andric   /// regions are completed.
4580b57cec5SDimitry Andric   /// \p FirstCompletedRegion: Index of the first completed region.
4590b57cec5SDimitry Andric   void completeRegionsUntil(Optional<LineColPair> Loc,
4600b57cec5SDimitry Andric                             unsigned FirstCompletedRegion) {
4610b57cec5SDimitry Andric     // Sort the completed regions by end location. This makes it simple to
4620b57cec5SDimitry Andric     // emit closing segments in sorted order.
4630b57cec5SDimitry Andric     auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;
4640b57cec5SDimitry Andric     std::stable_sort(CompletedRegionsIt, ActiveRegions.end(),
4650b57cec5SDimitry Andric                       [](const CountedRegion *L, const CountedRegion *R) {
4660b57cec5SDimitry Andric                         return L->endLoc() < R->endLoc();
4670b57cec5SDimitry Andric                       });
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric     // Emit segments for all completed regions.
4700b57cec5SDimitry Andric     for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E;
4710b57cec5SDimitry Andric          ++I) {
4720b57cec5SDimitry Andric       const auto *CompletedRegion = ActiveRegions[I];
4730b57cec5SDimitry Andric       assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
4740b57cec5SDimitry Andric              "Completed region ends after start of new region");
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric       const auto *PrevCompletedRegion = ActiveRegions[I - 1];
4770b57cec5SDimitry Andric       auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric       // Don't emit any more segments if they start where the new region begins.
4800b57cec5SDimitry Andric       if (Loc && CompletedSegmentLoc == *Loc)
4810b57cec5SDimitry Andric         break;
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric       // Don't emit a segment if the next completed region ends at the same
4840b57cec5SDimitry Andric       // location as this one.
4850b57cec5SDimitry Andric       if (CompletedSegmentLoc == CompletedRegion->endLoc())
4860b57cec5SDimitry Andric         continue;
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric       // Use the count from the last completed region which ends at this loc.
4890b57cec5SDimitry Andric       for (unsigned J = I + 1; J < E; ++J)
4900b57cec5SDimitry Andric         if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
4910b57cec5SDimitry Andric           CompletedRegion = ActiveRegions[J];
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric       startSegment(*CompletedRegion, CompletedSegmentLoc, false);
4940b57cec5SDimitry Andric     }
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric     auto Last = ActiveRegions.back();
4970b57cec5SDimitry Andric     if (FirstCompletedRegion && Last->endLoc() != *Loc) {
4980b57cec5SDimitry Andric       // If there's a gap after the end of the last completed region and the
4990b57cec5SDimitry Andric       // start of the new region, use the last active region to fill the gap.
5000b57cec5SDimitry Andric       startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(),
5010b57cec5SDimitry Andric                    false);
5020b57cec5SDimitry Andric     } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) {
5030b57cec5SDimitry Andric       // Emit a skipped segment if there are no more active regions. This
5040b57cec5SDimitry Andric       // ensures that gaps between functions are marked correctly.
5050b57cec5SDimitry Andric       startSegment(*Last, Last->endLoc(), false, true);
5060b57cec5SDimitry Andric     }
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric     // Pop the completed regions.
5090b57cec5SDimitry Andric     ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end());
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
5130b57cec5SDimitry Andric     for (const auto &CR : enumerate(Regions)) {
5140b57cec5SDimitry Andric       auto CurStartLoc = CR.value().startLoc();
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric       // Active regions which end before the current region need to be popped.
5170b57cec5SDimitry Andric       auto CompletedRegions =
5180b57cec5SDimitry Andric           std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),
5190b57cec5SDimitry Andric                                 [&](const CountedRegion *Region) {
5200b57cec5SDimitry Andric                                   return !(Region->endLoc() <= CurStartLoc);
5210b57cec5SDimitry Andric                                 });
5220b57cec5SDimitry Andric       if (CompletedRegions != ActiveRegions.end()) {
5230b57cec5SDimitry Andric         unsigned FirstCompletedRegion =
5240b57cec5SDimitry Andric             std::distance(ActiveRegions.begin(), CompletedRegions);
5250b57cec5SDimitry Andric         completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
5260b57cec5SDimitry Andric       }
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric       bool GapRegion = CR.value().Kind == CounterMappingRegion::GapRegion;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric       // Try to emit a segment for the current region.
5310b57cec5SDimitry Andric       if (CurStartLoc == CR.value().endLoc()) {
5320b57cec5SDimitry Andric         // Avoid making zero-length regions active. If it's the last region,
5330b57cec5SDimitry Andric         // emit a skipped segment. Otherwise use its predecessor's count.
534e8d8bef9SDimitry Andric         const bool Skipped =
535e8d8bef9SDimitry Andric             (CR.index() + 1) == Regions.size() ||
536e8d8bef9SDimitry Andric             CR.value().Kind == CounterMappingRegion::SkippedRegion;
5370b57cec5SDimitry Andric         startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),
5380b57cec5SDimitry Andric                      CurStartLoc, !GapRegion, Skipped);
539e8d8bef9SDimitry Andric         // If it is skipped segment, create a segment with last pushed
540e8d8bef9SDimitry Andric         // regions's count at CurStartLoc.
541e8d8bef9SDimitry Andric         if (Skipped && !ActiveRegions.empty())
542e8d8bef9SDimitry Andric           startSegment(*ActiveRegions.back(), CurStartLoc, false);
5430b57cec5SDimitry Andric         continue;
5440b57cec5SDimitry Andric       }
5450b57cec5SDimitry Andric       if (CR.index() + 1 == Regions.size() ||
5460b57cec5SDimitry Andric           CurStartLoc != Regions[CR.index() + 1].startLoc()) {
5470b57cec5SDimitry Andric         // Emit a segment if the next region doesn't start at the same location
5480b57cec5SDimitry Andric         // as this one.
5490b57cec5SDimitry Andric         startSegment(CR.value(), CurStartLoc, !GapRegion);
5500b57cec5SDimitry Andric       }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric       // This region is active (i.e not completed).
5530b57cec5SDimitry Andric       ActiveRegions.push_back(&CR.value());
5540b57cec5SDimitry Andric     }
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric     // Complete any remaining active regions.
5570b57cec5SDimitry Andric     if (!ActiveRegions.empty())
5580b57cec5SDimitry Andric       completeRegionsUntil(None, 0);
5590b57cec5SDimitry Andric   }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   /// Sort a nested sequence of regions from a single file.
5620b57cec5SDimitry Andric   static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
5630b57cec5SDimitry Andric     llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) {
5640b57cec5SDimitry Andric       if (LHS.startLoc() != RHS.startLoc())
5650b57cec5SDimitry Andric         return LHS.startLoc() < RHS.startLoc();
5660b57cec5SDimitry Andric       if (LHS.endLoc() != RHS.endLoc())
5670b57cec5SDimitry Andric         // When LHS completely contains RHS, we sort LHS first.
5680b57cec5SDimitry Andric         return RHS.endLoc() < LHS.endLoc();
5690b57cec5SDimitry Andric       // If LHS and RHS cover the same area, we need to sort them according
5700b57cec5SDimitry Andric       // to their kinds so that the most suitable region will become "active"
5710b57cec5SDimitry Andric       // in combineRegions(). Because we accumulate counter values only from
5720b57cec5SDimitry Andric       // regions of the same kind as the first region of the area, prefer
5730b57cec5SDimitry Andric       // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
5740b57cec5SDimitry Andric       static_assert(CounterMappingRegion::CodeRegion <
5750b57cec5SDimitry Andric                             CounterMappingRegion::ExpansionRegion &&
5760b57cec5SDimitry Andric                         CounterMappingRegion::ExpansionRegion <
5770b57cec5SDimitry Andric                             CounterMappingRegion::SkippedRegion,
5780b57cec5SDimitry Andric                     "Unexpected order of region kind values");
5790b57cec5SDimitry Andric       return LHS.Kind < RHS.Kind;
5800b57cec5SDimitry Andric     });
5810b57cec5SDimitry Andric   }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric   /// Combine counts of regions which cover the same area.
5840b57cec5SDimitry Andric   static ArrayRef<CountedRegion>
5850b57cec5SDimitry Andric   combineRegions(MutableArrayRef<CountedRegion> Regions) {
5860b57cec5SDimitry Andric     if (Regions.empty())
5870b57cec5SDimitry Andric       return Regions;
5880b57cec5SDimitry Andric     auto Active = Regions.begin();
5890b57cec5SDimitry Andric     auto End = Regions.end();
5900b57cec5SDimitry Andric     for (auto I = Regions.begin() + 1; I != End; ++I) {
5910b57cec5SDimitry Andric       if (Active->startLoc() != I->startLoc() ||
5920b57cec5SDimitry Andric           Active->endLoc() != I->endLoc()) {
5930b57cec5SDimitry Andric         // Shift to the next region.
5940b57cec5SDimitry Andric         ++Active;
5950b57cec5SDimitry Andric         if (Active != I)
5960b57cec5SDimitry Andric           *Active = *I;
5970b57cec5SDimitry Andric         continue;
5980b57cec5SDimitry Andric       }
5990b57cec5SDimitry Andric       // Merge duplicate region.
6000b57cec5SDimitry Andric       // If CodeRegions and ExpansionRegions cover the same area, it's probably
6010b57cec5SDimitry Andric       // a macro which is fully expanded to another macro. In that case, we need
6020b57cec5SDimitry Andric       // to accumulate counts only from CodeRegions, or else the area will be
6030b57cec5SDimitry Andric       // counted twice.
6040b57cec5SDimitry Andric       // On the other hand, a macro may have a nested macro in its body. If the
6050b57cec5SDimitry Andric       // outer macro is used several times, the ExpansionRegion for the nested
6060b57cec5SDimitry Andric       // macro will also be added several times. These ExpansionRegions cover
6070b57cec5SDimitry Andric       // the same source locations and have to be combined to reach the correct
6080b57cec5SDimitry Andric       // value for that area.
6090b57cec5SDimitry Andric       // We add counts of the regions of the same kind as the active region
6100b57cec5SDimitry Andric       // to handle the both situations.
6110b57cec5SDimitry Andric       if (I->Kind == Active->Kind)
6120b57cec5SDimitry Andric         Active->ExecutionCount += I->ExecutionCount;
6130b57cec5SDimitry Andric     }
6140b57cec5SDimitry Andric     return Regions.drop_back(std::distance(++Active, End));
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric public:
6180b57cec5SDimitry Andric   /// Build a sorted list of CoverageSegments from a list of Regions.
6190b57cec5SDimitry Andric   static std::vector<CoverageSegment>
6200b57cec5SDimitry Andric   buildSegments(MutableArrayRef<CountedRegion> Regions) {
6210b57cec5SDimitry Andric     std::vector<CoverageSegment> Segments;
6220b57cec5SDimitry Andric     SegmentBuilder Builder(Segments);
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric     sortNestedRegions(Regions);
6250b57cec5SDimitry Andric     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric     LLVM_DEBUG({
6280b57cec5SDimitry Andric       dbgs() << "Combined regions:\n";
6290b57cec5SDimitry Andric       for (const auto &CR : CombinedRegions)
6300b57cec5SDimitry Andric         dbgs() << "  " << CR.LineStart << ":" << CR.ColumnStart << " -> "
6310b57cec5SDimitry Andric                << CR.LineEnd << ":" << CR.ColumnEnd
6320b57cec5SDimitry Andric                << " (count=" << CR.ExecutionCount << ")\n";
6330b57cec5SDimitry Andric     });
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric     Builder.buildSegmentsImpl(CombinedRegions);
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric #ifndef NDEBUG
6380b57cec5SDimitry Andric     for (unsigned I = 1, E = Segments.size(); I < E; ++I) {
6390b57cec5SDimitry Andric       const auto &L = Segments[I - 1];
6400b57cec5SDimitry Andric       const auto &R = Segments[I];
6410b57cec5SDimitry Andric       if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) {
642e8d8bef9SDimitry Andric         if (L.Line == R.Line && L.Col == R.Col && !L.HasCount)
643e8d8bef9SDimitry Andric           continue;
6440b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col
6450b57cec5SDimitry Andric                           << " followed by " << R.Line << ":" << R.Col << "\n");
6460b57cec5SDimitry Andric         assert(false && "Coverage segments not unique or sorted");
6470b57cec5SDimitry Andric       }
6480b57cec5SDimitry Andric     }
6490b57cec5SDimitry Andric #endif
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric     return Segments;
6520b57cec5SDimitry Andric   }
6530b57cec5SDimitry Andric };
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric } // end anonymous namespace
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
6580b57cec5SDimitry Andric   std::vector<StringRef> Filenames;
6590b57cec5SDimitry Andric   for (const auto &Function : getCoveredFunctions())
660e8d8bef9SDimitry Andric     llvm::append_range(Filenames, Function.Filenames);
6610b57cec5SDimitry Andric   llvm::sort(Filenames);
6620b57cec5SDimitry Andric   auto Last = std::unique(Filenames.begin(), Filenames.end());
6630b57cec5SDimitry Andric   Filenames.erase(Last, Filenames.end());
6640b57cec5SDimitry Andric   return Filenames;
6650b57cec5SDimitry Andric }
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric static SmallBitVector gatherFileIDs(StringRef SourceFile,
6680b57cec5SDimitry Andric                                     const FunctionRecord &Function) {
6690b57cec5SDimitry Andric   SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
6700b57cec5SDimitry Andric   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
6710b57cec5SDimitry Andric     if (SourceFile == Function.Filenames[I])
6720b57cec5SDimitry Andric       FilenameEquivalence[I] = true;
6730b57cec5SDimitry Andric   return FilenameEquivalence;
6740b57cec5SDimitry Andric }
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric /// Return the ID of the file where the definition of the function is located.
6770b57cec5SDimitry Andric static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
6780b57cec5SDimitry Andric   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
6790b57cec5SDimitry Andric   for (const auto &CR : Function.CountedRegions)
6800b57cec5SDimitry Andric     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
6810b57cec5SDimitry Andric       IsNotExpandedFile[CR.ExpandedFileID] = false;
6820b57cec5SDimitry Andric   int I = IsNotExpandedFile.find_first();
6830b57cec5SDimitry Andric   if (I == -1)
6840b57cec5SDimitry Andric     return None;
6850b57cec5SDimitry Andric   return I;
6860b57cec5SDimitry Andric }
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric /// Check if SourceFile is the file that contains the definition of
6890b57cec5SDimitry Andric /// the Function. Return the ID of the file in that case or None otherwise.
6900b57cec5SDimitry Andric static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
6910b57cec5SDimitry Andric                                              const FunctionRecord &Function) {
6920b57cec5SDimitry Andric   Optional<unsigned> I = findMainViewFileID(Function);
6930b57cec5SDimitry Andric   if (I && SourceFile == Function.Filenames[*I])
6940b57cec5SDimitry Andric     return I;
6950b57cec5SDimitry Andric   return None;
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric static bool isExpansion(const CountedRegion &R, unsigned FileID) {
6990b57cec5SDimitry Andric   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
7000b57cec5SDimitry Andric }
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
7030b57cec5SDimitry Andric   CoverageData FileCoverage(Filename);
7040b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
7050b57cec5SDimitry Andric 
7068bcb0991SDimitry Andric   // Look up the function records in the given file. Due to hash collisions on
7078bcb0991SDimitry Andric   // the filename, we may get back some records that are not in the file.
7088bcb0991SDimitry Andric   ArrayRef<unsigned> RecordIndices =
7098bcb0991SDimitry Andric       getImpreciseRecordIndicesForFilename(Filename);
7108bcb0991SDimitry Andric   for (unsigned RecordIndex : RecordIndices) {
7118bcb0991SDimitry Andric     const FunctionRecord &Function = Functions[RecordIndex];
7120b57cec5SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
7130b57cec5SDimitry Andric     auto FileIDs = gatherFileIDs(Filename, Function);
7140b57cec5SDimitry Andric     for (const auto &CR : Function.CountedRegions)
7150b57cec5SDimitry Andric       if (FileIDs.test(CR.FileID)) {
7160b57cec5SDimitry Andric         Regions.push_back(CR);
7170b57cec5SDimitry Andric         if (MainFileID && isExpansion(CR, *MainFileID))
7180b57cec5SDimitry Andric           FileCoverage.Expansions.emplace_back(CR, Function);
7190b57cec5SDimitry Andric       }
720e8d8bef9SDimitry Andric     // Capture branch regions specific to the function (excluding expansions).
721e8d8bef9SDimitry Andric     for (const auto &CR : Function.CountedBranchRegions)
722e8d8bef9SDimitry Andric       if (FileIDs.test(CR.FileID) && (CR.FileID == CR.ExpandedFileID))
723e8d8bef9SDimitry Andric         FileCoverage.BranchRegions.push_back(CR);
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
7270b57cec5SDimitry Andric   FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   return FileCoverage;
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric std::vector<InstantiationGroup>
7330b57cec5SDimitry Andric CoverageMapping::getInstantiationGroups(StringRef Filename) const {
7340b57cec5SDimitry Andric   FunctionInstantiationSetCollector InstantiationSetCollector;
7358bcb0991SDimitry Andric   // Look up the function records in the given file. Due to hash collisions on
7368bcb0991SDimitry Andric   // the filename, we may get back some records that are not in the file.
7378bcb0991SDimitry Andric   ArrayRef<unsigned> RecordIndices =
7388bcb0991SDimitry Andric       getImpreciseRecordIndicesForFilename(Filename);
7398bcb0991SDimitry Andric   for (unsigned RecordIndex : RecordIndices) {
7408bcb0991SDimitry Andric     const FunctionRecord &Function = Functions[RecordIndex];
7410b57cec5SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
7420b57cec5SDimitry Andric     if (!MainFileID)
7430b57cec5SDimitry Andric       continue;
7440b57cec5SDimitry Andric     InstantiationSetCollector.insert(Function, *MainFileID);
7450b57cec5SDimitry Andric   }
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   std::vector<InstantiationGroup> Result;
7480b57cec5SDimitry Andric   for (auto &InstantiationSet : InstantiationSetCollector) {
7490b57cec5SDimitry Andric     InstantiationGroup IG{InstantiationSet.first.first,
7500b57cec5SDimitry Andric                           InstantiationSet.first.second,
7510b57cec5SDimitry Andric                           std::move(InstantiationSet.second)};
7520b57cec5SDimitry Andric     Result.emplace_back(std::move(IG));
7530b57cec5SDimitry Andric   }
7540b57cec5SDimitry Andric   return Result;
7550b57cec5SDimitry Andric }
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric CoverageData
7580b57cec5SDimitry Andric CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
7590b57cec5SDimitry Andric   auto MainFileID = findMainViewFileID(Function);
7600b57cec5SDimitry Andric   if (!MainFileID)
7610b57cec5SDimitry Andric     return CoverageData();
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
7640b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
7650b57cec5SDimitry Andric   for (const auto &CR : Function.CountedRegions)
7660b57cec5SDimitry Andric     if (CR.FileID == *MainFileID) {
7670b57cec5SDimitry Andric       Regions.push_back(CR);
7680b57cec5SDimitry Andric       if (isExpansion(CR, *MainFileID))
7690b57cec5SDimitry Andric         FunctionCoverage.Expansions.emplace_back(CR, Function);
7700b57cec5SDimitry Andric     }
771e8d8bef9SDimitry Andric   // Capture branch regions specific to the function (excluding expansions).
772e8d8bef9SDimitry Andric   for (const auto &CR : Function.CountedBranchRegions)
773e8d8bef9SDimitry Andric     if (CR.FileID == *MainFileID)
774e8d8bef9SDimitry Andric       FunctionCoverage.BranchRegions.push_back(CR);
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
7770b57cec5SDimitry Andric                     << "\n");
7780b57cec5SDimitry Andric   FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   return FunctionCoverage;
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric CoverageData CoverageMapping::getCoverageForExpansion(
7840b57cec5SDimitry Andric     const ExpansionRecord &Expansion) const {
7850b57cec5SDimitry Andric   CoverageData ExpansionCoverage(
7860b57cec5SDimitry Andric       Expansion.Function.Filenames[Expansion.FileID]);
7870b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
7880b57cec5SDimitry Andric   for (const auto &CR : Expansion.Function.CountedRegions)
7890b57cec5SDimitry Andric     if (CR.FileID == Expansion.FileID) {
7900b57cec5SDimitry Andric       Regions.push_back(CR);
7910b57cec5SDimitry Andric       if (isExpansion(CR, Expansion.FileID))
7920b57cec5SDimitry Andric         ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
7930b57cec5SDimitry Andric     }
794e8d8bef9SDimitry Andric   for (const auto &CR : Expansion.Function.CountedBranchRegions)
795e8d8bef9SDimitry Andric     // Capture branch regions that only pertain to the corresponding expansion.
796e8d8bef9SDimitry Andric     if (CR.FileID == Expansion.FileID)
797e8d8bef9SDimitry Andric       ExpansionCoverage.BranchRegions.push_back(CR);
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
8000b57cec5SDimitry Andric                     << Expansion.FileID << "\n");
8010b57cec5SDimitry Andric   ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   return ExpansionCoverage;
8040b57cec5SDimitry Andric }
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric LineCoverageStats::LineCoverageStats(
8070b57cec5SDimitry Andric     ArrayRef<const CoverageSegment *> LineSegments,
8080b57cec5SDimitry Andric     const CoverageSegment *WrappedSegment, unsigned Line)
8090b57cec5SDimitry Andric     : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
8100b57cec5SDimitry Andric       LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
8110b57cec5SDimitry Andric   // Find the minimum number of regions which start in this line.
8120b57cec5SDimitry Andric   unsigned MinRegionCount = 0;
8130b57cec5SDimitry Andric   auto isStartOfRegion = [](const CoverageSegment *S) {
8140b57cec5SDimitry Andric     return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
8150b57cec5SDimitry Andric   };
8160b57cec5SDimitry Andric   for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
8170b57cec5SDimitry Andric     if (isStartOfRegion(LineSegments[I]))
8180b57cec5SDimitry Andric       ++MinRegionCount;
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric   bool StartOfSkippedRegion = !LineSegments.empty() &&
8210b57cec5SDimitry Andric                               !LineSegments.front()->HasCount &&
8220b57cec5SDimitry Andric                               LineSegments.front()->IsRegionEntry;
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   HasMultipleRegions = MinRegionCount > 1;
8250b57cec5SDimitry Andric   Mapped =
8260b57cec5SDimitry Andric       !StartOfSkippedRegion &&
8270b57cec5SDimitry Andric       ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric   if (!Mapped)
8300b57cec5SDimitry Andric     return;
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   // Pick the max count from the non-gap, region entry segments and the
8330b57cec5SDimitry Andric   // wrapped count.
8340b57cec5SDimitry Andric   if (WrappedSegment)
8350b57cec5SDimitry Andric     ExecutionCount = WrappedSegment->Count;
8360b57cec5SDimitry Andric   if (!MinRegionCount)
8370b57cec5SDimitry Andric     return;
8380b57cec5SDimitry Andric   for (const auto *LS : LineSegments)
8390b57cec5SDimitry Andric     if (isStartOfRegion(LS))
8400b57cec5SDimitry Andric       ExecutionCount = std::max(ExecutionCount, LS->Count);
8410b57cec5SDimitry Andric }
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric LineCoverageIterator &LineCoverageIterator::operator++() {
8440b57cec5SDimitry Andric   if (Next == CD.end()) {
8450b57cec5SDimitry Andric     Stats = LineCoverageStats();
8460b57cec5SDimitry Andric     Ended = true;
8470b57cec5SDimitry Andric     return *this;
8480b57cec5SDimitry Andric   }
8490b57cec5SDimitry Andric   if (Segments.size())
8500b57cec5SDimitry Andric     WrappedSegment = Segments.back();
8510b57cec5SDimitry Andric   Segments.clear();
8520b57cec5SDimitry Andric   while (Next != CD.end() && Next->Line == Line)
8530b57cec5SDimitry Andric     Segments.push_back(&*Next++);
8540b57cec5SDimitry Andric   Stats = LineCoverageStats(Segments, WrappedSegment, Line);
8550b57cec5SDimitry Andric   ++Line;
8560b57cec5SDimitry Andric   return *this;
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric static std::string getCoverageMapErrString(coveragemap_error Err) {
8600b57cec5SDimitry Andric   switch (Err) {
8610b57cec5SDimitry Andric   case coveragemap_error::success:
8620b57cec5SDimitry Andric     return "Success";
8630b57cec5SDimitry Andric   case coveragemap_error::eof:
8640b57cec5SDimitry Andric     return "End of File";
8650b57cec5SDimitry Andric   case coveragemap_error::no_data_found:
8660b57cec5SDimitry Andric     return "No coverage data found";
8670b57cec5SDimitry Andric   case coveragemap_error::unsupported_version:
8680b57cec5SDimitry Andric     return "Unsupported coverage format version";
8690b57cec5SDimitry Andric   case coveragemap_error::truncated:
8700b57cec5SDimitry Andric     return "Truncated coverage data";
8710b57cec5SDimitry Andric   case coveragemap_error::malformed:
8720b57cec5SDimitry Andric     return "Malformed coverage data";
8735ffd83dbSDimitry Andric   case coveragemap_error::decompression_failed:
8745ffd83dbSDimitry Andric     return "Failed to decompress coverage data (zlib)";
875e8d8bef9SDimitry Andric   case coveragemap_error::invalid_or_missing_arch_specifier:
876e8d8bef9SDimitry Andric     return "`-arch` specifier is invalid or missing for universal binary";
8770b57cec5SDimitry Andric   }
8780b57cec5SDimitry Andric   llvm_unreachable("A value of coveragemap_error has no message.");
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric namespace {
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It
8840b57cec5SDimitry Andric // will be removed once this transition is complete. Clients should prefer to
8850b57cec5SDimitry Andric // deal with the Error value directly, rather than converting to error_code.
8860b57cec5SDimitry Andric class CoverageMappingErrorCategoryType : public std::error_category {
8870b57cec5SDimitry Andric   const char *name() const noexcept override { return "llvm.coveragemap"; }
8880b57cec5SDimitry Andric   std::string message(int IE) const override {
8890b57cec5SDimitry Andric     return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
8900b57cec5SDimitry Andric   }
8910b57cec5SDimitry Andric };
8920b57cec5SDimitry Andric 
8930b57cec5SDimitry Andric } // end anonymous namespace
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric std::string CoverageMapError::message() const {
8960b57cec5SDimitry Andric   return getCoverageMapErrString(Err);
8970b57cec5SDimitry Andric }
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric const std::error_category &llvm::coverage::coveragemap_category() {
900*753f127fSDimitry Andric   static CoverageMappingErrorCategoryType ErrorCategory;
901*753f127fSDimitry Andric   return ErrorCategory;
9020b57cec5SDimitry Andric }
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric char CoverageMapError::ID = 0;
905