xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===- CoverageMapping.cpp - Code coverage mapping support ----------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file contains support for clang's and llvm's instrumentation based
107330f729Sjoerg // code coverage.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg 
147330f729Sjoerg #include "llvm/ProfileData/Coverage/CoverageMapping.h"
157330f729Sjoerg #include "llvm/ADT/ArrayRef.h"
167330f729Sjoerg #include "llvm/ADT/DenseMap.h"
177330f729Sjoerg #include "llvm/ADT/None.h"
187330f729Sjoerg #include "llvm/ADT/Optional.h"
197330f729Sjoerg #include "llvm/ADT/SmallBitVector.h"
207330f729Sjoerg #include "llvm/ADT/SmallVector.h"
217330f729Sjoerg #include "llvm/ADT/StringRef.h"
227330f729Sjoerg #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
237330f729Sjoerg #include "llvm/ProfileData/InstrProfReader.h"
247330f729Sjoerg #include "llvm/Support/Debug.h"
257330f729Sjoerg #include "llvm/Support/Errc.h"
267330f729Sjoerg #include "llvm/Support/Error.h"
277330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
287330f729Sjoerg #include "llvm/Support/ManagedStatic.h"
297330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
307330f729Sjoerg #include "llvm/Support/raw_ostream.h"
317330f729Sjoerg #include <algorithm>
327330f729Sjoerg #include <cassert>
337330f729Sjoerg #include <cstdint>
347330f729Sjoerg #include <iterator>
357330f729Sjoerg #include <map>
367330f729Sjoerg #include <memory>
377330f729Sjoerg #include <string>
387330f729Sjoerg #include <system_error>
397330f729Sjoerg #include <utility>
407330f729Sjoerg #include <vector>
417330f729Sjoerg 
427330f729Sjoerg using namespace llvm;
437330f729Sjoerg using namespace coverage;
447330f729Sjoerg 
457330f729Sjoerg #define DEBUG_TYPE "coverage-mapping"
467330f729Sjoerg 
get(const CounterExpression & E)477330f729Sjoerg Counter CounterExpressionBuilder::get(const CounterExpression &E) {
487330f729Sjoerg   auto It = ExpressionIndices.find(E);
497330f729Sjoerg   if (It != ExpressionIndices.end())
507330f729Sjoerg     return Counter::getExpression(It->second);
517330f729Sjoerg   unsigned I = Expressions.size();
527330f729Sjoerg   Expressions.push_back(E);
537330f729Sjoerg   ExpressionIndices[E] = I;
547330f729Sjoerg   return Counter::getExpression(I);
557330f729Sjoerg }
567330f729Sjoerg 
extractTerms(Counter C,int Factor,SmallVectorImpl<Term> & Terms)577330f729Sjoerg void CounterExpressionBuilder::extractTerms(Counter C, int Factor,
587330f729Sjoerg                                             SmallVectorImpl<Term> &Terms) {
597330f729Sjoerg   switch (C.getKind()) {
607330f729Sjoerg   case Counter::Zero:
617330f729Sjoerg     break;
627330f729Sjoerg   case Counter::CounterValueReference:
637330f729Sjoerg     Terms.emplace_back(C.getCounterID(), Factor);
647330f729Sjoerg     break;
657330f729Sjoerg   case Counter::Expression:
667330f729Sjoerg     const auto &E = Expressions[C.getExpressionID()];
677330f729Sjoerg     extractTerms(E.LHS, Factor, Terms);
687330f729Sjoerg     extractTerms(
697330f729Sjoerg         E.RHS, E.Kind == CounterExpression::Subtract ? -Factor : Factor, Terms);
707330f729Sjoerg     break;
717330f729Sjoerg   }
727330f729Sjoerg }
737330f729Sjoerg 
simplify(Counter ExpressionTree)747330f729Sjoerg Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
757330f729Sjoerg   // Gather constant terms.
767330f729Sjoerg   SmallVector<Term, 32> Terms;
777330f729Sjoerg   extractTerms(ExpressionTree, +1, Terms);
787330f729Sjoerg 
797330f729Sjoerg   // If there are no terms, this is just a zero. The algorithm below assumes at
807330f729Sjoerg   // least one term.
817330f729Sjoerg   if (Terms.size() == 0)
827330f729Sjoerg     return Counter::getZero();
837330f729Sjoerg 
847330f729Sjoerg   // Group the terms by counter ID.
857330f729Sjoerg   llvm::sort(Terms, [](const Term &LHS, const Term &RHS) {
867330f729Sjoerg     return LHS.CounterID < RHS.CounterID;
877330f729Sjoerg   });
887330f729Sjoerg 
897330f729Sjoerg   // Combine terms by counter ID to eliminate counters that sum to zero.
907330f729Sjoerg   auto Prev = Terms.begin();
917330f729Sjoerg   for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
927330f729Sjoerg     if (I->CounterID == Prev->CounterID) {
937330f729Sjoerg       Prev->Factor += I->Factor;
947330f729Sjoerg       continue;
957330f729Sjoerg     }
967330f729Sjoerg     ++Prev;
977330f729Sjoerg     *Prev = *I;
987330f729Sjoerg   }
997330f729Sjoerg   Terms.erase(++Prev, Terms.end());
1007330f729Sjoerg 
1017330f729Sjoerg   Counter C;
1027330f729Sjoerg   // Create additions. We do this before subtractions to avoid constructs like
1037330f729Sjoerg   // ((0 - X) + Y), as opposed to (Y - X).
1047330f729Sjoerg   for (auto T : Terms) {
1057330f729Sjoerg     if (T.Factor <= 0)
1067330f729Sjoerg       continue;
1077330f729Sjoerg     for (int I = 0; I < T.Factor; ++I)
1087330f729Sjoerg       if (C.isZero())
1097330f729Sjoerg         C = Counter::getCounter(T.CounterID);
1107330f729Sjoerg       else
1117330f729Sjoerg         C = get(CounterExpression(CounterExpression::Add, C,
1127330f729Sjoerg                                   Counter::getCounter(T.CounterID)));
1137330f729Sjoerg   }
1147330f729Sjoerg 
1157330f729Sjoerg   // Create subtractions.
1167330f729Sjoerg   for (auto T : Terms) {
1177330f729Sjoerg     if (T.Factor >= 0)
1187330f729Sjoerg       continue;
1197330f729Sjoerg     for (int I = 0; I < -T.Factor; ++I)
1207330f729Sjoerg       C = get(CounterExpression(CounterExpression::Subtract, C,
1217330f729Sjoerg                                 Counter::getCounter(T.CounterID)));
1227330f729Sjoerg   }
1237330f729Sjoerg   return C;
1247330f729Sjoerg }
1257330f729Sjoerg 
add(Counter LHS,Counter RHS)1267330f729Sjoerg Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
1277330f729Sjoerg   return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
1287330f729Sjoerg }
1297330f729Sjoerg 
subtract(Counter LHS,Counter RHS)1307330f729Sjoerg Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
1317330f729Sjoerg   return simplify(
1327330f729Sjoerg       get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
1337330f729Sjoerg }
1347330f729Sjoerg 
dump(const Counter & C,raw_ostream & OS) const1357330f729Sjoerg void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
1367330f729Sjoerg   switch (C.getKind()) {
1377330f729Sjoerg   case Counter::Zero:
1387330f729Sjoerg     OS << '0';
1397330f729Sjoerg     return;
1407330f729Sjoerg   case Counter::CounterValueReference:
1417330f729Sjoerg     OS << '#' << C.getCounterID();
1427330f729Sjoerg     break;
1437330f729Sjoerg   case Counter::Expression: {
1447330f729Sjoerg     if (C.getExpressionID() >= Expressions.size())
1457330f729Sjoerg       return;
1467330f729Sjoerg     const auto &E = Expressions[C.getExpressionID()];
1477330f729Sjoerg     OS << '(';
1487330f729Sjoerg     dump(E.LHS, OS);
1497330f729Sjoerg     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
1507330f729Sjoerg     dump(E.RHS, OS);
1517330f729Sjoerg     OS << ')';
1527330f729Sjoerg     break;
1537330f729Sjoerg   }
1547330f729Sjoerg   }
1557330f729Sjoerg   if (CounterValues.empty())
1567330f729Sjoerg     return;
1577330f729Sjoerg   Expected<int64_t> Value = evaluate(C);
1587330f729Sjoerg   if (auto E = Value.takeError()) {
1597330f729Sjoerg     consumeError(std::move(E));
1607330f729Sjoerg     return;
1617330f729Sjoerg   }
1627330f729Sjoerg   OS << '[' << *Value << ']';
1637330f729Sjoerg }
1647330f729Sjoerg 
evaluate(const Counter & C) const1657330f729Sjoerg Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
1667330f729Sjoerg   switch (C.getKind()) {
1677330f729Sjoerg   case Counter::Zero:
1687330f729Sjoerg     return 0;
1697330f729Sjoerg   case Counter::CounterValueReference:
1707330f729Sjoerg     if (C.getCounterID() >= CounterValues.size())
1717330f729Sjoerg       return errorCodeToError(errc::argument_out_of_domain);
1727330f729Sjoerg     return CounterValues[C.getCounterID()];
1737330f729Sjoerg   case Counter::Expression: {
1747330f729Sjoerg     if (C.getExpressionID() >= Expressions.size())
1757330f729Sjoerg       return errorCodeToError(errc::argument_out_of_domain);
1767330f729Sjoerg     const auto &E = Expressions[C.getExpressionID()];
1777330f729Sjoerg     Expected<int64_t> LHS = evaluate(E.LHS);
1787330f729Sjoerg     if (!LHS)
1797330f729Sjoerg       return LHS;
1807330f729Sjoerg     Expected<int64_t> RHS = evaluate(E.RHS);
1817330f729Sjoerg     if (!RHS)
1827330f729Sjoerg       return RHS;
1837330f729Sjoerg     return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
1847330f729Sjoerg   }
1857330f729Sjoerg   }
1867330f729Sjoerg   llvm_unreachable("Unhandled CounterKind");
1877330f729Sjoerg }
1887330f729Sjoerg 
getMaxCounterID(const Counter & C) const189*82d56013Sjoerg unsigned CounterMappingContext::getMaxCounterID(const Counter &C) const {
190*82d56013Sjoerg   switch (C.getKind()) {
191*82d56013Sjoerg   case Counter::Zero:
192*82d56013Sjoerg     return 0;
193*82d56013Sjoerg   case Counter::CounterValueReference:
194*82d56013Sjoerg     return C.getCounterID();
195*82d56013Sjoerg   case Counter::Expression: {
196*82d56013Sjoerg     if (C.getExpressionID() >= Expressions.size())
197*82d56013Sjoerg       return 0;
198*82d56013Sjoerg     const auto &E = Expressions[C.getExpressionID()];
199*82d56013Sjoerg     return std::max(getMaxCounterID(E.LHS), getMaxCounterID(E.RHS));
200*82d56013Sjoerg   }
201*82d56013Sjoerg   }
202*82d56013Sjoerg   llvm_unreachable("Unhandled CounterKind");
203*82d56013Sjoerg }
204*82d56013Sjoerg 
skipOtherFiles()2057330f729Sjoerg void FunctionRecordIterator::skipOtherFiles() {
2067330f729Sjoerg   while (Current != Records.end() && !Filename.empty() &&
2077330f729Sjoerg          Filename != Current->Filenames[0])
2087330f729Sjoerg     ++Current;
2097330f729Sjoerg   if (Current == Records.end())
2107330f729Sjoerg     *this = FunctionRecordIterator();
2117330f729Sjoerg }
2127330f729Sjoerg 
getImpreciseRecordIndicesForFilename(StringRef Filename) const2137330f729Sjoerg ArrayRef<unsigned> CoverageMapping::getImpreciseRecordIndicesForFilename(
2147330f729Sjoerg     StringRef Filename) const {
2157330f729Sjoerg   size_t FilenameHash = hash_value(Filename);
2167330f729Sjoerg   auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);
2177330f729Sjoerg   if (RecordIt == FilenameHash2RecordIndices.end())
2187330f729Sjoerg     return {};
2197330f729Sjoerg   return RecordIt->second;
2207330f729Sjoerg }
2217330f729Sjoerg 
getMaxCounterID(const CounterMappingContext & Ctx,const CoverageMappingRecord & Record)222*82d56013Sjoerg static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
223*82d56013Sjoerg                                 const CoverageMappingRecord &Record) {
224*82d56013Sjoerg   unsigned MaxCounterID = 0;
225*82d56013Sjoerg   for (const auto &Region : Record.MappingRegions) {
226*82d56013Sjoerg     MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count));
227*82d56013Sjoerg   }
228*82d56013Sjoerg   return MaxCounterID;
229*82d56013Sjoerg }
230*82d56013Sjoerg 
loadFunctionRecord(const CoverageMappingRecord & Record,IndexedInstrProfReader & ProfileReader)2317330f729Sjoerg Error CoverageMapping::loadFunctionRecord(
2327330f729Sjoerg     const CoverageMappingRecord &Record,
2337330f729Sjoerg     IndexedInstrProfReader &ProfileReader) {
2347330f729Sjoerg   StringRef OrigFuncName = Record.FunctionName;
2357330f729Sjoerg   if (OrigFuncName.empty())
2367330f729Sjoerg     return make_error<CoverageMapError>(coveragemap_error::malformed);
2377330f729Sjoerg 
2387330f729Sjoerg   if (Record.Filenames.empty())
2397330f729Sjoerg     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
2407330f729Sjoerg   else
2417330f729Sjoerg     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
2427330f729Sjoerg 
2437330f729Sjoerg   CounterMappingContext Ctx(Record.Expressions);
2447330f729Sjoerg 
2457330f729Sjoerg   std::vector<uint64_t> Counts;
2467330f729Sjoerg   if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName,
2477330f729Sjoerg                                                 Record.FunctionHash, Counts)) {
2487330f729Sjoerg     instrprof_error IPE = InstrProfError::take(std::move(E));
2497330f729Sjoerg     if (IPE == instrprof_error::hash_mismatch) {
250*82d56013Sjoerg       FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
251*82d56013Sjoerg                                       Record.FunctionHash);
2527330f729Sjoerg       return Error::success();
2537330f729Sjoerg     } else if (IPE != instrprof_error::unknown_function)
2547330f729Sjoerg       return make_error<InstrProfError>(IPE);
255*82d56013Sjoerg     Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
2567330f729Sjoerg   }
2577330f729Sjoerg   Ctx.setCounts(Counts);
2587330f729Sjoerg 
2597330f729Sjoerg   assert(!Record.MappingRegions.empty() && "Function has no regions");
2607330f729Sjoerg 
2617330f729Sjoerg   // This coverage record is a zero region for a function that's unused in
2627330f729Sjoerg   // some TU, but used in a different TU. Ignore it. The coverage maps from the
2637330f729Sjoerg   // the other TU will either be loaded (providing full region counts) or they
2647330f729Sjoerg   // won't (in which case we don't unintuitively report functions as uncovered
2657330f729Sjoerg   // when they have non-zero counts in the profile).
2667330f729Sjoerg   if (Record.MappingRegions.size() == 1 &&
2677330f729Sjoerg       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
2687330f729Sjoerg     return Error::success();
2697330f729Sjoerg 
2707330f729Sjoerg   FunctionRecord Function(OrigFuncName, Record.Filenames);
2717330f729Sjoerg   for (const auto &Region : Record.MappingRegions) {
2727330f729Sjoerg     Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
2737330f729Sjoerg     if (auto E = ExecutionCount.takeError()) {
2747330f729Sjoerg       consumeError(std::move(E));
2757330f729Sjoerg       return Error::success();
2767330f729Sjoerg     }
277*82d56013Sjoerg     Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
278*82d56013Sjoerg     if (auto E = AltExecutionCount.takeError()) {
279*82d56013Sjoerg       consumeError(std::move(E));
280*82d56013Sjoerg       return Error::success();
281*82d56013Sjoerg     }
282*82d56013Sjoerg     Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
2837330f729Sjoerg   }
2847330f729Sjoerg 
2857330f729Sjoerg   // Don't create records for (filenames, function) pairs we've already seen.
2867330f729Sjoerg   auto FilenamesHash = hash_combine_range(Record.Filenames.begin(),
2877330f729Sjoerg                                           Record.Filenames.end());
2887330f729Sjoerg   if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
2897330f729Sjoerg     return Error::success();
2907330f729Sjoerg 
2917330f729Sjoerg   Functions.push_back(std::move(Function));
2927330f729Sjoerg 
2937330f729Sjoerg   // Performance optimization: keep track of the indices of the function records
2947330f729Sjoerg   // which correspond to each filename. This can be used to substantially speed
2957330f729Sjoerg   // up queries for coverage info in a file.
2967330f729Sjoerg   unsigned RecordIndex = Functions.size() - 1;
2977330f729Sjoerg   for (StringRef Filename : Record.Filenames) {
2987330f729Sjoerg     auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
2997330f729Sjoerg     // Note that there may be duplicates in the filename set for a function
3007330f729Sjoerg     // record, because of e.g. macro expansions in the function in which both
3017330f729Sjoerg     // the macro and the function are defined in the same file.
3027330f729Sjoerg     if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
3037330f729Sjoerg       RecordIndices.push_back(RecordIndex);
3047330f729Sjoerg   }
3057330f729Sjoerg 
3067330f729Sjoerg   return Error::success();
3077330f729Sjoerg }
3087330f729Sjoerg 
309*82d56013Sjoerg // This function is for memory optimization by shortening the lifetimes
310*82d56013Sjoerg // of CoverageMappingReader instances.
loadFromReaders(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,IndexedInstrProfReader & ProfileReader,CoverageMapping & Coverage)311*82d56013Sjoerg Error CoverageMapping::loadFromReaders(
312*82d56013Sjoerg     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
313*82d56013Sjoerg     IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage) {
314*82d56013Sjoerg   for (const auto &CoverageReader : CoverageReaders) {
315*82d56013Sjoerg     for (auto RecordOrErr : *CoverageReader) {
316*82d56013Sjoerg       if (Error E = RecordOrErr.takeError())
317*82d56013Sjoerg         return E;
318*82d56013Sjoerg       const auto &Record = *RecordOrErr;
319*82d56013Sjoerg       if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader))
320*82d56013Sjoerg         return E;
321*82d56013Sjoerg     }
322*82d56013Sjoerg   }
323*82d56013Sjoerg   return Error::success();
324*82d56013Sjoerg }
325*82d56013Sjoerg 
load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,IndexedInstrProfReader & ProfileReader)3267330f729Sjoerg Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
3277330f729Sjoerg     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
3287330f729Sjoerg     IndexedInstrProfReader &ProfileReader) {
3297330f729Sjoerg   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
330*82d56013Sjoerg   if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
3317330f729Sjoerg     return std::move(E);
3327330f729Sjoerg   return std::move(Coverage);
3337330f729Sjoerg }
3347330f729Sjoerg 
3357330f729Sjoerg // If E is a no_data_found error, returns success. Otherwise returns E.
handleMaybeNoDataFoundError(Error E)3367330f729Sjoerg static Error handleMaybeNoDataFoundError(Error E) {
3377330f729Sjoerg   return handleErrors(
3387330f729Sjoerg       std::move(E), [](const CoverageMapError &CME) {
3397330f729Sjoerg         if (CME.get() == coveragemap_error::no_data_found)
3407330f729Sjoerg           return static_cast<Error>(Error::success());
3417330f729Sjoerg         return make_error<CoverageMapError>(CME.get());
3427330f729Sjoerg       });
3437330f729Sjoerg }
3447330f729Sjoerg 
3457330f729Sjoerg Expected<std::unique_ptr<CoverageMapping>>
load(ArrayRef<StringRef> ObjectFilenames,StringRef ProfileFilename,ArrayRef<StringRef> Arches,StringRef CompilationDir)3467330f729Sjoerg CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
347*82d56013Sjoerg                       StringRef ProfileFilename, ArrayRef<StringRef> Arches,
348*82d56013Sjoerg                       StringRef CompilationDir) {
3497330f729Sjoerg   auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
3507330f729Sjoerg   if (Error E = ProfileReaderOrErr.takeError())
3517330f729Sjoerg     return std::move(E);
3527330f729Sjoerg   auto ProfileReader = std::move(ProfileReaderOrErr.get());
353*82d56013Sjoerg   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
354*82d56013Sjoerg   bool DataFound = false;
3557330f729Sjoerg 
3567330f729Sjoerg   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
357*82d56013Sjoerg     auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(
358*82d56013Sjoerg         File.value(), /*IsText=*/false, /*RequiresNullTerminator=*/false);
3597330f729Sjoerg     if (std::error_code EC = CovMappingBufOrErr.getError())
3607330f729Sjoerg       return errorCodeToError(EC);
3617330f729Sjoerg     StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()];
3627330f729Sjoerg     MemoryBufferRef CovMappingBufRef =
3637330f729Sjoerg         CovMappingBufOrErr.get()->getMemBufferRef();
364*82d56013Sjoerg     SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
365*82d56013Sjoerg     auto CoverageReadersOrErr = BinaryCoverageReader::create(
366*82d56013Sjoerg         CovMappingBufRef, Arch, Buffers, CompilationDir);
3677330f729Sjoerg     if (Error E = CoverageReadersOrErr.takeError()) {
3687330f729Sjoerg       E = handleMaybeNoDataFoundError(std::move(E));
3697330f729Sjoerg       if (E)
3707330f729Sjoerg         return std::move(E);
3717330f729Sjoerg       // E == success (originally a no_data_found error).
3727330f729Sjoerg       continue;
3737330f729Sjoerg     }
374*82d56013Sjoerg 
375*82d56013Sjoerg     SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers;
3767330f729Sjoerg     for (auto &Reader : CoverageReadersOrErr.get())
3777330f729Sjoerg       Readers.push_back(std::move(Reader));
378*82d56013Sjoerg     DataFound |= !Readers.empty();
379*82d56013Sjoerg     if (Error E = loadFromReaders(Readers, *ProfileReader, *Coverage))
380*82d56013Sjoerg       return std::move(E);
3817330f729Sjoerg   }
3827330f729Sjoerg   // If no readers were created, either no objects were provided or none of them
3837330f729Sjoerg   // had coverage data. Return an error in the latter case.
384*82d56013Sjoerg   if (!DataFound && !ObjectFilenames.empty())
3857330f729Sjoerg     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
386*82d56013Sjoerg   return std::move(Coverage);
3877330f729Sjoerg }
3887330f729Sjoerg 
3897330f729Sjoerg namespace {
3907330f729Sjoerg 
3917330f729Sjoerg /// Distributes functions into instantiation sets.
3927330f729Sjoerg ///
3937330f729Sjoerg /// An instantiation set is a collection of functions that have the same source
3947330f729Sjoerg /// code, ie, template functions specializations.
3957330f729Sjoerg class FunctionInstantiationSetCollector {
3967330f729Sjoerg   using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
3977330f729Sjoerg   MapT InstantiatedFunctions;
3987330f729Sjoerg 
3997330f729Sjoerg public:
insert(const FunctionRecord & Function,unsigned FileID)4007330f729Sjoerg   void insert(const FunctionRecord &Function, unsigned FileID) {
4017330f729Sjoerg     auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
4027330f729Sjoerg     while (I != E && I->FileID != FileID)
4037330f729Sjoerg       ++I;
4047330f729Sjoerg     assert(I != E && "function does not cover the given file");
4057330f729Sjoerg     auto &Functions = InstantiatedFunctions[I->startLoc()];
4067330f729Sjoerg     Functions.push_back(&Function);
4077330f729Sjoerg   }
4087330f729Sjoerg 
begin()4097330f729Sjoerg   MapT::iterator begin() { return InstantiatedFunctions.begin(); }
end()4107330f729Sjoerg   MapT::iterator end() { return InstantiatedFunctions.end(); }
4117330f729Sjoerg };
4127330f729Sjoerg 
4137330f729Sjoerg class SegmentBuilder {
4147330f729Sjoerg   std::vector<CoverageSegment> &Segments;
4157330f729Sjoerg   SmallVector<const CountedRegion *, 8> ActiveRegions;
4167330f729Sjoerg 
SegmentBuilder(std::vector<CoverageSegment> & Segments)4177330f729Sjoerg   SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
4187330f729Sjoerg 
4197330f729Sjoerg   /// Emit a segment with the count from \p Region starting at \p StartLoc.
4207330f729Sjoerg   //
4217330f729Sjoerg   /// \p IsRegionEntry: The segment is at the start of a new non-gap region.
4227330f729Sjoerg   /// \p EmitSkippedRegion: The segment must be emitted as a skipped region.
startSegment(const CountedRegion & Region,LineColPair StartLoc,bool IsRegionEntry,bool EmitSkippedRegion=false)4237330f729Sjoerg   void startSegment(const CountedRegion &Region, LineColPair StartLoc,
4247330f729Sjoerg                     bool IsRegionEntry, bool EmitSkippedRegion = false) {
4257330f729Sjoerg     bool HasCount = !EmitSkippedRegion &&
4267330f729Sjoerg                     (Region.Kind != CounterMappingRegion::SkippedRegion);
4277330f729Sjoerg 
4287330f729Sjoerg     // If the new segment wouldn't affect coverage rendering, skip it.
4297330f729Sjoerg     if (!Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
4307330f729Sjoerg       const auto &Last = Segments.back();
4317330f729Sjoerg       if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount &&
4327330f729Sjoerg           !Last.IsRegionEntry)
4337330f729Sjoerg         return;
4347330f729Sjoerg     }
4357330f729Sjoerg 
4367330f729Sjoerg     if (HasCount)
4377330f729Sjoerg       Segments.emplace_back(StartLoc.first, StartLoc.second,
4387330f729Sjoerg                             Region.ExecutionCount, IsRegionEntry,
4397330f729Sjoerg                             Region.Kind == CounterMappingRegion::GapRegion);
4407330f729Sjoerg     else
4417330f729Sjoerg       Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
4427330f729Sjoerg 
4437330f729Sjoerg     LLVM_DEBUG({
4447330f729Sjoerg       const auto &Last = Segments.back();
4457330f729Sjoerg       dbgs() << "Segment at " << Last.Line << ":" << Last.Col
4467330f729Sjoerg              << " (count = " << Last.Count << ")"
4477330f729Sjoerg              << (Last.IsRegionEntry ? ", RegionEntry" : "")
4487330f729Sjoerg              << (!Last.HasCount ? ", Skipped" : "")
4497330f729Sjoerg              << (Last.IsGapRegion ? ", Gap" : "") << "\n";
4507330f729Sjoerg     });
4517330f729Sjoerg   }
4527330f729Sjoerg 
4537330f729Sjoerg   /// Emit segments for active regions which end before \p Loc.
4547330f729Sjoerg   ///
4557330f729Sjoerg   /// \p Loc: The start location of the next region. If None, all active
4567330f729Sjoerg   /// regions are completed.
4577330f729Sjoerg   /// \p FirstCompletedRegion: Index of the first completed region.
completeRegionsUntil(Optional<LineColPair> Loc,unsigned FirstCompletedRegion)4587330f729Sjoerg   void completeRegionsUntil(Optional<LineColPair> Loc,
4597330f729Sjoerg                             unsigned FirstCompletedRegion) {
4607330f729Sjoerg     // Sort the completed regions by end location. This makes it simple to
4617330f729Sjoerg     // emit closing segments in sorted order.
4627330f729Sjoerg     auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;
4637330f729Sjoerg     std::stable_sort(CompletedRegionsIt, ActiveRegions.end(),
4647330f729Sjoerg                       [](const CountedRegion *L, const CountedRegion *R) {
4657330f729Sjoerg                         return L->endLoc() < R->endLoc();
4667330f729Sjoerg                       });
4677330f729Sjoerg 
4687330f729Sjoerg     // Emit segments for all completed regions.
4697330f729Sjoerg     for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E;
4707330f729Sjoerg          ++I) {
4717330f729Sjoerg       const auto *CompletedRegion = ActiveRegions[I];
4727330f729Sjoerg       assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
4737330f729Sjoerg              "Completed region ends after start of new region");
4747330f729Sjoerg 
4757330f729Sjoerg       const auto *PrevCompletedRegion = ActiveRegions[I - 1];
4767330f729Sjoerg       auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
4777330f729Sjoerg 
4787330f729Sjoerg       // Don't emit any more segments if they start where the new region begins.
4797330f729Sjoerg       if (Loc && CompletedSegmentLoc == *Loc)
4807330f729Sjoerg         break;
4817330f729Sjoerg 
4827330f729Sjoerg       // Don't emit a segment if the next completed region ends at the same
4837330f729Sjoerg       // location as this one.
4847330f729Sjoerg       if (CompletedSegmentLoc == CompletedRegion->endLoc())
4857330f729Sjoerg         continue;
4867330f729Sjoerg 
4877330f729Sjoerg       // Use the count from the last completed region which ends at this loc.
4887330f729Sjoerg       for (unsigned J = I + 1; J < E; ++J)
4897330f729Sjoerg         if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
4907330f729Sjoerg           CompletedRegion = ActiveRegions[J];
4917330f729Sjoerg 
4927330f729Sjoerg       startSegment(*CompletedRegion, CompletedSegmentLoc, false);
4937330f729Sjoerg     }
4947330f729Sjoerg 
4957330f729Sjoerg     auto Last = ActiveRegions.back();
4967330f729Sjoerg     if (FirstCompletedRegion && Last->endLoc() != *Loc) {
4977330f729Sjoerg       // If there's a gap after the end of the last completed region and the
4987330f729Sjoerg       // start of the new region, use the last active region to fill the gap.
4997330f729Sjoerg       startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(),
5007330f729Sjoerg                    false);
5017330f729Sjoerg     } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) {
5027330f729Sjoerg       // Emit a skipped segment if there are no more active regions. This
5037330f729Sjoerg       // ensures that gaps between functions are marked correctly.
5047330f729Sjoerg       startSegment(*Last, Last->endLoc(), false, true);
5057330f729Sjoerg     }
5067330f729Sjoerg 
5077330f729Sjoerg     // Pop the completed regions.
5087330f729Sjoerg     ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end());
5097330f729Sjoerg   }
5107330f729Sjoerg 
buildSegmentsImpl(ArrayRef<CountedRegion> Regions)5117330f729Sjoerg   void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
5127330f729Sjoerg     for (const auto &CR : enumerate(Regions)) {
5137330f729Sjoerg       auto CurStartLoc = CR.value().startLoc();
5147330f729Sjoerg 
5157330f729Sjoerg       // Active regions which end before the current region need to be popped.
5167330f729Sjoerg       auto CompletedRegions =
5177330f729Sjoerg           std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),
5187330f729Sjoerg                                 [&](const CountedRegion *Region) {
5197330f729Sjoerg                                   return !(Region->endLoc() <= CurStartLoc);
5207330f729Sjoerg                                 });
5217330f729Sjoerg       if (CompletedRegions != ActiveRegions.end()) {
5227330f729Sjoerg         unsigned FirstCompletedRegion =
5237330f729Sjoerg             std::distance(ActiveRegions.begin(), CompletedRegions);
5247330f729Sjoerg         completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
5257330f729Sjoerg       }
5267330f729Sjoerg 
5277330f729Sjoerg       bool GapRegion = CR.value().Kind == CounterMappingRegion::GapRegion;
5287330f729Sjoerg 
5297330f729Sjoerg       // Try to emit a segment for the current region.
5307330f729Sjoerg       if (CurStartLoc == CR.value().endLoc()) {
5317330f729Sjoerg         // Avoid making zero-length regions active. If it's the last region,
5327330f729Sjoerg         // emit a skipped segment. Otherwise use its predecessor's count.
533*82d56013Sjoerg         const bool Skipped =
534*82d56013Sjoerg             (CR.index() + 1) == Regions.size() ||
535*82d56013Sjoerg             CR.value().Kind == CounterMappingRegion::SkippedRegion;
5367330f729Sjoerg         startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),
5377330f729Sjoerg                      CurStartLoc, !GapRegion, Skipped);
538*82d56013Sjoerg         // If it is skipped segment, create a segment with last pushed
539*82d56013Sjoerg         // regions's count at CurStartLoc.
540*82d56013Sjoerg         if (Skipped && !ActiveRegions.empty())
541*82d56013Sjoerg           startSegment(*ActiveRegions.back(), CurStartLoc, false);
5427330f729Sjoerg         continue;
5437330f729Sjoerg       }
5447330f729Sjoerg       if (CR.index() + 1 == Regions.size() ||
5457330f729Sjoerg           CurStartLoc != Regions[CR.index() + 1].startLoc()) {
5467330f729Sjoerg         // Emit a segment if the next region doesn't start at the same location
5477330f729Sjoerg         // as this one.
5487330f729Sjoerg         startSegment(CR.value(), CurStartLoc, !GapRegion);
5497330f729Sjoerg       }
5507330f729Sjoerg 
5517330f729Sjoerg       // This region is active (i.e not completed).
5527330f729Sjoerg       ActiveRegions.push_back(&CR.value());
5537330f729Sjoerg     }
5547330f729Sjoerg 
5557330f729Sjoerg     // Complete any remaining active regions.
5567330f729Sjoerg     if (!ActiveRegions.empty())
5577330f729Sjoerg       completeRegionsUntil(None, 0);
5587330f729Sjoerg   }
5597330f729Sjoerg 
5607330f729Sjoerg   /// Sort a nested sequence of regions from a single file.
sortNestedRegions(MutableArrayRef<CountedRegion> Regions)5617330f729Sjoerg   static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
5627330f729Sjoerg     llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) {
5637330f729Sjoerg       if (LHS.startLoc() != RHS.startLoc())
5647330f729Sjoerg         return LHS.startLoc() < RHS.startLoc();
5657330f729Sjoerg       if (LHS.endLoc() != RHS.endLoc())
5667330f729Sjoerg         // When LHS completely contains RHS, we sort LHS first.
5677330f729Sjoerg         return RHS.endLoc() < LHS.endLoc();
5687330f729Sjoerg       // If LHS and RHS cover the same area, we need to sort them according
5697330f729Sjoerg       // to their kinds so that the most suitable region will become "active"
5707330f729Sjoerg       // in combineRegions(). Because we accumulate counter values only from
5717330f729Sjoerg       // regions of the same kind as the first region of the area, prefer
5727330f729Sjoerg       // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
5737330f729Sjoerg       static_assert(CounterMappingRegion::CodeRegion <
5747330f729Sjoerg                             CounterMappingRegion::ExpansionRegion &&
5757330f729Sjoerg                         CounterMappingRegion::ExpansionRegion <
5767330f729Sjoerg                             CounterMappingRegion::SkippedRegion,
5777330f729Sjoerg                     "Unexpected order of region kind values");
5787330f729Sjoerg       return LHS.Kind < RHS.Kind;
5797330f729Sjoerg     });
5807330f729Sjoerg   }
5817330f729Sjoerg 
5827330f729Sjoerg   /// Combine counts of regions which cover the same area.
5837330f729Sjoerg   static ArrayRef<CountedRegion>
combineRegions(MutableArrayRef<CountedRegion> Regions)5847330f729Sjoerg   combineRegions(MutableArrayRef<CountedRegion> Regions) {
5857330f729Sjoerg     if (Regions.empty())
5867330f729Sjoerg       return Regions;
5877330f729Sjoerg     auto Active = Regions.begin();
5887330f729Sjoerg     auto End = Regions.end();
5897330f729Sjoerg     for (auto I = Regions.begin() + 1; I != End; ++I) {
5907330f729Sjoerg       if (Active->startLoc() != I->startLoc() ||
5917330f729Sjoerg           Active->endLoc() != I->endLoc()) {
5927330f729Sjoerg         // Shift to the next region.
5937330f729Sjoerg         ++Active;
5947330f729Sjoerg         if (Active != I)
5957330f729Sjoerg           *Active = *I;
5967330f729Sjoerg         continue;
5977330f729Sjoerg       }
5987330f729Sjoerg       // Merge duplicate region.
5997330f729Sjoerg       // If CodeRegions and ExpansionRegions cover the same area, it's probably
6007330f729Sjoerg       // a macro which is fully expanded to another macro. In that case, we need
6017330f729Sjoerg       // to accumulate counts only from CodeRegions, or else the area will be
6027330f729Sjoerg       // counted twice.
6037330f729Sjoerg       // On the other hand, a macro may have a nested macro in its body. If the
6047330f729Sjoerg       // outer macro is used several times, the ExpansionRegion for the nested
6057330f729Sjoerg       // macro will also be added several times. These ExpansionRegions cover
6067330f729Sjoerg       // the same source locations and have to be combined to reach the correct
6077330f729Sjoerg       // value for that area.
6087330f729Sjoerg       // We add counts of the regions of the same kind as the active region
6097330f729Sjoerg       // to handle the both situations.
6107330f729Sjoerg       if (I->Kind == Active->Kind)
6117330f729Sjoerg         Active->ExecutionCount += I->ExecutionCount;
6127330f729Sjoerg     }
6137330f729Sjoerg     return Regions.drop_back(std::distance(++Active, End));
6147330f729Sjoerg   }
6157330f729Sjoerg 
6167330f729Sjoerg public:
6177330f729Sjoerg   /// Build a sorted list of CoverageSegments from a list of Regions.
6187330f729Sjoerg   static std::vector<CoverageSegment>
buildSegments(MutableArrayRef<CountedRegion> Regions)6197330f729Sjoerg   buildSegments(MutableArrayRef<CountedRegion> Regions) {
6207330f729Sjoerg     std::vector<CoverageSegment> Segments;
6217330f729Sjoerg     SegmentBuilder Builder(Segments);
6227330f729Sjoerg 
6237330f729Sjoerg     sortNestedRegions(Regions);
6247330f729Sjoerg     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
6257330f729Sjoerg 
6267330f729Sjoerg     LLVM_DEBUG({
6277330f729Sjoerg       dbgs() << "Combined regions:\n";
6287330f729Sjoerg       for (const auto &CR : CombinedRegions)
6297330f729Sjoerg         dbgs() << "  " << CR.LineStart << ":" << CR.ColumnStart << " -> "
6307330f729Sjoerg                << CR.LineEnd << ":" << CR.ColumnEnd
6317330f729Sjoerg                << " (count=" << CR.ExecutionCount << ")\n";
6327330f729Sjoerg     });
6337330f729Sjoerg 
6347330f729Sjoerg     Builder.buildSegmentsImpl(CombinedRegions);
6357330f729Sjoerg 
6367330f729Sjoerg #ifndef NDEBUG
6377330f729Sjoerg     for (unsigned I = 1, E = Segments.size(); I < E; ++I) {
6387330f729Sjoerg       const auto &L = Segments[I - 1];
6397330f729Sjoerg       const auto &R = Segments[I];
6407330f729Sjoerg       if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) {
641*82d56013Sjoerg         if (L.Line == R.Line && L.Col == R.Col && !L.HasCount)
642*82d56013Sjoerg           continue;
6437330f729Sjoerg         LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col
6447330f729Sjoerg                           << " followed by " << R.Line << ":" << R.Col << "\n");
6457330f729Sjoerg         assert(false && "Coverage segments not unique or sorted");
6467330f729Sjoerg       }
6477330f729Sjoerg     }
6487330f729Sjoerg #endif
6497330f729Sjoerg 
6507330f729Sjoerg     return Segments;
6517330f729Sjoerg   }
6527330f729Sjoerg };
6537330f729Sjoerg 
6547330f729Sjoerg } // end anonymous namespace
6557330f729Sjoerg 
getUniqueSourceFiles() const6567330f729Sjoerg std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
6577330f729Sjoerg   std::vector<StringRef> Filenames;
6587330f729Sjoerg   for (const auto &Function : getCoveredFunctions())
659*82d56013Sjoerg     llvm::append_range(Filenames, Function.Filenames);
6607330f729Sjoerg   llvm::sort(Filenames);
6617330f729Sjoerg   auto Last = std::unique(Filenames.begin(), Filenames.end());
6627330f729Sjoerg   Filenames.erase(Last, Filenames.end());
6637330f729Sjoerg   return Filenames;
6647330f729Sjoerg }
6657330f729Sjoerg 
gatherFileIDs(StringRef SourceFile,const FunctionRecord & Function)6667330f729Sjoerg static SmallBitVector gatherFileIDs(StringRef SourceFile,
6677330f729Sjoerg                                     const FunctionRecord &Function) {
6687330f729Sjoerg   SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
6697330f729Sjoerg   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
6707330f729Sjoerg     if (SourceFile == Function.Filenames[I])
6717330f729Sjoerg       FilenameEquivalence[I] = true;
6727330f729Sjoerg   return FilenameEquivalence;
6737330f729Sjoerg }
6747330f729Sjoerg 
6757330f729Sjoerg /// Return the ID of the file where the definition of the function is located.
findMainViewFileID(const FunctionRecord & Function)6767330f729Sjoerg static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
6777330f729Sjoerg   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
6787330f729Sjoerg   for (const auto &CR : Function.CountedRegions)
6797330f729Sjoerg     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
6807330f729Sjoerg       IsNotExpandedFile[CR.ExpandedFileID] = false;
6817330f729Sjoerg   int I = IsNotExpandedFile.find_first();
6827330f729Sjoerg   if (I == -1)
6837330f729Sjoerg     return None;
6847330f729Sjoerg   return I;
6857330f729Sjoerg }
6867330f729Sjoerg 
6877330f729Sjoerg /// Check if SourceFile is the file that contains the definition of
6887330f729Sjoerg /// the Function. Return the ID of the file in that case or None otherwise.
findMainViewFileID(StringRef SourceFile,const FunctionRecord & Function)6897330f729Sjoerg static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
6907330f729Sjoerg                                              const FunctionRecord &Function) {
6917330f729Sjoerg   Optional<unsigned> I = findMainViewFileID(Function);
6927330f729Sjoerg   if (I && SourceFile == Function.Filenames[*I])
6937330f729Sjoerg     return I;
6947330f729Sjoerg   return None;
6957330f729Sjoerg }
6967330f729Sjoerg 
isExpansion(const CountedRegion & R,unsigned FileID)6977330f729Sjoerg static bool isExpansion(const CountedRegion &R, unsigned FileID) {
6987330f729Sjoerg   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
6997330f729Sjoerg }
7007330f729Sjoerg 
getCoverageForFile(StringRef Filename) const7017330f729Sjoerg CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
7027330f729Sjoerg   CoverageData FileCoverage(Filename);
7037330f729Sjoerg   std::vector<CountedRegion> Regions;
7047330f729Sjoerg 
7057330f729Sjoerg   // Look up the function records in the given file. Due to hash collisions on
7067330f729Sjoerg   // the filename, we may get back some records that are not in the file.
7077330f729Sjoerg   ArrayRef<unsigned> RecordIndices =
7087330f729Sjoerg       getImpreciseRecordIndicesForFilename(Filename);
7097330f729Sjoerg   for (unsigned RecordIndex : RecordIndices) {
7107330f729Sjoerg     const FunctionRecord &Function = Functions[RecordIndex];
7117330f729Sjoerg     auto MainFileID = findMainViewFileID(Filename, Function);
7127330f729Sjoerg     auto FileIDs = gatherFileIDs(Filename, Function);
7137330f729Sjoerg     for (const auto &CR : Function.CountedRegions)
7147330f729Sjoerg       if (FileIDs.test(CR.FileID)) {
7157330f729Sjoerg         Regions.push_back(CR);
7167330f729Sjoerg         if (MainFileID && isExpansion(CR, *MainFileID))
7177330f729Sjoerg           FileCoverage.Expansions.emplace_back(CR, Function);
7187330f729Sjoerg       }
719*82d56013Sjoerg     // Capture branch regions specific to the function (excluding expansions).
720*82d56013Sjoerg     for (const auto &CR : Function.CountedBranchRegions)
721*82d56013Sjoerg       if (FileIDs.test(CR.FileID) && (CR.FileID == CR.ExpandedFileID))
722*82d56013Sjoerg         FileCoverage.BranchRegions.push_back(CR);
7237330f729Sjoerg   }
7247330f729Sjoerg 
7257330f729Sjoerg   LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
7267330f729Sjoerg   FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
7277330f729Sjoerg 
7287330f729Sjoerg   return FileCoverage;
7297330f729Sjoerg }
7307330f729Sjoerg 
7317330f729Sjoerg std::vector<InstantiationGroup>
getInstantiationGroups(StringRef Filename) const7327330f729Sjoerg CoverageMapping::getInstantiationGroups(StringRef Filename) const {
7337330f729Sjoerg   FunctionInstantiationSetCollector InstantiationSetCollector;
7347330f729Sjoerg   // Look up the function records in the given file. Due to hash collisions on
7357330f729Sjoerg   // the filename, we may get back some records that are not in the file.
7367330f729Sjoerg   ArrayRef<unsigned> RecordIndices =
7377330f729Sjoerg       getImpreciseRecordIndicesForFilename(Filename);
7387330f729Sjoerg   for (unsigned RecordIndex : RecordIndices) {
7397330f729Sjoerg     const FunctionRecord &Function = Functions[RecordIndex];
7407330f729Sjoerg     auto MainFileID = findMainViewFileID(Filename, Function);
7417330f729Sjoerg     if (!MainFileID)
7427330f729Sjoerg       continue;
7437330f729Sjoerg     InstantiationSetCollector.insert(Function, *MainFileID);
7447330f729Sjoerg   }
7457330f729Sjoerg 
7467330f729Sjoerg   std::vector<InstantiationGroup> Result;
7477330f729Sjoerg   for (auto &InstantiationSet : InstantiationSetCollector) {
7487330f729Sjoerg     InstantiationGroup IG{InstantiationSet.first.first,
7497330f729Sjoerg                           InstantiationSet.first.second,
7507330f729Sjoerg                           std::move(InstantiationSet.second)};
7517330f729Sjoerg     Result.emplace_back(std::move(IG));
7527330f729Sjoerg   }
7537330f729Sjoerg   return Result;
7547330f729Sjoerg }
7557330f729Sjoerg 
7567330f729Sjoerg CoverageData
getCoverageForFunction(const FunctionRecord & Function) const7577330f729Sjoerg CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
7587330f729Sjoerg   auto MainFileID = findMainViewFileID(Function);
7597330f729Sjoerg   if (!MainFileID)
7607330f729Sjoerg     return CoverageData();
7617330f729Sjoerg 
7627330f729Sjoerg   CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
7637330f729Sjoerg   std::vector<CountedRegion> Regions;
7647330f729Sjoerg   for (const auto &CR : Function.CountedRegions)
7657330f729Sjoerg     if (CR.FileID == *MainFileID) {
7667330f729Sjoerg       Regions.push_back(CR);
7677330f729Sjoerg       if (isExpansion(CR, *MainFileID))
7687330f729Sjoerg         FunctionCoverage.Expansions.emplace_back(CR, Function);
7697330f729Sjoerg     }
770*82d56013Sjoerg   // Capture branch regions specific to the function (excluding expansions).
771*82d56013Sjoerg   for (const auto &CR : Function.CountedBranchRegions)
772*82d56013Sjoerg     if (CR.FileID == *MainFileID)
773*82d56013Sjoerg       FunctionCoverage.BranchRegions.push_back(CR);
7747330f729Sjoerg 
7757330f729Sjoerg   LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
7767330f729Sjoerg                     << "\n");
7777330f729Sjoerg   FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
7787330f729Sjoerg 
7797330f729Sjoerg   return FunctionCoverage;
7807330f729Sjoerg }
7817330f729Sjoerg 
getCoverageForExpansion(const ExpansionRecord & Expansion) const7827330f729Sjoerg CoverageData CoverageMapping::getCoverageForExpansion(
7837330f729Sjoerg     const ExpansionRecord &Expansion) const {
7847330f729Sjoerg   CoverageData ExpansionCoverage(
7857330f729Sjoerg       Expansion.Function.Filenames[Expansion.FileID]);
7867330f729Sjoerg   std::vector<CountedRegion> Regions;
7877330f729Sjoerg   for (const auto &CR : Expansion.Function.CountedRegions)
7887330f729Sjoerg     if (CR.FileID == Expansion.FileID) {
7897330f729Sjoerg       Regions.push_back(CR);
7907330f729Sjoerg       if (isExpansion(CR, Expansion.FileID))
7917330f729Sjoerg         ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
7927330f729Sjoerg     }
793*82d56013Sjoerg   for (const auto &CR : Expansion.Function.CountedBranchRegions)
794*82d56013Sjoerg     // Capture branch regions that only pertain to the corresponding expansion.
795*82d56013Sjoerg     if (CR.FileID == Expansion.FileID)
796*82d56013Sjoerg       ExpansionCoverage.BranchRegions.push_back(CR);
7977330f729Sjoerg 
7987330f729Sjoerg   LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
7997330f729Sjoerg                     << Expansion.FileID << "\n");
8007330f729Sjoerg   ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
8017330f729Sjoerg 
8027330f729Sjoerg   return ExpansionCoverage;
8037330f729Sjoerg }
8047330f729Sjoerg 
LineCoverageStats(ArrayRef<const CoverageSegment * > LineSegments,const CoverageSegment * WrappedSegment,unsigned Line)8057330f729Sjoerg LineCoverageStats::LineCoverageStats(
8067330f729Sjoerg     ArrayRef<const CoverageSegment *> LineSegments,
8077330f729Sjoerg     const CoverageSegment *WrappedSegment, unsigned Line)
8087330f729Sjoerg     : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
8097330f729Sjoerg       LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
8107330f729Sjoerg   // Find the minimum number of regions which start in this line.
8117330f729Sjoerg   unsigned MinRegionCount = 0;
8127330f729Sjoerg   auto isStartOfRegion = [](const CoverageSegment *S) {
8137330f729Sjoerg     return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
8147330f729Sjoerg   };
8157330f729Sjoerg   for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
8167330f729Sjoerg     if (isStartOfRegion(LineSegments[I]))
8177330f729Sjoerg       ++MinRegionCount;
8187330f729Sjoerg 
8197330f729Sjoerg   bool StartOfSkippedRegion = !LineSegments.empty() &&
8207330f729Sjoerg                               !LineSegments.front()->HasCount &&
8217330f729Sjoerg                               LineSegments.front()->IsRegionEntry;
8227330f729Sjoerg 
8237330f729Sjoerg   HasMultipleRegions = MinRegionCount > 1;
8247330f729Sjoerg   Mapped =
8257330f729Sjoerg       !StartOfSkippedRegion &&
8267330f729Sjoerg       ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
8277330f729Sjoerg 
8287330f729Sjoerg   if (!Mapped)
8297330f729Sjoerg     return;
8307330f729Sjoerg 
8317330f729Sjoerg   // Pick the max count from the non-gap, region entry segments and the
8327330f729Sjoerg   // wrapped count.
8337330f729Sjoerg   if (WrappedSegment)
8347330f729Sjoerg     ExecutionCount = WrappedSegment->Count;
8357330f729Sjoerg   if (!MinRegionCount)
8367330f729Sjoerg     return;
8377330f729Sjoerg   for (const auto *LS : LineSegments)
8387330f729Sjoerg     if (isStartOfRegion(LS))
8397330f729Sjoerg       ExecutionCount = std::max(ExecutionCount, LS->Count);
8407330f729Sjoerg }
8417330f729Sjoerg 
operator ++()8427330f729Sjoerg LineCoverageIterator &LineCoverageIterator::operator++() {
8437330f729Sjoerg   if (Next == CD.end()) {
8447330f729Sjoerg     Stats = LineCoverageStats();
8457330f729Sjoerg     Ended = true;
8467330f729Sjoerg     return *this;
8477330f729Sjoerg   }
8487330f729Sjoerg   if (Segments.size())
8497330f729Sjoerg     WrappedSegment = Segments.back();
8507330f729Sjoerg   Segments.clear();
8517330f729Sjoerg   while (Next != CD.end() && Next->Line == Line)
8527330f729Sjoerg     Segments.push_back(&*Next++);
8537330f729Sjoerg   Stats = LineCoverageStats(Segments, WrappedSegment, Line);
8547330f729Sjoerg   ++Line;
8557330f729Sjoerg   return *this;
8567330f729Sjoerg }
8577330f729Sjoerg 
getCoverageMapErrString(coveragemap_error Err)8587330f729Sjoerg static std::string getCoverageMapErrString(coveragemap_error Err) {
8597330f729Sjoerg   switch (Err) {
8607330f729Sjoerg   case coveragemap_error::success:
8617330f729Sjoerg     return "Success";
8627330f729Sjoerg   case coveragemap_error::eof:
8637330f729Sjoerg     return "End of File";
8647330f729Sjoerg   case coveragemap_error::no_data_found:
8657330f729Sjoerg     return "No coverage data found";
8667330f729Sjoerg   case coveragemap_error::unsupported_version:
8677330f729Sjoerg     return "Unsupported coverage format version";
8687330f729Sjoerg   case coveragemap_error::truncated:
8697330f729Sjoerg     return "Truncated coverage data";
8707330f729Sjoerg   case coveragemap_error::malformed:
8717330f729Sjoerg     return "Malformed coverage data";
872*82d56013Sjoerg   case coveragemap_error::decompression_failed:
873*82d56013Sjoerg     return "Failed to decompress coverage data (zlib)";
874*82d56013Sjoerg   case coveragemap_error::invalid_or_missing_arch_specifier:
875*82d56013Sjoerg     return "`-arch` specifier is invalid or missing for universal binary";
8767330f729Sjoerg   }
8777330f729Sjoerg   llvm_unreachable("A value of coveragemap_error has no message.");
8787330f729Sjoerg }
8797330f729Sjoerg 
8807330f729Sjoerg namespace {
8817330f729Sjoerg 
8827330f729Sjoerg // FIXME: This class is only here to support the transition to llvm::Error. It
8837330f729Sjoerg // will be removed once this transition is complete. Clients should prefer to
8847330f729Sjoerg // deal with the Error value directly, rather than converting to error_code.
8857330f729Sjoerg class CoverageMappingErrorCategoryType : public std::error_category {
name() const8867330f729Sjoerg   const char *name() const noexcept override { return "llvm.coveragemap"; }
message(int IE) const8877330f729Sjoerg   std::string message(int IE) const override {
8887330f729Sjoerg     return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
8897330f729Sjoerg   }
8907330f729Sjoerg };
8917330f729Sjoerg 
8927330f729Sjoerg } // end anonymous namespace
8937330f729Sjoerg 
message() const8947330f729Sjoerg std::string CoverageMapError::message() const {
8957330f729Sjoerg   return getCoverageMapErrString(Err);
8967330f729Sjoerg }
8977330f729Sjoerg 
8987330f729Sjoerg static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
8997330f729Sjoerg 
coveragemap_category()9007330f729Sjoerg const std::error_category &llvm::coverage::coveragemap_category() {
9017330f729Sjoerg   return *ErrorCategory;
9027330f729Sjoerg }
9037330f729Sjoerg 
9047330f729Sjoerg char CoverageMapError::ID = 0;
905