xref: /freebsd/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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 
189*fe6060f1SDimitry Andric unsigned CounterMappingContext::getMaxCounterID(const Counter &C) const {
190*fe6060f1SDimitry Andric   switch (C.getKind()) {
191*fe6060f1SDimitry Andric   case Counter::Zero:
192*fe6060f1SDimitry Andric     return 0;
193*fe6060f1SDimitry Andric   case Counter::CounterValueReference:
194*fe6060f1SDimitry Andric     return C.getCounterID();
195*fe6060f1SDimitry Andric   case Counter::Expression: {
196*fe6060f1SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
197*fe6060f1SDimitry Andric       return 0;
198*fe6060f1SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
199*fe6060f1SDimitry Andric     return std::max(getMaxCounterID(E.LHS), getMaxCounterID(E.RHS));
200*fe6060f1SDimitry Andric   }
201*fe6060f1SDimitry Andric   }
202*fe6060f1SDimitry Andric   llvm_unreachable("Unhandled CounterKind");
203*fe6060f1SDimitry Andric }
204*fe6060f1SDimitry Andric 
2050b57cec5SDimitry Andric void FunctionRecordIterator::skipOtherFiles() {
2060b57cec5SDimitry Andric   while (Current != Records.end() && !Filename.empty() &&
2070b57cec5SDimitry Andric          Filename != Current->Filenames[0])
2080b57cec5SDimitry Andric     ++Current;
2090b57cec5SDimitry Andric   if (Current == Records.end())
2100b57cec5SDimitry Andric     *this = FunctionRecordIterator();
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
2138bcb0991SDimitry Andric ArrayRef<unsigned> CoverageMapping::getImpreciseRecordIndicesForFilename(
2148bcb0991SDimitry Andric     StringRef Filename) const {
2158bcb0991SDimitry Andric   size_t FilenameHash = hash_value(Filename);
2168bcb0991SDimitry Andric   auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
2178bcb0991SDimitry Andric   if (RecordIt == FilenameHash2RecordIndices.end())
2188bcb0991SDimitry Andric     return {};
2198bcb0991SDimitry Andric   return RecordIt->second;
2208bcb0991SDimitry Andric }
2218bcb0991SDimitry Andric 
222*fe6060f1SDimitry Andric static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
223*fe6060f1SDimitry Andric                                 const CoverageMappingRecord &Record) {
224*fe6060f1SDimitry Andric   unsigned MaxCounterID = 0;
225*fe6060f1SDimitry Andric   for (const auto &Region : Record.MappingRegions) {
226*fe6060f1SDimitry Andric     MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count));
227*fe6060f1SDimitry Andric   }
228*fe6060f1SDimitry Andric   return MaxCounterID;
229*fe6060f1SDimitry Andric }
230*fe6060f1SDimitry Andric 
2310b57cec5SDimitry Andric Error CoverageMapping::loadFunctionRecord(
2320b57cec5SDimitry Andric     const CoverageMappingRecord &Record,
2330b57cec5SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
2340b57cec5SDimitry Andric   StringRef OrigFuncName = Record.FunctionName;
2350b57cec5SDimitry Andric   if (OrigFuncName.empty())
2360b57cec5SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   if (Record.Filenames.empty())
2390b57cec5SDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
2400b57cec5SDimitry Andric   else
2410b57cec5SDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   CounterMappingContext Ctx(Record.Expressions);
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   std::vector<uint64_t> Counts;
2460b57cec5SDimitry Andric   if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName,
2470b57cec5SDimitry Andric                                                 Record.FunctionHash, Counts)) {
2480b57cec5SDimitry Andric     instrprof_error IPE = InstrProfError::take(std::move(E));
2490b57cec5SDimitry Andric     if (IPE == instrprof_error::hash_mismatch) {
2505ffd83dbSDimitry Andric       FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
2515ffd83dbSDimitry Andric                                       Record.FunctionHash);
2520b57cec5SDimitry Andric       return Error::success();
2530b57cec5SDimitry Andric     } else if (IPE != instrprof_error::unknown_function)
2540b57cec5SDimitry Andric       return make_error<InstrProfError>(IPE);
255*fe6060f1SDimitry Andric     Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric   Ctx.setCounts(Counts);
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   assert(!Record.MappingRegions.empty() && "Function has no regions");
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   // This coverage record is a zero region for a function that's unused in
2620b57cec5SDimitry Andric   // some TU, but used in a different TU. Ignore it. The coverage maps from the
2630b57cec5SDimitry Andric   // the other TU will either be loaded (providing full region counts) or they
2640b57cec5SDimitry Andric   // won't (in which case we don't unintuitively report functions as uncovered
2650b57cec5SDimitry Andric   // when they have non-zero counts in the profile).
2660b57cec5SDimitry Andric   if (Record.MappingRegions.size() == 1 &&
2670b57cec5SDimitry Andric       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
2680b57cec5SDimitry Andric     return Error::success();
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   FunctionRecord Function(OrigFuncName, Record.Filenames);
2710b57cec5SDimitry Andric   for (const auto &Region : Record.MappingRegions) {
2720b57cec5SDimitry Andric     Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
2730b57cec5SDimitry Andric     if (auto E = ExecutionCount.takeError()) {
2740b57cec5SDimitry Andric       consumeError(std::move(E));
2750b57cec5SDimitry Andric       return Error::success();
2760b57cec5SDimitry Andric     }
277e8d8bef9SDimitry Andric     Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
278e8d8bef9SDimitry Andric     if (auto E = AltExecutionCount.takeError()) {
279e8d8bef9SDimitry Andric       consumeError(std::move(E));
280e8d8bef9SDimitry Andric       return Error::success();
281e8d8bef9SDimitry Andric     }
282e8d8bef9SDimitry Andric     Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
2830b57cec5SDimitry Andric   }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   // Don't create records for (filenames, function) pairs we've already seen.
2860b57cec5SDimitry Andric   auto FilenamesHash = hash_combine_range(Record.Filenames.begin(),
2870b57cec5SDimitry Andric                                           Record.Filenames.end());
2880b57cec5SDimitry Andric   if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
2890b57cec5SDimitry Andric     return Error::success();
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   Functions.push_back(std::move(Function));
2928bcb0991SDimitry Andric 
2938bcb0991SDimitry Andric   // Performance optimization: keep track of the indices of the function records
2948bcb0991SDimitry Andric   // which correspond to each filename. This can be used to substantially speed
2958bcb0991SDimitry Andric   // up queries for coverage info in a file.
2968bcb0991SDimitry Andric   unsigned RecordIndex = Functions.size() - 1;
2978bcb0991SDimitry Andric   for (StringRef Filename : Record.Filenames) {
2988bcb0991SDimitry Andric     auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
2998bcb0991SDimitry Andric     // Note that there may be duplicates in the filename set for a function
3008bcb0991SDimitry Andric     // record, because of e.g. macro expansions in the function in which both
3018bcb0991SDimitry Andric     // the macro and the function are defined in the same file.
3028bcb0991SDimitry Andric     if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
3038bcb0991SDimitry Andric       RecordIndices.push_back(RecordIndex);
3048bcb0991SDimitry Andric   }
3058bcb0991SDimitry Andric 
3060b57cec5SDimitry Andric   return Error::success();
3070b57cec5SDimitry Andric }
3080b57cec5SDimitry Andric 
309*fe6060f1SDimitry Andric // This function is for memory optimization by shortening the lifetimes
310*fe6060f1SDimitry Andric // of CoverageMappingReader instances.
311*fe6060f1SDimitry Andric Error CoverageMapping::loadFromReaders(
312*fe6060f1SDimitry Andric     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
313*fe6060f1SDimitry Andric     IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage) {
314*fe6060f1SDimitry Andric   for (const auto &CoverageReader : CoverageReaders) {
315*fe6060f1SDimitry Andric     for (auto RecordOrErr : *CoverageReader) {
316*fe6060f1SDimitry Andric       if (Error E = RecordOrErr.takeError())
317*fe6060f1SDimitry Andric         return E;
318*fe6060f1SDimitry Andric       const auto &Record = *RecordOrErr;
319*fe6060f1SDimitry Andric       if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader))
320*fe6060f1SDimitry Andric         return E;
321*fe6060f1SDimitry Andric     }
322*fe6060f1SDimitry Andric   }
323*fe6060f1SDimitry Andric   return Error::success();
324*fe6060f1SDimitry Andric }
325*fe6060f1SDimitry Andric 
3260b57cec5SDimitry Andric Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
3270b57cec5SDimitry Andric     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
3280b57cec5SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
3290b57cec5SDimitry Andric   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
330*fe6060f1SDimitry Andric   if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
3310b57cec5SDimitry Andric     return std::move(E);
3320b57cec5SDimitry Andric   return std::move(Coverage);
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
3358bcb0991SDimitry Andric // If E is a no_data_found error, returns success. Otherwise returns E.
3368bcb0991SDimitry Andric static Error handleMaybeNoDataFoundError(Error E) {
3378bcb0991SDimitry Andric   return handleErrors(
3388bcb0991SDimitry Andric       std::move(E), [](const CoverageMapError &CME) {
3398bcb0991SDimitry Andric         if (CME.get() == coveragemap_error::no_data_found)
3408bcb0991SDimitry Andric           return static_cast<Error>(Error::success());
3418bcb0991SDimitry Andric         return make_error<CoverageMapError>(CME.get());
3428bcb0991SDimitry Andric       });
3438bcb0991SDimitry Andric }
3448bcb0991SDimitry Andric 
3450b57cec5SDimitry Andric Expected<std::unique_ptr<CoverageMapping>>
3460b57cec5SDimitry Andric CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
347*fe6060f1SDimitry Andric                       StringRef ProfileFilename, ArrayRef<StringRef> Arches,
348*fe6060f1SDimitry Andric                       StringRef CompilationDir) {
3490b57cec5SDimitry Andric   auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
3500b57cec5SDimitry Andric   if (Error E = ProfileReaderOrErr.takeError())
3510b57cec5SDimitry Andric     return std::move(E);
3520b57cec5SDimitry Andric   auto ProfileReader = std::move(ProfileReaderOrErr.get());
353*fe6060f1SDimitry Andric   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
354*fe6060f1SDimitry Andric   bool DataFound = false;
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
357*fe6060f1SDimitry Andric     auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(
358*fe6060f1SDimitry Andric         File.value(), /*IsText=*/false, /*RequiresNullTerminator=*/false);
3590b57cec5SDimitry Andric     if (std::error_code EC = CovMappingBufOrErr.getError())
3600b57cec5SDimitry Andric       return errorCodeToError(EC);
3610b57cec5SDimitry Andric     StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()];
3620b57cec5SDimitry Andric     MemoryBufferRef CovMappingBufRef =
3630b57cec5SDimitry Andric         CovMappingBufOrErr.get()->getMemBufferRef();
364*fe6060f1SDimitry Andric     SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
365*fe6060f1SDimitry Andric     auto CoverageReadersOrErr = BinaryCoverageReader::create(
366*fe6060f1SDimitry Andric         CovMappingBufRef, Arch, Buffers, CompilationDir);
3678bcb0991SDimitry Andric     if (Error E = CoverageReadersOrErr.takeError()) {
3688bcb0991SDimitry Andric       E = handleMaybeNoDataFoundError(std::move(E));
3698bcb0991SDimitry Andric       if (E)
3700b57cec5SDimitry Andric         return std::move(E);
3718bcb0991SDimitry Andric       // E == success (originally a no_data_found error).
3728bcb0991SDimitry Andric       continue;
3738bcb0991SDimitry Andric     }
374*fe6060f1SDimitry Andric 
375*fe6060f1SDimitry Andric     SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers;
3760b57cec5SDimitry Andric     for (auto &Reader : CoverageReadersOrErr.get())
3770b57cec5SDimitry Andric       Readers.push_back(std::move(Reader));
378*fe6060f1SDimitry Andric     DataFound |= !Readers.empty();
379*fe6060f1SDimitry Andric     if (Error E = loadFromReaders(Readers, *ProfileReader, *Coverage))
380*fe6060f1SDimitry Andric       return std::move(E);
3810b57cec5SDimitry Andric   }
3828bcb0991SDimitry Andric   // If no readers were created, either no objects were provided or none of them
3838bcb0991SDimitry Andric   // had coverage data. Return an error in the latter case.
384*fe6060f1SDimitry Andric   if (!DataFound && !ObjectFilenames.empty())
3858bcb0991SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
386*fe6060f1SDimitry Andric   return std::move(Coverage);
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric namespace {
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric /// Distributes functions into instantiation sets.
3920b57cec5SDimitry Andric ///
3930b57cec5SDimitry Andric /// An instantiation set is a collection of functions that have the same source
3940b57cec5SDimitry Andric /// code, ie, template functions specializations.
3950b57cec5SDimitry Andric class FunctionInstantiationSetCollector {
3960b57cec5SDimitry Andric   using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
3970b57cec5SDimitry Andric   MapT InstantiatedFunctions;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric public:
4000b57cec5SDimitry Andric   void insert(const FunctionRecord &Function, unsigned FileID) {
4010b57cec5SDimitry Andric     auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
4020b57cec5SDimitry Andric     while (I != E && I->FileID != FileID)
4030b57cec5SDimitry Andric       ++I;
4040b57cec5SDimitry Andric     assert(I != E && "function does not cover the given file");
4050b57cec5SDimitry Andric     auto &Functions = InstantiatedFunctions[I->startLoc()];
4060b57cec5SDimitry Andric     Functions.push_back(&Function);
4070b57cec5SDimitry Andric   }
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   MapT::iterator begin() { return InstantiatedFunctions.begin(); }
4100b57cec5SDimitry Andric   MapT::iterator end() { return InstantiatedFunctions.end(); }
4110b57cec5SDimitry Andric };
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric class SegmentBuilder {
4140b57cec5SDimitry Andric   std::vector<CoverageSegment> &Segments;
4150b57cec5SDimitry Andric   SmallVector<const CountedRegion *, 8> ActiveRegions;
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   /// Emit a segment with the count from \p Region starting at \p StartLoc.
4200b57cec5SDimitry Andric   //
4210b57cec5SDimitry Andric   /// \p IsRegionEntry: The segment is at the start of a new non-gap region.
4220b57cec5SDimitry Andric   /// \p EmitSkippedRegion: The segment must be emitted as a skipped region.
4230b57cec5SDimitry Andric   void startSegment(const CountedRegion &Region, LineColPair StartLoc,
4240b57cec5SDimitry Andric                     bool IsRegionEntry, bool EmitSkippedRegion = false) {
4250b57cec5SDimitry Andric     bool HasCount = !EmitSkippedRegion &&
4260b57cec5SDimitry Andric                     (Region.Kind != CounterMappingRegion::SkippedRegion);
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric     // If the new segment wouldn't affect coverage rendering, skip it.
4290b57cec5SDimitry Andric     if (!Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
4300b57cec5SDimitry Andric       const auto &Last = Segments.back();
4310b57cec5SDimitry Andric       if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount &&
4320b57cec5SDimitry Andric           !Last.IsRegionEntry)
4330b57cec5SDimitry Andric         return;
4340b57cec5SDimitry Andric     }
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric     if (HasCount)
4370b57cec5SDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second,
4380b57cec5SDimitry Andric                             Region.ExecutionCount, IsRegionEntry,
4390b57cec5SDimitry Andric                             Region.Kind == CounterMappingRegion::GapRegion);
4400b57cec5SDimitry Andric     else
4410b57cec5SDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric     LLVM_DEBUG({
4440b57cec5SDimitry Andric       const auto &Last = Segments.back();
4450b57cec5SDimitry Andric       dbgs() << "Segment at " << Last.Line << ":" << Last.Col
4460b57cec5SDimitry Andric              << " (count = " << Last.Count << ")"
4470b57cec5SDimitry Andric              << (Last.IsRegionEntry ? ", RegionEntry" : "")
4480b57cec5SDimitry Andric              << (!Last.HasCount ? ", Skipped" : "")
4490b57cec5SDimitry Andric              << (Last.IsGapRegion ? ", Gap" : "") << "\n";
4500b57cec5SDimitry Andric     });
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   /// Emit segments for active regions which end before \p Loc.
4540b57cec5SDimitry Andric   ///
4550b57cec5SDimitry Andric   /// \p Loc: The start location of the next region. If None, all active
4560b57cec5SDimitry Andric   /// regions are completed.
4570b57cec5SDimitry Andric   /// \p FirstCompletedRegion: Index of the first completed region.
4580b57cec5SDimitry Andric   void completeRegionsUntil(Optional<LineColPair> Loc,
4590b57cec5SDimitry Andric                             unsigned FirstCompletedRegion) {
4600b57cec5SDimitry Andric     // Sort the completed regions by end location. This makes it simple to
4610b57cec5SDimitry Andric     // emit closing segments in sorted order.
4620b57cec5SDimitry Andric     auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;
4630b57cec5SDimitry Andric     std::stable_sort(CompletedRegionsIt, ActiveRegions.end(),
4640b57cec5SDimitry Andric                       [](const CountedRegion *L, const CountedRegion *R) {
4650b57cec5SDimitry Andric                         return L->endLoc() < R->endLoc();
4660b57cec5SDimitry Andric                       });
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric     // Emit segments for all completed regions.
4690b57cec5SDimitry Andric     for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E;
4700b57cec5SDimitry Andric          ++I) {
4710b57cec5SDimitry Andric       const auto *CompletedRegion = ActiveRegions[I];
4720b57cec5SDimitry Andric       assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
4730b57cec5SDimitry Andric              "Completed region ends after start of new region");
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric       const auto *PrevCompletedRegion = ActiveRegions[I - 1];
4760b57cec5SDimitry Andric       auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric       // Don't emit any more segments if they start where the new region begins.
4790b57cec5SDimitry Andric       if (Loc && CompletedSegmentLoc == *Loc)
4800b57cec5SDimitry Andric         break;
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric       // Don't emit a segment if the next completed region ends at the same
4830b57cec5SDimitry Andric       // location as this one.
4840b57cec5SDimitry Andric       if (CompletedSegmentLoc == CompletedRegion->endLoc())
4850b57cec5SDimitry Andric         continue;
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric       // Use the count from the last completed region which ends at this loc.
4880b57cec5SDimitry Andric       for (unsigned J = I + 1; J < E; ++J)
4890b57cec5SDimitry Andric         if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
4900b57cec5SDimitry Andric           CompletedRegion = ActiveRegions[J];
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric       startSegment(*CompletedRegion, CompletedSegmentLoc, false);
4930b57cec5SDimitry Andric     }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric     auto Last = ActiveRegions.back();
4960b57cec5SDimitry Andric     if (FirstCompletedRegion && Last->endLoc() != *Loc) {
4970b57cec5SDimitry Andric       // If there's a gap after the end of the last completed region and the
4980b57cec5SDimitry Andric       // start of the new region, use the last active region to fill the gap.
4990b57cec5SDimitry Andric       startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(),
5000b57cec5SDimitry Andric                    false);
5010b57cec5SDimitry Andric     } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) {
5020b57cec5SDimitry Andric       // Emit a skipped segment if there are no more active regions. This
5030b57cec5SDimitry Andric       // ensures that gaps between functions are marked correctly.
5040b57cec5SDimitry Andric       startSegment(*Last, Last->endLoc(), false, true);
5050b57cec5SDimitry Andric     }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric     // Pop the completed regions.
5080b57cec5SDimitry Andric     ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end());
5090b57cec5SDimitry Andric   }
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
5120b57cec5SDimitry Andric     for (const auto &CR : enumerate(Regions)) {
5130b57cec5SDimitry Andric       auto CurStartLoc = CR.value().startLoc();
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric       // Active regions which end before the current region need to be popped.
5160b57cec5SDimitry Andric       auto CompletedRegions =
5170b57cec5SDimitry Andric           std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),
5180b57cec5SDimitry Andric                                 [&](const CountedRegion *Region) {
5190b57cec5SDimitry Andric                                   return !(Region->endLoc() <= CurStartLoc);
5200b57cec5SDimitry Andric                                 });
5210b57cec5SDimitry Andric       if (CompletedRegions != ActiveRegions.end()) {
5220b57cec5SDimitry Andric         unsigned FirstCompletedRegion =
5230b57cec5SDimitry Andric             std::distance(ActiveRegions.begin(), CompletedRegions);
5240b57cec5SDimitry Andric         completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
5250b57cec5SDimitry Andric       }
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric       bool GapRegion = CR.value().Kind == CounterMappingRegion::GapRegion;
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric       // Try to emit a segment for the current region.
5300b57cec5SDimitry Andric       if (CurStartLoc == CR.value().endLoc()) {
5310b57cec5SDimitry Andric         // Avoid making zero-length regions active. If it's the last region,
5320b57cec5SDimitry Andric         // emit a skipped segment. Otherwise use its predecessor's count.
533e8d8bef9SDimitry Andric         const bool Skipped =
534e8d8bef9SDimitry Andric             (CR.index() + 1) == Regions.size() ||
535e8d8bef9SDimitry Andric             CR.value().Kind == CounterMappingRegion::SkippedRegion;
5360b57cec5SDimitry Andric         startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),
5370b57cec5SDimitry Andric                      CurStartLoc, !GapRegion, Skipped);
538e8d8bef9SDimitry Andric         // If it is skipped segment, create a segment with last pushed
539e8d8bef9SDimitry Andric         // regions's count at CurStartLoc.
540e8d8bef9SDimitry Andric         if (Skipped && !ActiveRegions.empty())
541e8d8bef9SDimitry Andric           startSegment(*ActiveRegions.back(), CurStartLoc, false);
5420b57cec5SDimitry Andric         continue;
5430b57cec5SDimitry Andric       }
5440b57cec5SDimitry Andric       if (CR.index() + 1 == Regions.size() ||
5450b57cec5SDimitry Andric           CurStartLoc != Regions[CR.index() + 1].startLoc()) {
5460b57cec5SDimitry Andric         // Emit a segment if the next region doesn't start at the same location
5470b57cec5SDimitry Andric         // as this one.
5480b57cec5SDimitry Andric         startSegment(CR.value(), CurStartLoc, !GapRegion);
5490b57cec5SDimitry Andric       }
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric       // This region is active (i.e not completed).
5520b57cec5SDimitry Andric       ActiveRegions.push_back(&CR.value());
5530b57cec5SDimitry Andric     }
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric     // Complete any remaining active regions.
5560b57cec5SDimitry Andric     if (!ActiveRegions.empty())
5570b57cec5SDimitry Andric       completeRegionsUntil(None, 0);
5580b57cec5SDimitry Andric   }
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   /// Sort a nested sequence of regions from a single file.
5610b57cec5SDimitry Andric   static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
5620b57cec5SDimitry Andric     llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) {
5630b57cec5SDimitry Andric       if (LHS.startLoc() != RHS.startLoc())
5640b57cec5SDimitry Andric         return LHS.startLoc() < RHS.startLoc();
5650b57cec5SDimitry Andric       if (LHS.endLoc() != RHS.endLoc())
5660b57cec5SDimitry Andric         // When LHS completely contains RHS, we sort LHS first.
5670b57cec5SDimitry Andric         return RHS.endLoc() < LHS.endLoc();
5680b57cec5SDimitry Andric       // If LHS and RHS cover the same area, we need to sort them according
5690b57cec5SDimitry Andric       // to their kinds so that the most suitable region will become "active"
5700b57cec5SDimitry Andric       // in combineRegions(). Because we accumulate counter values only from
5710b57cec5SDimitry Andric       // regions of the same kind as the first region of the area, prefer
5720b57cec5SDimitry Andric       // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
5730b57cec5SDimitry Andric       static_assert(CounterMappingRegion::CodeRegion <
5740b57cec5SDimitry Andric                             CounterMappingRegion::ExpansionRegion &&
5750b57cec5SDimitry Andric                         CounterMappingRegion::ExpansionRegion <
5760b57cec5SDimitry Andric                             CounterMappingRegion::SkippedRegion,
5770b57cec5SDimitry Andric                     "Unexpected order of region kind values");
5780b57cec5SDimitry Andric       return LHS.Kind < RHS.Kind;
5790b57cec5SDimitry Andric     });
5800b57cec5SDimitry Andric   }
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric   /// Combine counts of regions which cover the same area.
5830b57cec5SDimitry Andric   static ArrayRef<CountedRegion>
5840b57cec5SDimitry Andric   combineRegions(MutableArrayRef<CountedRegion> Regions) {
5850b57cec5SDimitry Andric     if (Regions.empty())
5860b57cec5SDimitry Andric       return Regions;
5870b57cec5SDimitry Andric     auto Active = Regions.begin();
5880b57cec5SDimitry Andric     auto End = Regions.end();
5890b57cec5SDimitry Andric     for (auto I = Regions.begin() + 1; I != End; ++I) {
5900b57cec5SDimitry Andric       if (Active->startLoc() != I->startLoc() ||
5910b57cec5SDimitry Andric           Active->endLoc() != I->endLoc()) {
5920b57cec5SDimitry Andric         // Shift to the next region.
5930b57cec5SDimitry Andric         ++Active;
5940b57cec5SDimitry Andric         if (Active != I)
5950b57cec5SDimitry Andric           *Active = *I;
5960b57cec5SDimitry Andric         continue;
5970b57cec5SDimitry Andric       }
5980b57cec5SDimitry Andric       // Merge duplicate region.
5990b57cec5SDimitry Andric       // If CodeRegions and ExpansionRegions cover the same area, it's probably
6000b57cec5SDimitry Andric       // a macro which is fully expanded to another macro. In that case, we need
6010b57cec5SDimitry Andric       // to accumulate counts only from CodeRegions, or else the area will be
6020b57cec5SDimitry Andric       // counted twice.
6030b57cec5SDimitry Andric       // On the other hand, a macro may have a nested macro in its body. If the
6040b57cec5SDimitry Andric       // outer macro is used several times, the ExpansionRegion for the nested
6050b57cec5SDimitry Andric       // macro will also be added several times. These ExpansionRegions cover
6060b57cec5SDimitry Andric       // the same source locations and have to be combined to reach the correct
6070b57cec5SDimitry Andric       // value for that area.
6080b57cec5SDimitry Andric       // We add counts of the regions of the same kind as the active region
6090b57cec5SDimitry Andric       // to handle the both situations.
6100b57cec5SDimitry Andric       if (I->Kind == Active->Kind)
6110b57cec5SDimitry Andric         Active->ExecutionCount += I->ExecutionCount;
6120b57cec5SDimitry Andric     }
6130b57cec5SDimitry Andric     return Regions.drop_back(std::distance(++Active, End));
6140b57cec5SDimitry Andric   }
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric public:
6170b57cec5SDimitry Andric   /// Build a sorted list of CoverageSegments from a list of Regions.
6180b57cec5SDimitry Andric   static std::vector<CoverageSegment>
6190b57cec5SDimitry Andric   buildSegments(MutableArrayRef<CountedRegion> Regions) {
6200b57cec5SDimitry Andric     std::vector<CoverageSegment> Segments;
6210b57cec5SDimitry Andric     SegmentBuilder Builder(Segments);
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric     sortNestedRegions(Regions);
6240b57cec5SDimitry Andric     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric     LLVM_DEBUG({
6270b57cec5SDimitry Andric       dbgs() << "Combined regions:\n";
6280b57cec5SDimitry Andric       for (const auto &CR : CombinedRegions)
6290b57cec5SDimitry Andric         dbgs() << "  " << CR.LineStart << ":" << CR.ColumnStart << " -> "
6300b57cec5SDimitry Andric                << CR.LineEnd << ":" << CR.ColumnEnd
6310b57cec5SDimitry Andric                << " (count=" << CR.ExecutionCount << ")\n";
6320b57cec5SDimitry Andric     });
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric     Builder.buildSegmentsImpl(CombinedRegions);
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric #ifndef NDEBUG
6370b57cec5SDimitry Andric     for (unsigned I = 1, E = Segments.size(); I < E; ++I) {
6380b57cec5SDimitry Andric       const auto &L = Segments[I - 1];
6390b57cec5SDimitry Andric       const auto &R = Segments[I];
6400b57cec5SDimitry Andric       if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) {
641e8d8bef9SDimitry Andric         if (L.Line == R.Line && L.Col == R.Col && !L.HasCount)
642e8d8bef9SDimitry Andric           continue;
6430b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col
6440b57cec5SDimitry Andric                           << " followed by " << R.Line << ":" << R.Col << "\n");
6450b57cec5SDimitry Andric         assert(false && "Coverage segments not unique or sorted");
6460b57cec5SDimitry Andric       }
6470b57cec5SDimitry Andric     }
6480b57cec5SDimitry Andric #endif
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric     return Segments;
6510b57cec5SDimitry Andric   }
6520b57cec5SDimitry Andric };
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric } // end anonymous namespace
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
6570b57cec5SDimitry Andric   std::vector<StringRef> Filenames;
6580b57cec5SDimitry Andric   for (const auto &Function : getCoveredFunctions())
659e8d8bef9SDimitry Andric     llvm::append_range(Filenames, Function.Filenames);
6600b57cec5SDimitry Andric   llvm::sort(Filenames);
6610b57cec5SDimitry Andric   auto Last = std::unique(Filenames.begin(), Filenames.end());
6620b57cec5SDimitry Andric   Filenames.erase(Last, Filenames.end());
6630b57cec5SDimitry Andric   return Filenames;
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric static SmallBitVector gatherFileIDs(StringRef SourceFile,
6670b57cec5SDimitry Andric                                     const FunctionRecord &Function) {
6680b57cec5SDimitry Andric   SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
6690b57cec5SDimitry Andric   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
6700b57cec5SDimitry Andric     if (SourceFile == Function.Filenames[I])
6710b57cec5SDimitry Andric       FilenameEquivalence[I] = true;
6720b57cec5SDimitry Andric   return FilenameEquivalence;
6730b57cec5SDimitry Andric }
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric /// Return the ID of the file where the definition of the function is located.
6760b57cec5SDimitry Andric static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
6770b57cec5SDimitry Andric   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
6780b57cec5SDimitry Andric   for (const auto &CR : Function.CountedRegions)
6790b57cec5SDimitry Andric     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
6800b57cec5SDimitry Andric       IsNotExpandedFile[CR.ExpandedFileID] = false;
6810b57cec5SDimitry Andric   int I = IsNotExpandedFile.find_first();
6820b57cec5SDimitry Andric   if (I == -1)
6830b57cec5SDimitry Andric     return None;
6840b57cec5SDimitry Andric   return I;
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric /// Check if SourceFile is the file that contains the definition of
6880b57cec5SDimitry Andric /// the Function. Return the ID of the file in that case or None otherwise.
6890b57cec5SDimitry Andric static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
6900b57cec5SDimitry Andric                                              const FunctionRecord &Function) {
6910b57cec5SDimitry Andric   Optional<unsigned> I = findMainViewFileID(Function);
6920b57cec5SDimitry Andric   if (I && SourceFile == Function.Filenames[*I])
6930b57cec5SDimitry Andric     return I;
6940b57cec5SDimitry Andric   return None;
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric static bool isExpansion(const CountedRegion &R, unsigned FileID) {
6980b57cec5SDimitry Andric   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
6990b57cec5SDimitry Andric }
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
7020b57cec5SDimitry Andric   CoverageData FileCoverage(Filename);
7030b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
7040b57cec5SDimitry Andric 
7058bcb0991SDimitry Andric   // Look up the function records in the given file. Due to hash collisions on
7068bcb0991SDimitry Andric   // the filename, we may get back some records that are not in the file.
7078bcb0991SDimitry Andric   ArrayRef<unsigned> RecordIndices =
7088bcb0991SDimitry Andric       getImpreciseRecordIndicesForFilename(Filename);
7098bcb0991SDimitry Andric   for (unsigned RecordIndex : RecordIndices) {
7108bcb0991SDimitry Andric     const FunctionRecord &Function = Functions[RecordIndex];
7110b57cec5SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
7120b57cec5SDimitry Andric     auto FileIDs = gatherFileIDs(Filename, Function);
7130b57cec5SDimitry Andric     for (const auto &CR : Function.CountedRegions)
7140b57cec5SDimitry Andric       if (FileIDs.test(CR.FileID)) {
7150b57cec5SDimitry Andric         Regions.push_back(CR);
7160b57cec5SDimitry Andric         if (MainFileID && isExpansion(CR, *MainFileID))
7170b57cec5SDimitry Andric           FileCoverage.Expansions.emplace_back(CR, Function);
7180b57cec5SDimitry Andric       }
719e8d8bef9SDimitry Andric     // Capture branch regions specific to the function (excluding expansions).
720e8d8bef9SDimitry Andric     for (const auto &CR : Function.CountedBranchRegions)
721e8d8bef9SDimitry Andric       if (FileIDs.test(CR.FileID) && (CR.FileID == CR.ExpandedFileID))
722e8d8bef9SDimitry Andric         FileCoverage.BranchRegions.push_back(CR);
7230b57cec5SDimitry Andric   }
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
7260b57cec5SDimitry Andric   FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric   return FileCoverage;
7290b57cec5SDimitry Andric }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric std::vector<InstantiationGroup>
7320b57cec5SDimitry Andric CoverageMapping::getInstantiationGroups(StringRef Filename) const {
7330b57cec5SDimitry Andric   FunctionInstantiationSetCollector InstantiationSetCollector;
7348bcb0991SDimitry Andric   // Look up the function records in the given file. Due to hash collisions on
7358bcb0991SDimitry Andric   // the filename, we may get back some records that are not in the file.
7368bcb0991SDimitry Andric   ArrayRef<unsigned> RecordIndices =
7378bcb0991SDimitry Andric       getImpreciseRecordIndicesForFilename(Filename);
7388bcb0991SDimitry Andric   for (unsigned RecordIndex : RecordIndices) {
7398bcb0991SDimitry Andric     const FunctionRecord &Function = Functions[RecordIndex];
7400b57cec5SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
7410b57cec5SDimitry Andric     if (!MainFileID)
7420b57cec5SDimitry Andric       continue;
7430b57cec5SDimitry Andric     InstantiationSetCollector.insert(Function, *MainFileID);
7440b57cec5SDimitry Andric   }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   std::vector<InstantiationGroup> Result;
7470b57cec5SDimitry Andric   for (auto &InstantiationSet : InstantiationSetCollector) {
7480b57cec5SDimitry Andric     InstantiationGroup IG{InstantiationSet.first.first,
7490b57cec5SDimitry Andric                           InstantiationSet.first.second,
7500b57cec5SDimitry Andric                           std::move(InstantiationSet.second)};
7510b57cec5SDimitry Andric     Result.emplace_back(std::move(IG));
7520b57cec5SDimitry Andric   }
7530b57cec5SDimitry Andric   return Result;
7540b57cec5SDimitry Andric }
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric CoverageData
7570b57cec5SDimitry Andric CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
7580b57cec5SDimitry Andric   auto MainFileID = findMainViewFileID(Function);
7590b57cec5SDimitry Andric   if (!MainFileID)
7600b57cec5SDimitry Andric     return CoverageData();
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
7630b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
7640b57cec5SDimitry Andric   for (const auto &CR : Function.CountedRegions)
7650b57cec5SDimitry Andric     if (CR.FileID == *MainFileID) {
7660b57cec5SDimitry Andric       Regions.push_back(CR);
7670b57cec5SDimitry Andric       if (isExpansion(CR, *MainFileID))
7680b57cec5SDimitry Andric         FunctionCoverage.Expansions.emplace_back(CR, Function);
7690b57cec5SDimitry Andric     }
770e8d8bef9SDimitry Andric   // Capture branch regions specific to the function (excluding expansions).
771e8d8bef9SDimitry Andric   for (const auto &CR : Function.CountedBranchRegions)
772e8d8bef9SDimitry Andric     if (CR.FileID == *MainFileID)
773e8d8bef9SDimitry Andric       FunctionCoverage.BranchRegions.push_back(CR);
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
7760b57cec5SDimitry Andric                     << "\n");
7770b57cec5SDimitry Andric   FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric   return FunctionCoverage;
7800b57cec5SDimitry Andric }
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric CoverageData CoverageMapping::getCoverageForExpansion(
7830b57cec5SDimitry Andric     const ExpansionRecord &Expansion) const {
7840b57cec5SDimitry Andric   CoverageData ExpansionCoverage(
7850b57cec5SDimitry Andric       Expansion.Function.Filenames[Expansion.FileID]);
7860b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
7870b57cec5SDimitry Andric   for (const auto &CR : Expansion.Function.CountedRegions)
7880b57cec5SDimitry Andric     if (CR.FileID == Expansion.FileID) {
7890b57cec5SDimitry Andric       Regions.push_back(CR);
7900b57cec5SDimitry Andric       if (isExpansion(CR, Expansion.FileID))
7910b57cec5SDimitry Andric         ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
7920b57cec5SDimitry Andric     }
793e8d8bef9SDimitry Andric   for (const auto &CR : Expansion.Function.CountedBranchRegions)
794e8d8bef9SDimitry Andric     // Capture branch regions that only pertain to the corresponding expansion.
795e8d8bef9SDimitry Andric     if (CR.FileID == Expansion.FileID)
796e8d8bef9SDimitry Andric       ExpansionCoverage.BranchRegions.push_back(CR);
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
7990b57cec5SDimitry Andric                     << Expansion.FileID << "\n");
8000b57cec5SDimitry Andric   ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   return ExpansionCoverage;
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric LineCoverageStats::LineCoverageStats(
8060b57cec5SDimitry Andric     ArrayRef<const CoverageSegment *> LineSegments,
8070b57cec5SDimitry Andric     const CoverageSegment *WrappedSegment, unsigned Line)
8080b57cec5SDimitry Andric     : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
8090b57cec5SDimitry Andric       LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
8100b57cec5SDimitry Andric   // Find the minimum number of regions which start in this line.
8110b57cec5SDimitry Andric   unsigned MinRegionCount = 0;
8120b57cec5SDimitry Andric   auto isStartOfRegion = [](const CoverageSegment *S) {
8130b57cec5SDimitry Andric     return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
8140b57cec5SDimitry Andric   };
8150b57cec5SDimitry Andric   for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
8160b57cec5SDimitry Andric     if (isStartOfRegion(LineSegments[I]))
8170b57cec5SDimitry Andric       ++MinRegionCount;
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   bool StartOfSkippedRegion = !LineSegments.empty() &&
8200b57cec5SDimitry Andric                               !LineSegments.front()->HasCount &&
8210b57cec5SDimitry Andric                               LineSegments.front()->IsRegionEntry;
8220b57cec5SDimitry Andric 
8230b57cec5SDimitry Andric   HasMultipleRegions = MinRegionCount > 1;
8240b57cec5SDimitry Andric   Mapped =
8250b57cec5SDimitry Andric       !StartOfSkippedRegion &&
8260b57cec5SDimitry Andric       ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric   if (!Mapped)
8290b57cec5SDimitry Andric     return;
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric   // Pick the max count from the non-gap, region entry segments and the
8320b57cec5SDimitry Andric   // wrapped count.
8330b57cec5SDimitry Andric   if (WrappedSegment)
8340b57cec5SDimitry Andric     ExecutionCount = WrappedSegment->Count;
8350b57cec5SDimitry Andric   if (!MinRegionCount)
8360b57cec5SDimitry Andric     return;
8370b57cec5SDimitry Andric   for (const auto *LS : LineSegments)
8380b57cec5SDimitry Andric     if (isStartOfRegion(LS))
8390b57cec5SDimitry Andric       ExecutionCount = std::max(ExecutionCount, LS->Count);
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric LineCoverageIterator &LineCoverageIterator::operator++() {
8430b57cec5SDimitry Andric   if (Next == CD.end()) {
8440b57cec5SDimitry Andric     Stats = LineCoverageStats();
8450b57cec5SDimitry Andric     Ended = true;
8460b57cec5SDimitry Andric     return *this;
8470b57cec5SDimitry Andric   }
8480b57cec5SDimitry Andric   if (Segments.size())
8490b57cec5SDimitry Andric     WrappedSegment = Segments.back();
8500b57cec5SDimitry Andric   Segments.clear();
8510b57cec5SDimitry Andric   while (Next != CD.end() && Next->Line == Line)
8520b57cec5SDimitry Andric     Segments.push_back(&*Next++);
8530b57cec5SDimitry Andric   Stats = LineCoverageStats(Segments, WrappedSegment, Line);
8540b57cec5SDimitry Andric   ++Line;
8550b57cec5SDimitry Andric   return *this;
8560b57cec5SDimitry Andric }
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric static std::string getCoverageMapErrString(coveragemap_error Err) {
8590b57cec5SDimitry Andric   switch (Err) {
8600b57cec5SDimitry Andric   case coveragemap_error::success:
8610b57cec5SDimitry Andric     return "Success";
8620b57cec5SDimitry Andric   case coveragemap_error::eof:
8630b57cec5SDimitry Andric     return "End of File";
8640b57cec5SDimitry Andric   case coveragemap_error::no_data_found:
8650b57cec5SDimitry Andric     return "No coverage data found";
8660b57cec5SDimitry Andric   case coveragemap_error::unsupported_version:
8670b57cec5SDimitry Andric     return "Unsupported coverage format version";
8680b57cec5SDimitry Andric   case coveragemap_error::truncated:
8690b57cec5SDimitry Andric     return "Truncated coverage data";
8700b57cec5SDimitry Andric   case coveragemap_error::malformed:
8710b57cec5SDimitry Andric     return "Malformed coverage data";
8725ffd83dbSDimitry Andric   case coveragemap_error::decompression_failed:
8735ffd83dbSDimitry Andric     return "Failed to decompress coverage data (zlib)";
874e8d8bef9SDimitry Andric   case coveragemap_error::invalid_or_missing_arch_specifier:
875e8d8bef9SDimitry Andric     return "`-arch` specifier is invalid or missing for universal binary";
8760b57cec5SDimitry Andric   }
8770b57cec5SDimitry Andric   llvm_unreachable("A value of coveragemap_error has no message.");
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric namespace {
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It
8830b57cec5SDimitry Andric // will be removed once this transition is complete. Clients should prefer to
8840b57cec5SDimitry Andric // deal with the Error value directly, rather than converting to error_code.
8850b57cec5SDimitry Andric class CoverageMappingErrorCategoryType : public std::error_category {
8860b57cec5SDimitry Andric   const char *name() const noexcept override { return "llvm.coveragemap"; }
8870b57cec5SDimitry Andric   std::string message(int IE) const override {
8880b57cec5SDimitry Andric     return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
8890b57cec5SDimitry Andric   }
8900b57cec5SDimitry Andric };
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric } // end anonymous namespace
8930b57cec5SDimitry Andric 
8940b57cec5SDimitry Andric std::string CoverageMapError::message() const {
8950b57cec5SDimitry Andric   return getCoverageMapErrString(Err);
8960b57cec5SDimitry Andric }
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric const std::error_category &llvm::coverage::coveragemap_category() {
9010b57cec5SDimitry Andric   return *ErrorCategory;
9020b57cec5SDimitry Andric }
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric char CoverageMapError::ID = 0;
905