xref: /freebsd/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- CoverageMapping.cpp - Code coverage mapping support ----------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file contains support for clang's and llvm's instrumentation based
10*0b57cec5SDimitry Andric // code coverage.
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMapping.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
17*0b57cec5SDimitry Andric #include "llvm/ADT/None.h"
18*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
19*0b57cec5SDimitry Andric #include "llvm/ADT/SmallBitVector.h"
20*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
21*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
22*0b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
23*0b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
24*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
25*0b57cec5SDimitry Andric #include "llvm/Support/Errc.h"
26*0b57cec5SDimitry Andric #include "llvm/Support/Error.h"
27*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
28*0b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h"
29*0b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
30*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
31*0b57cec5SDimitry Andric #include <algorithm>
32*0b57cec5SDimitry Andric #include <cassert>
33*0b57cec5SDimitry Andric #include <cstdint>
34*0b57cec5SDimitry Andric #include <iterator>
35*0b57cec5SDimitry Andric #include <map>
36*0b57cec5SDimitry Andric #include <memory>
37*0b57cec5SDimitry Andric #include <string>
38*0b57cec5SDimitry Andric #include <system_error>
39*0b57cec5SDimitry Andric #include <utility>
40*0b57cec5SDimitry Andric #include <vector>
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric using namespace llvm;
43*0b57cec5SDimitry Andric using namespace coverage;
44*0b57cec5SDimitry Andric 
45*0b57cec5SDimitry Andric #define DEBUG_TYPE "coverage-mapping"
46*0b57cec5SDimitry Andric 
47*0b57cec5SDimitry Andric Counter CounterExpressionBuilder::get(const CounterExpression &E) {
48*0b57cec5SDimitry Andric   auto It = ExpressionIndices.find(E);
49*0b57cec5SDimitry Andric   if (It != ExpressionIndices.end())
50*0b57cec5SDimitry Andric     return Counter::getExpression(It->second);
51*0b57cec5SDimitry Andric   unsigned I = Expressions.size();
52*0b57cec5SDimitry Andric   Expressions.push_back(E);
53*0b57cec5SDimitry Andric   ExpressionIndices[E] = I;
54*0b57cec5SDimitry Andric   return Counter::getExpression(I);
55*0b57cec5SDimitry Andric }
56*0b57cec5SDimitry Andric 
57*0b57cec5SDimitry Andric void CounterExpressionBuilder::extractTerms(Counter C, int Factor,
58*0b57cec5SDimitry Andric                                             SmallVectorImpl<Term> &Terms) {
59*0b57cec5SDimitry Andric   switch (C.getKind()) {
60*0b57cec5SDimitry Andric   case Counter::Zero:
61*0b57cec5SDimitry Andric     break;
62*0b57cec5SDimitry Andric   case Counter::CounterValueReference:
63*0b57cec5SDimitry Andric     Terms.emplace_back(C.getCounterID(), Factor);
64*0b57cec5SDimitry Andric     break;
65*0b57cec5SDimitry Andric   case Counter::Expression:
66*0b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
67*0b57cec5SDimitry Andric     extractTerms(E.LHS, Factor, Terms);
68*0b57cec5SDimitry Andric     extractTerms(
69*0b57cec5SDimitry Andric         E.RHS, E.Kind == CounterExpression::Subtract ? -Factor : Factor, Terms);
70*0b57cec5SDimitry Andric     break;
71*0b57cec5SDimitry Andric   }
72*0b57cec5SDimitry Andric }
73*0b57cec5SDimitry Andric 
74*0b57cec5SDimitry Andric Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
75*0b57cec5SDimitry Andric   // Gather constant terms.
76*0b57cec5SDimitry Andric   SmallVector<Term, 32> Terms;
77*0b57cec5SDimitry Andric   extractTerms(ExpressionTree, +1, Terms);
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric   // If there are no terms, this is just a zero. The algorithm below assumes at
80*0b57cec5SDimitry Andric   // least one term.
81*0b57cec5SDimitry Andric   if (Terms.size() == 0)
82*0b57cec5SDimitry Andric     return Counter::getZero();
83*0b57cec5SDimitry Andric 
84*0b57cec5SDimitry Andric   // Group the terms by counter ID.
85*0b57cec5SDimitry Andric   llvm::sort(Terms, [](const Term &LHS, const Term &RHS) {
86*0b57cec5SDimitry Andric     return LHS.CounterID < RHS.CounterID;
87*0b57cec5SDimitry Andric   });
88*0b57cec5SDimitry Andric 
89*0b57cec5SDimitry Andric   // Combine terms by counter ID to eliminate counters that sum to zero.
90*0b57cec5SDimitry Andric   auto Prev = Terms.begin();
91*0b57cec5SDimitry Andric   for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
92*0b57cec5SDimitry Andric     if (I->CounterID == Prev->CounterID) {
93*0b57cec5SDimitry Andric       Prev->Factor += I->Factor;
94*0b57cec5SDimitry Andric       continue;
95*0b57cec5SDimitry Andric     }
96*0b57cec5SDimitry Andric     ++Prev;
97*0b57cec5SDimitry Andric     *Prev = *I;
98*0b57cec5SDimitry Andric   }
99*0b57cec5SDimitry Andric   Terms.erase(++Prev, Terms.end());
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric   Counter C;
102*0b57cec5SDimitry Andric   // Create additions. We do this before subtractions to avoid constructs like
103*0b57cec5SDimitry Andric   // ((0 - X) + Y), as opposed to (Y - X).
104*0b57cec5SDimitry Andric   for (auto T : Terms) {
105*0b57cec5SDimitry Andric     if (T.Factor <= 0)
106*0b57cec5SDimitry Andric       continue;
107*0b57cec5SDimitry Andric     for (int I = 0; I < T.Factor; ++I)
108*0b57cec5SDimitry Andric       if (C.isZero())
109*0b57cec5SDimitry Andric         C = Counter::getCounter(T.CounterID);
110*0b57cec5SDimitry Andric       else
111*0b57cec5SDimitry Andric         C = get(CounterExpression(CounterExpression::Add, C,
112*0b57cec5SDimitry Andric                                   Counter::getCounter(T.CounterID)));
113*0b57cec5SDimitry Andric   }
114*0b57cec5SDimitry Andric 
115*0b57cec5SDimitry Andric   // Create subtractions.
116*0b57cec5SDimitry Andric   for (auto T : Terms) {
117*0b57cec5SDimitry Andric     if (T.Factor >= 0)
118*0b57cec5SDimitry Andric       continue;
119*0b57cec5SDimitry Andric     for (int I = 0; I < -T.Factor; ++I)
120*0b57cec5SDimitry Andric       C = get(CounterExpression(CounterExpression::Subtract, C,
121*0b57cec5SDimitry Andric                                 Counter::getCounter(T.CounterID)));
122*0b57cec5SDimitry Andric   }
123*0b57cec5SDimitry Andric   return C;
124*0b57cec5SDimitry Andric }
125*0b57cec5SDimitry Andric 
126*0b57cec5SDimitry Andric Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
127*0b57cec5SDimitry Andric   return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
128*0b57cec5SDimitry Andric }
129*0b57cec5SDimitry Andric 
130*0b57cec5SDimitry Andric Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
131*0b57cec5SDimitry Andric   return simplify(
132*0b57cec5SDimitry Andric       get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
133*0b57cec5SDimitry Andric }
134*0b57cec5SDimitry Andric 
135*0b57cec5SDimitry Andric void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
136*0b57cec5SDimitry Andric   switch (C.getKind()) {
137*0b57cec5SDimitry Andric   case Counter::Zero:
138*0b57cec5SDimitry Andric     OS << '0';
139*0b57cec5SDimitry Andric     return;
140*0b57cec5SDimitry Andric   case Counter::CounterValueReference:
141*0b57cec5SDimitry Andric     OS << '#' << C.getCounterID();
142*0b57cec5SDimitry Andric     break;
143*0b57cec5SDimitry Andric   case Counter::Expression: {
144*0b57cec5SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
145*0b57cec5SDimitry Andric       return;
146*0b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
147*0b57cec5SDimitry Andric     OS << '(';
148*0b57cec5SDimitry Andric     dump(E.LHS, OS);
149*0b57cec5SDimitry Andric     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
150*0b57cec5SDimitry Andric     dump(E.RHS, OS);
151*0b57cec5SDimitry Andric     OS << ')';
152*0b57cec5SDimitry Andric     break;
153*0b57cec5SDimitry Andric   }
154*0b57cec5SDimitry Andric   }
155*0b57cec5SDimitry Andric   if (CounterValues.empty())
156*0b57cec5SDimitry Andric     return;
157*0b57cec5SDimitry Andric   Expected<int64_t> Value = evaluate(C);
158*0b57cec5SDimitry Andric   if (auto E = Value.takeError()) {
159*0b57cec5SDimitry Andric     consumeError(std::move(E));
160*0b57cec5SDimitry Andric     return;
161*0b57cec5SDimitry Andric   }
162*0b57cec5SDimitry Andric   OS << '[' << *Value << ']';
163*0b57cec5SDimitry Andric }
164*0b57cec5SDimitry Andric 
165*0b57cec5SDimitry Andric Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
166*0b57cec5SDimitry Andric   switch (C.getKind()) {
167*0b57cec5SDimitry Andric   case Counter::Zero:
168*0b57cec5SDimitry Andric     return 0;
169*0b57cec5SDimitry Andric   case Counter::CounterValueReference:
170*0b57cec5SDimitry Andric     if (C.getCounterID() >= CounterValues.size())
171*0b57cec5SDimitry Andric       return errorCodeToError(errc::argument_out_of_domain);
172*0b57cec5SDimitry Andric     return CounterValues[C.getCounterID()];
173*0b57cec5SDimitry Andric   case Counter::Expression: {
174*0b57cec5SDimitry Andric     if (C.getExpressionID() >= Expressions.size())
175*0b57cec5SDimitry Andric       return errorCodeToError(errc::argument_out_of_domain);
176*0b57cec5SDimitry Andric     const auto &E = Expressions[C.getExpressionID()];
177*0b57cec5SDimitry Andric     Expected<int64_t> LHS = evaluate(E.LHS);
178*0b57cec5SDimitry Andric     if (!LHS)
179*0b57cec5SDimitry Andric       return LHS;
180*0b57cec5SDimitry Andric     Expected<int64_t> RHS = evaluate(E.RHS);
181*0b57cec5SDimitry Andric     if (!RHS)
182*0b57cec5SDimitry Andric       return RHS;
183*0b57cec5SDimitry Andric     return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
184*0b57cec5SDimitry Andric   }
185*0b57cec5SDimitry Andric   }
186*0b57cec5SDimitry Andric   llvm_unreachable("Unhandled CounterKind");
187*0b57cec5SDimitry Andric }
188*0b57cec5SDimitry Andric 
189*0b57cec5SDimitry Andric void FunctionRecordIterator::skipOtherFiles() {
190*0b57cec5SDimitry Andric   while (Current != Records.end() && !Filename.empty() &&
191*0b57cec5SDimitry Andric          Filename != Current->Filenames[0])
192*0b57cec5SDimitry Andric     ++Current;
193*0b57cec5SDimitry Andric   if (Current == Records.end())
194*0b57cec5SDimitry Andric     *this = FunctionRecordIterator();
195*0b57cec5SDimitry Andric }
196*0b57cec5SDimitry Andric 
197*0b57cec5SDimitry Andric Error CoverageMapping::loadFunctionRecord(
198*0b57cec5SDimitry Andric     const CoverageMappingRecord &Record,
199*0b57cec5SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
200*0b57cec5SDimitry Andric   StringRef OrigFuncName = Record.FunctionName;
201*0b57cec5SDimitry Andric   if (OrigFuncName.empty())
202*0b57cec5SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
203*0b57cec5SDimitry Andric 
204*0b57cec5SDimitry Andric   if (Record.Filenames.empty())
205*0b57cec5SDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
206*0b57cec5SDimitry Andric   else
207*0b57cec5SDimitry Andric     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric   CounterMappingContext Ctx(Record.Expressions);
210*0b57cec5SDimitry Andric 
211*0b57cec5SDimitry Andric   std::vector<uint64_t> Counts;
212*0b57cec5SDimitry Andric   if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName,
213*0b57cec5SDimitry Andric                                                 Record.FunctionHash, Counts)) {
214*0b57cec5SDimitry Andric     instrprof_error IPE = InstrProfError::take(std::move(E));
215*0b57cec5SDimitry Andric     if (IPE == instrprof_error::hash_mismatch) {
216*0b57cec5SDimitry Andric       FuncHashMismatches.emplace_back(Record.FunctionName, Record.FunctionHash);
217*0b57cec5SDimitry Andric       return Error::success();
218*0b57cec5SDimitry Andric     } else if (IPE != instrprof_error::unknown_function)
219*0b57cec5SDimitry Andric       return make_error<InstrProfError>(IPE);
220*0b57cec5SDimitry Andric     Counts.assign(Record.MappingRegions.size(), 0);
221*0b57cec5SDimitry Andric   }
222*0b57cec5SDimitry Andric   Ctx.setCounts(Counts);
223*0b57cec5SDimitry Andric 
224*0b57cec5SDimitry Andric   assert(!Record.MappingRegions.empty() && "Function has no regions");
225*0b57cec5SDimitry Andric 
226*0b57cec5SDimitry Andric   // This coverage record is a zero region for a function that's unused in
227*0b57cec5SDimitry Andric   // some TU, but used in a different TU. Ignore it. The coverage maps from the
228*0b57cec5SDimitry Andric   // the other TU will either be loaded (providing full region counts) or they
229*0b57cec5SDimitry Andric   // won't (in which case we don't unintuitively report functions as uncovered
230*0b57cec5SDimitry Andric   // when they have non-zero counts in the profile).
231*0b57cec5SDimitry Andric   if (Record.MappingRegions.size() == 1 &&
232*0b57cec5SDimitry Andric       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
233*0b57cec5SDimitry Andric     return Error::success();
234*0b57cec5SDimitry Andric 
235*0b57cec5SDimitry Andric   FunctionRecord Function(OrigFuncName, Record.Filenames);
236*0b57cec5SDimitry Andric   for (const auto &Region : Record.MappingRegions) {
237*0b57cec5SDimitry Andric     Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
238*0b57cec5SDimitry Andric     if (auto E = ExecutionCount.takeError()) {
239*0b57cec5SDimitry Andric       consumeError(std::move(E));
240*0b57cec5SDimitry Andric       return Error::success();
241*0b57cec5SDimitry Andric     }
242*0b57cec5SDimitry Andric     Function.pushRegion(Region, *ExecutionCount);
243*0b57cec5SDimitry Andric   }
244*0b57cec5SDimitry Andric 
245*0b57cec5SDimitry Andric   // Don't create records for (filenames, function) pairs we've already seen.
246*0b57cec5SDimitry Andric   auto FilenamesHash = hash_combine_range(Record.Filenames.begin(),
247*0b57cec5SDimitry Andric                                           Record.Filenames.end());
248*0b57cec5SDimitry Andric   if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
249*0b57cec5SDimitry Andric     return Error::success();
250*0b57cec5SDimitry Andric 
251*0b57cec5SDimitry Andric   Functions.push_back(std::move(Function));
252*0b57cec5SDimitry Andric   return Error::success();
253*0b57cec5SDimitry Andric }
254*0b57cec5SDimitry Andric 
255*0b57cec5SDimitry Andric Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
256*0b57cec5SDimitry Andric     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
257*0b57cec5SDimitry Andric     IndexedInstrProfReader &ProfileReader) {
258*0b57cec5SDimitry Andric   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
259*0b57cec5SDimitry Andric 
260*0b57cec5SDimitry Andric   for (const auto &CoverageReader : CoverageReaders) {
261*0b57cec5SDimitry Andric     for (auto RecordOrErr : *CoverageReader) {
262*0b57cec5SDimitry Andric       if (Error E = RecordOrErr.takeError())
263*0b57cec5SDimitry Andric         return std::move(E);
264*0b57cec5SDimitry Andric       const auto &Record = *RecordOrErr;
265*0b57cec5SDimitry Andric       if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
266*0b57cec5SDimitry Andric         return std::move(E);
267*0b57cec5SDimitry Andric     }
268*0b57cec5SDimitry Andric   }
269*0b57cec5SDimitry Andric 
270*0b57cec5SDimitry Andric   return std::move(Coverage);
271*0b57cec5SDimitry Andric }
272*0b57cec5SDimitry Andric 
273*0b57cec5SDimitry Andric Expected<std::unique_ptr<CoverageMapping>>
274*0b57cec5SDimitry Andric CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
275*0b57cec5SDimitry Andric                       StringRef ProfileFilename, ArrayRef<StringRef> Arches) {
276*0b57cec5SDimitry Andric   auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
277*0b57cec5SDimitry Andric   if (Error E = ProfileReaderOrErr.takeError())
278*0b57cec5SDimitry Andric     return std::move(E);
279*0b57cec5SDimitry Andric   auto ProfileReader = std::move(ProfileReaderOrErr.get());
280*0b57cec5SDimitry Andric 
281*0b57cec5SDimitry Andric   SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers;
282*0b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
283*0b57cec5SDimitry Andric   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
284*0b57cec5SDimitry Andric     auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(File.value());
285*0b57cec5SDimitry Andric     if (std::error_code EC = CovMappingBufOrErr.getError())
286*0b57cec5SDimitry Andric       return errorCodeToError(EC);
287*0b57cec5SDimitry Andric     StringRef Arch = Arches.empty() ? StringRef() : Arches[File.index()];
288*0b57cec5SDimitry Andric     MemoryBufferRef CovMappingBufRef =
289*0b57cec5SDimitry Andric         CovMappingBufOrErr.get()->getMemBufferRef();
290*0b57cec5SDimitry Andric     auto CoverageReadersOrErr =
291*0b57cec5SDimitry Andric         BinaryCoverageReader::create(CovMappingBufRef, Arch, Buffers);
292*0b57cec5SDimitry Andric     if (Error E = CoverageReadersOrErr.takeError())
293*0b57cec5SDimitry Andric       return std::move(E);
294*0b57cec5SDimitry Andric     for (auto &Reader : CoverageReadersOrErr.get())
295*0b57cec5SDimitry Andric       Readers.push_back(std::move(Reader));
296*0b57cec5SDimitry Andric     Buffers.push_back(std::move(CovMappingBufOrErr.get()));
297*0b57cec5SDimitry Andric   }
298*0b57cec5SDimitry Andric   return load(Readers, *ProfileReader);
299*0b57cec5SDimitry Andric }
300*0b57cec5SDimitry Andric 
301*0b57cec5SDimitry Andric namespace {
302*0b57cec5SDimitry Andric 
303*0b57cec5SDimitry Andric /// Distributes functions into instantiation sets.
304*0b57cec5SDimitry Andric ///
305*0b57cec5SDimitry Andric /// An instantiation set is a collection of functions that have the same source
306*0b57cec5SDimitry Andric /// code, ie, template functions specializations.
307*0b57cec5SDimitry Andric class FunctionInstantiationSetCollector {
308*0b57cec5SDimitry Andric   using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;
309*0b57cec5SDimitry Andric   MapT InstantiatedFunctions;
310*0b57cec5SDimitry Andric 
311*0b57cec5SDimitry Andric public:
312*0b57cec5SDimitry Andric   void insert(const FunctionRecord &Function, unsigned FileID) {
313*0b57cec5SDimitry Andric     auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
314*0b57cec5SDimitry Andric     while (I != E && I->FileID != FileID)
315*0b57cec5SDimitry Andric       ++I;
316*0b57cec5SDimitry Andric     assert(I != E && "function does not cover the given file");
317*0b57cec5SDimitry Andric     auto &Functions = InstantiatedFunctions[I->startLoc()];
318*0b57cec5SDimitry Andric     Functions.push_back(&Function);
319*0b57cec5SDimitry Andric   }
320*0b57cec5SDimitry Andric 
321*0b57cec5SDimitry Andric   MapT::iterator begin() { return InstantiatedFunctions.begin(); }
322*0b57cec5SDimitry Andric   MapT::iterator end() { return InstantiatedFunctions.end(); }
323*0b57cec5SDimitry Andric };
324*0b57cec5SDimitry Andric 
325*0b57cec5SDimitry Andric class SegmentBuilder {
326*0b57cec5SDimitry Andric   std::vector<CoverageSegment> &Segments;
327*0b57cec5SDimitry Andric   SmallVector<const CountedRegion *, 8> ActiveRegions;
328*0b57cec5SDimitry Andric 
329*0b57cec5SDimitry Andric   SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
330*0b57cec5SDimitry Andric 
331*0b57cec5SDimitry Andric   /// Emit a segment with the count from \p Region starting at \p StartLoc.
332*0b57cec5SDimitry Andric   //
333*0b57cec5SDimitry Andric   /// \p IsRegionEntry: The segment is at the start of a new non-gap region.
334*0b57cec5SDimitry Andric   /// \p EmitSkippedRegion: The segment must be emitted as a skipped region.
335*0b57cec5SDimitry Andric   void startSegment(const CountedRegion &Region, LineColPair StartLoc,
336*0b57cec5SDimitry Andric                     bool IsRegionEntry, bool EmitSkippedRegion = false) {
337*0b57cec5SDimitry Andric     bool HasCount = !EmitSkippedRegion &&
338*0b57cec5SDimitry Andric                     (Region.Kind != CounterMappingRegion::SkippedRegion);
339*0b57cec5SDimitry Andric 
340*0b57cec5SDimitry Andric     // If the new segment wouldn't affect coverage rendering, skip it.
341*0b57cec5SDimitry Andric     if (!Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {
342*0b57cec5SDimitry Andric       const auto &Last = Segments.back();
343*0b57cec5SDimitry Andric       if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount &&
344*0b57cec5SDimitry Andric           !Last.IsRegionEntry)
345*0b57cec5SDimitry Andric         return;
346*0b57cec5SDimitry Andric     }
347*0b57cec5SDimitry Andric 
348*0b57cec5SDimitry Andric     if (HasCount)
349*0b57cec5SDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second,
350*0b57cec5SDimitry Andric                             Region.ExecutionCount, IsRegionEntry,
351*0b57cec5SDimitry Andric                             Region.Kind == CounterMappingRegion::GapRegion);
352*0b57cec5SDimitry Andric     else
353*0b57cec5SDimitry Andric       Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);
354*0b57cec5SDimitry Andric 
355*0b57cec5SDimitry Andric     LLVM_DEBUG({
356*0b57cec5SDimitry Andric       const auto &Last = Segments.back();
357*0b57cec5SDimitry Andric       dbgs() << "Segment at " << Last.Line << ":" << Last.Col
358*0b57cec5SDimitry Andric              << " (count = " << Last.Count << ")"
359*0b57cec5SDimitry Andric              << (Last.IsRegionEntry ? ", RegionEntry" : "")
360*0b57cec5SDimitry Andric              << (!Last.HasCount ? ", Skipped" : "")
361*0b57cec5SDimitry Andric              << (Last.IsGapRegion ? ", Gap" : "") << "\n";
362*0b57cec5SDimitry Andric     });
363*0b57cec5SDimitry Andric   }
364*0b57cec5SDimitry Andric 
365*0b57cec5SDimitry Andric   /// Emit segments for active regions which end before \p Loc.
366*0b57cec5SDimitry Andric   ///
367*0b57cec5SDimitry Andric   /// \p Loc: The start location of the next region. If None, all active
368*0b57cec5SDimitry Andric   /// regions are completed.
369*0b57cec5SDimitry Andric   /// \p FirstCompletedRegion: Index of the first completed region.
370*0b57cec5SDimitry Andric   void completeRegionsUntil(Optional<LineColPair> Loc,
371*0b57cec5SDimitry Andric                             unsigned FirstCompletedRegion) {
372*0b57cec5SDimitry Andric     // Sort the completed regions by end location. This makes it simple to
373*0b57cec5SDimitry Andric     // emit closing segments in sorted order.
374*0b57cec5SDimitry Andric     auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;
375*0b57cec5SDimitry Andric     std::stable_sort(CompletedRegionsIt, ActiveRegions.end(),
376*0b57cec5SDimitry Andric                       [](const CountedRegion *L, const CountedRegion *R) {
377*0b57cec5SDimitry Andric                         return L->endLoc() < R->endLoc();
378*0b57cec5SDimitry Andric                       });
379*0b57cec5SDimitry Andric 
380*0b57cec5SDimitry Andric     // Emit segments for all completed regions.
381*0b57cec5SDimitry Andric     for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E;
382*0b57cec5SDimitry Andric          ++I) {
383*0b57cec5SDimitry Andric       const auto *CompletedRegion = ActiveRegions[I];
384*0b57cec5SDimitry Andric       assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&
385*0b57cec5SDimitry Andric              "Completed region ends after start of new region");
386*0b57cec5SDimitry Andric 
387*0b57cec5SDimitry Andric       const auto *PrevCompletedRegion = ActiveRegions[I - 1];
388*0b57cec5SDimitry Andric       auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();
389*0b57cec5SDimitry Andric 
390*0b57cec5SDimitry Andric       // Don't emit any more segments if they start where the new region begins.
391*0b57cec5SDimitry Andric       if (Loc && CompletedSegmentLoc == *Loc)
392*0b57cec5SDimitry Andric         break;
393*0b57cec5SDimitry Andric 
394*0b57cec5SDimitry Andric       // Don't emit a segment if the next completed region ends at the same
395*0b57cec5SDimitry Andric       // location as this one.
396*0b57cec5SDimitry Andric       if (CompletedSegmentLoc == CompletedRegion->endLoc())
397*0b57cec5SDimitry Andric         continue;
398*0b57cec5SDimitry Andric 
399*0b57cec5SDimitry Andric       // Use the count from the last completed region which ends at this loc.
400*0b57cec5SDimitry Andric       for (unsigned J = I + 1; J < E; ++J)
401*0b57cec5SDimitry Andric         if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())
402*0b57cec5SDimitry Andric           CompletedRegion = ActiveRegions[J];
403*0b57cec5SDimitry Andric 
404*0b57cec5SDimitry Andric       startSegment(*CompletedRegion, CompletedSegmentLoc, false);
405*0b57cec5SDimitry Andric     }
406*0b57cec5SDimitry Andric 
407*0b57cec5SDimitry Andric     auto Last = ActiveRegions.back();
408*0b57cec5SDimitry Andric     if (FirstCompletedRegion && Last->endLoc() != *Loc) {
409*0b57cec5SDimitry Andric       // If there's a gap after the end of the last completed region and the
410*0b57cec5SDimitry Andric       // start of the new region, use the last active region to fill the gap.
411*0b57cec5SDimitry Andric       startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(),
412*0b57cec5SDimitry Andric                    false);
413*0b57cec5SDimitry Andric     } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) {
414*0b57cec5SDimitry Andric       // Emit a skipped segment if there are no more active regions. This
415*0b57cec5SDimitry Andric       // ensures that gaps between functions are marked correctly.
416*0b57cec5SDimitry Andric       startSegment(*Last, Last->endLoc(), false, true);
417*0b57cec5SDimitry Andric     }
418*0b57cec5SDimitry Andric 
419*0b57cec5SDimitry Andric     // Pop the completed regions.
420*0b57cec5SDimitry Andric     ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end());
421*0b57cec5SDimitry Andric   }
422*0b57cec5SDimitry Andric 
423*0b57cec5SDimitry Andric   void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
424*0b57cec5SDimitry Andric     for (const auto &CR : enumerate(Regions)) {
425*0b57cec5SDimitry Andric       auto CurStartLoc = CR.value().startLoc();
426*0b57cec5SDimitry Andric 
427*0b57cec5SDimitry Andric       // Active regions which end before the current region need to be popped.
428*0b57cec5SDimitry Andric       auto CompletedRegions =
429*0b57cec5SDimitry Andric           std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),
430*0b57cec5SDimitry Andric                                 [&](const CountedRegion *Region) {
431*0b57cec5SDimitry Andric                                   return !(Region->endLoc() <= CurStartLoc);
432*0b57cec5SDimitry Andric                                 });
433*0b57cec5SDimitry Andric       if (CompletedRegions != ActiveRegions.end()) {
434*0b57cec5SDimitry Andric         unsigned FirstCompletedRegion =
435*0b57cec5SDimitry Andric             std::distance(ActiveRegions.begin(), CompletedRegions);
436*0b57cec5SDimitry Andric         completeRegionsUntil(CurStartLoc, FirstCompletedRegion);
437*0b57cec5SDimitry Andric       }
438*0b57cec5SDimitry Andric 
439*0b57cec5SDimitry Andric       bool GapRegion = CR.value().Kind == CounterMappingRegion::GapRegion;
440*0b57cec5SDimitry Andric 
441*0b57cec5SDimitry Andric       // Try to emit a segment for the current region.
442*0b57cec5SDimitry Andric       if (CurStartLoc == CR.value().endLoc()) {
443*0b57cec5SDimitry Andric         // Avoid making zero-length regions active. If it's the last region,
444*0b57cec5SDimitry Andric         // emit a skipped segment. Otherwise use its predecessor's count.
445*0b57cec5SDimitry Andric         const bool Skipped = (CR.index() + 1) == Regions.size();
446*0b57cec5SDimitry Andric         startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),
447*0b57cec5SDimitry Andric                      CurStartLoc, !GapRegion, Skipped);
448*0b57cec5SDimitry Andric         continue;
449*0b57cec5SDimitry Andric       }
450*0b57cec5SDimitry Andric       if (CR.index() + 1 == Regions.size() ||
451*0b57cec5SDimitry Andric           CurStartLoc != Regions[CR.index() + 1].startLoc()) {
452*0b57cec5SDimitry Andric         // Emit a segment if the next region doesn't start at the same location
453*0b57cec5SDimitry Andric         // as this one.
454*0b57cec5SDimitry Andric         startSegment(CR.value(), CurStartLoc, !GapRegion);
455*0b57cec5SDimitry Andric       }
456*0b57cec5SDimitry Andric 
457*0b57cec5SDimitry Andric       // This region is active (i.e not completed).
458*0b57cec5SDimitry Andric       ActiveRegions.push_back(&CR.value());
459*0b57cec5SDimitry Andric     }
460*0b57cec5SDimitry Andric 
461*0b57cec5SDimitry Andric     // Complete any remaining active regions.
462*0b57cec5SDimitry Andric     if (!ActiveRegions.empty())
463*0b57cec5SDimitry Andric       completeRegionsUntil(None, 0);
464*0b57cec5SDimitry Andric   }
465*0b57cec5SDimitry Andric 
466*0b57cec5SDimitry Andric   /// Sort a nested sequence of regions from a single file.
467*0b57cec5SDimitry Andric   static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
468*0b57cec5SDimitry Andric     llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) {
469*0b57cec5SDimitry Andric       if (LHS.startLoc() != RHS.startLoc())
470*0b57cec5SDimitry Andric         return LHS.startLoc() < RHS.startLoc();
471*0b57cec5SDimitry Andric       if (LHS.endLoc() != RHS.endLoc())
472*0b57cec5SDimitry Andric         // When LHS completely contains RHS, we sort LHS first.
473*0b57cec5SDimitry Andric         return RHS.endLoc() < LHS.endLoc();
474*0b57cec5SDimitry Andric       // If LHS and RHS cover the same area, we need to sort them according
475*0b57cec5SDimitry Andric       // to their kinds so that the most suitable region will become "active"
476*0b57cec5SDimitry Andric       // in combineRegions(). Because we accumulate counter values only from
477*0b57cec5SDimitry Andric       // regions of the same kind as the first region of the area, prefer
478*0b57cec5SDimitry Andric       // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
479*0b57cec5SDimitry Andric       static_assert(CounterMappingRegion::CodeRegion <
480*0b57cec5SDimitry Andric                             CounterMappingRegion::ExpansionRegion &&
481*0b57cec5SDimitry Andric                         CounterMappingRegion::ExpansionRegion <
482*0b57cec5SDimitry Andric                             CounterMappingRegion::SkippedRegion,
483*0b57cec5SDimitry Andric                     "Unexpected order of region kind values");
484*0b57cec5SDimitry Andric       return LHS.Kind < RHS.Kind;
485*0b57cec5SDimitry Andric     });
486*0b57cec5SDimitry Andric   }
487*0b57cec5SDimitry Andric 
488*0b57cec5SDimitry Andric   /// Combine counts of regions which cover the same area.
489*0b57cec5SDimitry Andric   static ArrayRef<CountedRegion>
490*0b57cec5SDimitry Andric   combineRegions(MutableArrayRef<CountedRegion> Regions) {
491*0b57cec5SDimitry Andric     if (Regions.empty())
492*0b57cec5SDimitry Andric       return Regions;
493*0b57cec5SDimitry Andric     auto Active = Regions.begin();
494*0b57cec5SDimitry Andric     auto End = Regions.end();
495*0b57cec5SDimitry Andric     for (auto I = Regions.begin() + 1; I != End; ++I) {
496*0b57cec5SDimitry Andric       if (Active->startLoc() != I->startLoc() ||
497*0b57cec5SDimitry Andric           Active->endLoc() != I->endLoc()) {
498*0b57cec5SDimitry Andric         // Shift to the next region.
499*0b57cec5SDimitry Andric         ++Active;
500*0b57cec5SDimitry Andric         if (Active != I)
501*0b57cec5SDimitry Andric           *Active = *I;
502*0b57cec5SDimitry Andric         continue;
503*0b57cec5SDimitry Andric       }
504*0b57cec5SDimitry Andric       // Merge duplicate region.
505*0b57cec5SDimitry Andric       // If CodeRegions and ExpansionRegions cover the same area, it's probably
506*0b57cec5SDimitry Andric       // a macro which is fully expanded to another macro. In that case, we need
507*0b57cec5SDimitry Andric       // to accumulate counts only from CodeRegions, or else the area will be
508*0b57cec5SDimitry Andric       // counted twice.
509*0b57cec5SDimitry Andric       // On the other hand, a macro may have a nested macro in its body. If the
510*0b57cec5SDimitry Andric       // outer macro is used several times, the ExpansionRegion for the nested
511*0b57cec5SDimitry Andric       // macro will also be added several times. These ExpansionRegions cover
512*0b57cec5SDimitry Andric       // the same source locations and have to be combined to reach the correct
513*0b57cec5SDimitry Andric       // value for that area.
514*0b57cec5SDimitry Andric       // We add counts of the regions of the same kind as the active region
515*0b57cec5SDimitry Andric       // to handle the both situations.
516*0b57cec5SDimitry Andric       if (I->Kind == Active->Kind)
517*0b57cec5SDimitry Andric         Active->ExecutionCount += I->ExecutionCount;
518*0b57cec5SDimitry Andric     }
519*0b57cec5SDimitry Andric     return Regions.drop_back(std::distance(++Active, End));
520*0b57cec5SDimitry Andric   }
521*0b57cec5SDimitry Andric 
522*0b57cec5SDimitry Andric public:
523*0b57cec5SDimitry Andric   /// Build a sorted list of CoverageSegments from a list of Regions.
524*0b57cec5SDimitry Andric   static std::vector<CoverageSegment>
525*0b57cec5SDimitry Andric   buildSegments(MutableArrayRef<CountedRegion> Regions) {
526*0b57cec5SDimitry Andric     std::vector<CoverageSegment> Segments;
527*0b57cec5SDimitry Andric     SegmentBuilder Builder(Segments);
528*0b57cec5SDimitry Andric 
529*0b57cec5SDimitry Andric     sortNestedRegions(Regions);
530*0b57cec5SDimitry Andric     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
531*0b57cec5SDimitry Andric 
532*0b57cec5SDimitry Andric     LLVM_DEBUG({
533*0b57cec5SDimitry Andric       dbgs() << "Combined regions:\n";
534*0b57cec5SDimitry Andric       for (const auto &CR : CombinedRegions)
535*0b57cec5SDimitry Andric         dbgs() << "  " << CR.LineStart << ":" << CR.ColumnStart << " -> "
536*0b57cec5SDimitry Andric                << CR.LineEnd << ":" << CR.ColumnEnd
537*0b57cec5SDimitry Andric                << " (count=" << CR.ExecutionCount << ")\n";
538*0b57cec5SDimitry Andric     });
539*0b57cec5SDimitry Andric 
540*0b57cec5SDimitry Andric     Builder.buildSegmentsImpl(CombinedRegions);
541*0b57cec5SDimitry Andric 
542*0b57cec5SDimitry Andric #ifndef NDEBUG
543*0b57cec5SDimitry Andric     for (unsigned I = 1, E = Segments.size(); I < E; ++I) {
544*0b57cec5SDimitry Andric       const auto &L = Segments[I - 1];
545*0b57cec5SDimitry Andric       const auto &R = Segments[I];
546*0b57cec5SDimitry Andric       if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) {
547*0b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col
548*0b57cec5SDimitry Andric                           << " followed by " << R.Line << ":" << R.Col << "\n");
549*0b57cec5SDimitry Andric         assert(false && "Coverage segments not unique or sorted");
550*0b57cec5SDimitry Andric       }
551*0b57cec5SDimitry Andric     }
552*0b57cec5SDimitry Andric #endif
553*0b57cec5SDimitry Andric 
554*0b57cec5SDimitry Andric     return Segments;
555*0b57cec5SDimitry Andric   }
556*0b57cec5SDimitry Andric };
557*0b57cec5SDimitry Andric 
558*0b57cec5SDimitry Andric } // end anonymous namespace
559*0b57cec5SDimitry Andric 
560*0b57cec5SDimitry Andric std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
561*0b57cec5SDimitry Andric   std::vector<StringRef> Filenames;
562*0b57cec5SDimitry Andric   for (const auto &Function : getCoveredFunctions())
563*0b57cec5SDimitry Andric     Filenames.insert(Filenames.end(), Function.Filenames.begin(),
564*0b57cec5SDimitry Andric                      Function.Filenames.end());
565*0b57cec5SDimitry Andric   llvm::sort(Filenames);
566*0b57cec5SDimitry Andric   auto Last = std::unique(Filenames.begin(), Filenames.end());
567*0b57cec5SDimitry Andric   Filenames.erase(Last, Filenames.end());
568*0b57cec5SDimitry Andric   return Filenames;
569*0b57cec5SDimitry Andric }
570*0b57cec5SDimitry Andric 
571*0b57cec5SDimitry Andric static SmallBitVector gatherFileIDs(StringRef SourceFile,
572*0b57cec5SDimitry Andric                                     const FunctionRecord &Function) {
573*0b57cec5SDimitry Andric   SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
574*0b57cec5SDimitry Andric   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
575*0b57cec5SDimitry Andric     if (SourceFile == Function.Filenames[I])
576*0b57cec5SDimitry Andric       FilenameEquivalence[I] = true;
577*0b57cec5SDimitry Andric   return FilenameEquivalence;
578*0b57cec5SDimitry Andric }
579*0b57cec5SDimitry Andric 
580*0b57cec5SDimitry Andric /// Return the ID of the file where the definition of the function is located.
581*0b57cec5SDimitry Andric static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
582*0b57cec5SDimitry Andric   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
583*0b57cec5SDimitry Andric   for (const auto &CR : Function.CountedRegions)
584*0b57cec5SDimitry Andric     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
585*0b57cec5SDimitry Andric       IsNotExpandedFile[CR.ExpandedFileID] = false;
586*0b57cec5SDimitry Andric   int I = IsNotExpandedFile.find_first();
587*0b57cec5SDimitry Andric   if (I == -1)
588*0b57cec5SDimitry Andric     return None;
589*0b57cec5SDimitry Andric   return I;
590*0b57cec5SDimitry Andric }
591*0b57cec5SDimitry Andric 
592*0b57cec5SDimitry Andric /// Check if SourceFile is the file that contains the definition of
593*0b57cec5SDimitry Andric /// the Function. Return the ID of the file in that case or None otherwise.
594*0b57cec5SDimitry Andric static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
595*0b57cec5SDimitry Andric                                              const FunctionRecord &Function) {
596*0b57cec5SDimitry Andric   Optional<unsigned> I = findMainViewFileID(Function);
597*0b57cec5SDimitry Andric   if (I && SourceFile == Function.Filenames[*I])
598*0b57cec5SDimitry Andric     return I;
599*0b57cec5SDimitry Andric   return None;
600*0b57cec5SDimitry Andric }
601*0b57cec5SDimitry Andric 
602*0b57cec5SDimitry Andric static bool isExpansion(const CountedRegion &R, unsigned FileID) {
603*0b57cec5SDimitry Andric   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
604*0b57cec5SDimitry Andric }
605*0b57cec5SDimitry Andric 
606*0b57cec5SDimitry Andric CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
607*0b57cec5SDimitry Andric   CoverageData FileCoverage(Filename);
608*0b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
609*0b57cec5SDimitry Andric 
610*0b57cec5SDimitry Andric   for (const auto &Function : Functions) {
611*0b57cec5SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
612*0b57cec5SDimitry Andric     auto FileIDs = gatherFileIDs(Filename, Function);
613*0b57cec5SDimitry Andric     for (const auto &CR : Function.CountedRegions)
614*0b57cec5SDimitry Andric       if (FileIDs.test(CR.FileID)) {
615*0b57cec5SDimitry Andric         Regions.push_back(CR);
616*0b57cec5SDimitry Andric         if (MainFileID && isExpansion(CR, *MainFileID))
617*0b57cec5SDimitry Andric           FileCoverage.Expansions.emplace_back(CR, Function);
618*0b57cec5SDimitry Andric       }
619*0b57cec5SDimitry Andric   }
620*0b57cec5SDimitry Andric 
621*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
622*0b57cec5SDimitry Andric   FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
623*0b57cec5SDimitry Andric 
624*0b57cec5SDimitry Andric   return FileCoverage;
625*0b57cec5SDimitry Andric }
626*0b57cec5SDimitry Andric 
627*0b57cec5SDimitry Andric std::vector<InstantiationGroup>
628*0b57cec5SDimitry Andric CoverageMapping::getInstantiationGroups(StringRef Filename) const {
629*0b57cec5SDimitry Andric   FunctionInstantiationSetCollector InstantiationSetCollector;
630*0b57cec5SDimitry Andric   for (const auto &Function : Functions) {
631*0b57cec5SDimitry Andric     auto MainFileID = findMainViewFileID(Filename, Function);
632*0b57cec5SDimitry Andric     if (!MainFileID)
633*0b57cec5SDimitry Andric       continue;
634*0b57cec5SDimitry Andric     InstantiationSetCollector.insert(Function, *MainFileID);
635*0b57cec5SDimitry Andric   }
636*0b57cec5SDimitry Andric 
637*0b57cec5SDimitry Andric   std::vector<InstantiationGroup> Result;
638*0b57cec5SDimitry Andric   for (auto &InstantiationSet : InstantiationSetCollector) {
639*0b57cec5SDimitry Andric     InstantiationGroup IG{InstantiationSet.first.first,
640*0b57cec5SDimitry Andric                           InstantiationSet.first.second,
641*0b57cec5SDimitry Andric                           std::move(InstantiationSet.second)};
642*0b57cec5SDimitry Andric     Result.emplace_back(std::move(IG));
643*0b57cec5SDimitry Andric   }
644*0b57cec5SDimitry Andric   return Result;
645*0b57cec5SDimitry Andric }
646*0b57cec5SDimitry Andric 
647*0b57cec5SDimitry Andric CoverageData
648*0b57cec5SDimitry Andric CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
649*0b57cec5SDimitry Andric   auto MainFileID = findMainViewFileID(Function);
650*0b57cec5SDimitry Andric   if (!MainFileID)
651*0b57cec5SDimitry Andric     return CoverageData();
652*0b57cec5SDimitry Andric 
653*0b57cec5SDimitry Andric   CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
654*0b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
655*0b57cec5SDimitry Andric   for (const auto &CR : Function.CountedRegions)
656*0b57cec5SDimitry Andric     if (CR.FileID == *MainFileID) {
657*0b57cec5SDimitry Andric       Regions.push_back(CR);
658*0b57cec5SDimitry Andric       if (isExpansion(CR, *MainFileID))
659*0b57cec5SDimitry Andric         FunctionCoverage.Expansions.emplace_back(CR, Function);
660*0b57cec5SDimitry Andric     }
661*0b57cec5SDimitry Andric 
662*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
663*0b57cec5SDimitry Andric                     << "\n");
664*0b57cec5SDimitry Andric   FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
665*0b57cec5SDimitry Andric 
666*0b57cec5SDimitry Andric   return FunctionCoverage;
667*0b57cec5SDimitry Andric }
668*0b57cec5SDimitry Andric 
669*0b57cec5SDimitry Andric CoverageData CoverageMapping::getCoverageForExpansion(
670*0b57cec5SDimitry Andric     const ExpansionRecord &Expansion) const {
671*0b57cec5SDimitry Andric   CoverageData ExpansionCoverage(
672*0b57cec5SDimitry Andric       Expansion.Function.Filenames[Expansion.FileID]);
673*0b57cec5SDimitry Andric   std::vector<CountedRegion> Regions;
674*0b57cec5SDimitry Andric   for (const auto &CR : Expansion.Function.CountedRegions)
675*0b57cec5SDimitry Andric     if (CR.FileID == Expansion.FileID) {
676*0b57cec5SDimitry Andric       Regions.push_back(CR);
677*0b57cec5SDimitry Andric       if (isExpansion(CR, Expansion.FileID))
678*0b57cec5SDimitry Andric         ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
679*0b57cec5SDimitry Andric     }
680*0b57cec5SDimitry Andric 
681*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
682*0b57cec5SDimitry Andric                     << Expansion.FileID << "\n");
683*0b57cec5SDimitry Andric   ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
684*0b57cec5SDimitry Andric 
685*0b57cec5SDimitry Andric   return ExpansionCoverage;
686*0b57cec5SDimitry Andric }
687*0b57cec5SDimitry Andric 
688*0b57cec5SDimitry Andric LineCoverageStats::LineCoverageStats(
689*0b57cec5SDimitry Andric     ArrayRef<const CoverageSegment *> LineSegments,
690*0b57cec5SDimitry Andric     const CoverageSegment *WrappedSegment, unsigned Line)
691*0b57cec5SDimitry Andric     : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),
692*0b57cec5SDimitry Andric       LineSegments(LineSegments), WrappedSegment(WrappedSegment) {
693*0b57cec5SDimitry Andric   // Find the minimum number of regions which start in this line.
694*0b57cec5SDimitry Andric   unsigned MinRegionCount = 0;
695*0b57cec5SDimitry Andric   auto isStartOfRegion = [](const CoverageSegment *S) {
696*0b57cec5SDimitry Andric     return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;
697*0b57cec5SDimitry Andric   };
698*0b57cec5SDimitry Andric   for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)
699*0b57cec5SDimitry Andric     if (isStartOfRegion(LineSegments[I]))
700*0b57cec5SDimitry Andric       ++MinRegionCount;
701*0b57cec5SDimitry Andric 
702*0b57cec5SDimitry Andric   bool StartOfSkippedRegion = !LineSegments.empty() &&
703*0b57cec5SDimitry Andric                               !LineSegments.front()->HasCount &&
704*0b57cec5SDimitry Andric                               LineSegments.front()->IsRegionEntry;
705*0b57cec5SDimitry Andric 
706*0b57cec5SDimitry Andric   HasMultipleRegions = MinRegionCount > 1;
707*0b57cec5SDimitry Andric   Mapped =
708*0b57cec5SDimitry Andric       !StartOfSkippedRegion &&
709*0b57cec5SDimitry Andric       ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));
710*0b57cec5SDimitry Andric 
711*0b57cec5SDimitry Andric   if (!Mapped)
712*0b57cec5SDimitry Andric     return;
713*0b57cec5SDimitry Andric 
714*0b57cec5SDimitry Andric   // Pick the max count from the non-gap, region entry segments and the
715*0b57cec5SDimitry Andric   // wrapped count.
716*0b57cec5SDimitry Andric   if (WrappedSegment)
717*0b57cec5SDimitry Andric     ExecutionCount = WrappedSegment->Count;
718*0b57cec5SDimitry Andric   if (!MinRegionCount)
719*0b57cec5SDimitry Andric     return;
720*0b57cec5SDimitry Andric   for (const auto *LS : LineSegments)
721*0b57cec5SDimitry Andric     if (isStartOfRegion(LS))
722*0b57cec5SDimitry Andric       ExecutionCount = std::max(ExecutionCount, LS->Count);
723*0b57cec5SDimitry Andric }
724*0b57cec5SDimitry Andric 
725*0b57cec5SDimitry Andric LineCoverageIterator &LineCoverageIterator::operator++() {
726*0b57cec5SDimitry Andric   if (Next == CD.end()) {
727*0b57cec5SDimitry Andric     Stats = LineCoverageStats();
728*0b57cec5SDimitry Andric     Ended = true;
729*0b57cec5SDimitry Andric     return *this;
730*0b57cec5SDimitry Andric   }
731*0b57cec5SDimitry Andric   if (Segments.size())
732*0b57cec5SDimitry Andric     WrappedSegment = Segments.back();
733*0b57cec5SDimitry Andric   Segments.clear();
734*0b57cec5SDimitry Andric   while (Next != CD.end() && Next->Line == Line)
735*0b57cec5SDimitry Andric     Segments.push_back(&*Next++);
736*0b57cec5SDimitry Andric   Stats = LineCoverageStats(Segments, WrappedSegment, Line);
737*0b57cec5SDimitry Andric   ++Line;
738*0b57cec5SDimitry Andric   return *this;
739*0b57cec5SDimitry Andric }
740*0b57cec5SDimitry Andric 
741*0b57cec5SDimitry Andric static std::string getCoverageMapErrString(coveragemap_error Err) {
742*0b57cec5SDimitry Andric   switch (Err) {
743*0b57cec5SDimitry Andric   case coveragemap_error::success:
744*0b57cec5SDimitry Andric     return "Success";
745*0b57cec5SDimitry Andric   case coveragemap_error::eof:
746*0b57cec5SDimitry Andric     return "End of File";
747*0b57cec5SDimitry Andric   case coveragemap_error::no_data_found:
748*0b57cec5SDimitry Andric     return "No coverage data found";
749*0b57cec5SDimitry Andric   case coveragemap_error::unsupported_version:
750*0b57cec5SDimitry Andric     return "Unsupported coverage format version";
751*0b57cec5SDimitry Andric   case coveragemap_error::truncated:
752*0b57cec5SDimitry Andric     return "Truncated coverage data";
753*0b57cec5SDimitry Andric   case coveragemap_error::malformed:
754*0b57cec5SDimitry Andric     return "Malformed coverage data";
755*0b57cec5SDimitry Andric   }
756*0b57cec5SDimitry Andric   llvm_unreachable("A value of coveragemap_error has no message.");
757*0b57cec5SDimitry Andric }
758*0b57cec5SDimitry Andric 
759*0b57cec5SDimitry Andric namespace {
760*0b57cec5SDimitry Andric 
761*0b57cec5SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It
762*0b57cec5SDimitry Andric // will be removed once this transition is complete. Clients should prefer to
763*0b57cec5SDimitry Andric // deal with the Error value directly, rather than converting to error_code.
764*0b57cec5SDimitry Andric class CoverageMappingErrorCategoryType : public std::error_category {
765*0b57cec5SDimitry Andric   const char *name() const noexcept override { return "llvm.coveragemap"; }
766*0b57cec5SDimitry Andric   std::string message(int IE) const override {
767*0b57cec5SDimitry Andric     return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
768*0b57cec5SDimitry Andric   }
769*0b57cec5SDimitry Andric };
770*0b57cec5SDimitry Andric 
771*0b57cec5SDimitry Andric } // end anonymous namespace
772*0b57cec5SDimitry Andric 
773*0b57cec5SDimitry Andric std::string CoverageMapError::message() const {
774*0b57cec5SDimitry Andric   return getCoverageMapErrString(Err);
775*0b57cec5SDimitry Andric }
776*0b57cec5SDimitry Andric 
777*0b57cec5SDimitry Andric static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
778*0b57cec5SDimitry Andric 
779*0b57cec5SDimitry Andric const std::error_category &llvm::coverage::coveragemap_category() {
780*0b57cec5SDimitry Andric   return *ErrorCategory;
781*0b57cec5SDimitry Andric }
782*0b57cec5SDimitry Andric 
783*0b57cec5SDimitry Andric char CoverageMapError::ID = 0;
784