blob: 953972968d6cade254f03745cd325de878f1ab0c [file] [log] [blame]
Eugene Zelenkoe78d1312017-03-03 01:07:34 +00001//===- CoverageMapping.cpp - Code coverage mapping support ------*- C++ -*-===//
Alex Lorenza20a5d52014-07-24 23:57:54 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains support for clang's and llvm's instrumentation based
11// code coverage.
12//
13//===----------------------------------------------------------------------===//
14
Chandler Carruth6bda14b2017-06-06 11:49:48 +000015#include "llvm/ProfileData/Coverage/CoverageMapping.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000016#include "llvm/ADT/ArrayRef.h"
Justin Bogner953e2402014-09-20 15:31:56 +000017#include "llvm/ADT/DenseMap.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000018#include "llvm/ADT/None.h"
Justin Bogner953e2402014-09-20 15:31:56 +000019#include "llvm/ADT/Optional.h"
Benjamin Kramer71e1eb52015-02-12 16:18:07 +000020#include "llvm/ADT/SmallBitVector.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000021#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringRef.h"
Easwaran Ramandc707122016-04-29 18:53:05 +000023#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
Justin Bogner953e2402014-09-20 15:31:56 +000024#include "llvm/ProfileData/InstrProfReader.h"
Justin Bognerb35a72a2014-09-25 00:34:18 +000025#include "llvm/Support/Debug.h"
Rafael Espindola74f29322015-06-13 17:23:04 +000026#include "llvm/Support/Errc.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000027#include "llvm/Support/Error.h"
Justin Bogner85b0a032014-09-08 21:04:00 +000028#include "llvm/Support/ErrorHandling.h"
Justin Bogner367a9f22015-05-06 23:19:35 +000029#include "llvm/Support/ManagedStatic.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000030#include "llvm/Support/MemoryBuffer.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000031#include "llvm/Support/raw_ostream.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000032#include <algorithm>
33#include <cassert>
34#include <cstdint>
35#include <iterator>
36#include <memory>
37#include <string>
38#include <system_error>
39#include <utility>
40#include <vector>
Alex Lorenza20a5d52014-07-24 23:57:54 +000041
42using namespace llvm;
43using namespace coverage;
44
Justin Bognerb35a72a2014-09-25 00:34:18 +000045#define DEBUG_TYPE "coverage-mapping"
46
Alex Lorenza20a5d52014-07-24 23:57:54 +000047Counter CounterExpressionBuilder::get(const CounterExpression &E) {
Justin Bognerad69e642014-10-02 17:14:18 +000048 auto It = ExpressionIndices.find(E);
49 if (It != ExpressionIndices.end())
50 return Counter::getExpression(It->second);
51 unsigned I = Expressions.size();
Alex Lorenza20a5d52014-07-24 23:57:54 +000052 Expressions.push_back(E);
Justin Bognerad69e642014-10-02 17:14:18 +000053 ExpressionIndices[E] = I;
54 return Counter::getExpression(I);
Alex Lorenza20a5d52014-07-24 23:57:54 +000055}
56
Justin Bognerf9535c42014-10-02 16:43:31 +000057void CounterExpressionBuilder::extractTerms(
58 Counter C, int Sign, SmallVectorImpl<std::pair<unsigned, int>> &Terms) {
Alex Lorenza20a5d52014-07-24 23:57:54 +000059 switch (C.getKind()) {
60 case Counter::Zero:
61 break;
62 case Counter::CounterValueReference:
Justin Bognerf9535c42014-10-02 16:43:31 +000063 Terms.push_back(std::make_pair(C.getCounterID(), Sign));
Alex Lorenza20a5d52014-07-24 23:57:54 +000064 break;
65 case Counter::Expression:
66 const auto &E = Expressions[C.getExpressionID()];
Justin Bognerf9535c42014-10-02 16:43:31 +000067 extractTerms(E.LHS, Sign, Terms);
68 extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign,
69 Terms);
Alex Lorenza20a5d52014-07-24 23:57:54 +000070 break;
71 }
72}
73
74Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
75 // Gather constant terms.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000076 SmallVector<std::pair<unsigned, int>, 32> Terms;
Justin Bognerf9535c42014-10-02 16:43:31 +000077 extractTerms(ExpressionTree, +1, Terms);
78
79 // If there are no terms, this is just a zero. The algorithm below assumes at
80 // least one term.
81 if (Terms.size() == 0)
82 return Counter::getZero();
83
84 // Group the terms by counter ID.
85 std::sort(Terms.begin(), Terms.end(),
86 [](const std::pair<unsigned, int> &LHS,
87 const std::pair<unsigned, int> &RHS) {
88 return LHS.first < RHS.first;
89 });
90
91 // Combine terms by counter ID to eliminate counters that sum to zero.
92 auto Prev = Terms.begin();
93 for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
94 if (I->first == Prev->first) {
95 Prev->second += I->second;
96 continue;
97 }
98 ++Prev;
99 *Prev = *I;
100 }
101 Terms.erase(++Prev, Terms.end());
Alex Lorenza20a5d52014-07-24 23:57:54 +0000102
103 Counter C;
Justin Bognerf9535c42014-10-02 16:43:31 +0000104 // Create additions. We do this before subtractions to avoid constructs like
105 // ((0 - X) + Y), as opposed to (Y - X).
106 for (auto Term : Terms) {
107 if (Term.second <= 0)
Alex Lorenza20a5d52014-07-24 23:57:54 +0000108 continue;
Justin Bognerf9535c42014-10-02 16:43:31 +0000109 for (int I = 0; I < Term.second; ++I)
Alex Lorenza20a5d52014-07-24 23:57:54 +0000110 if (C.isZero())
Justin Bognerf9535c42014-10-02 16:43:31 +0000111 C = Counter::getCounter(Term.first);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000112 else
113 C = get(CounterExpression(CounterExpression::Add, C,
Justin Bognerf9535c42014-10-02 16:43:31 +0000114 Counter::getCounter(Term.first)));
Alex Lorenza20a5d52014-07-24 23:57:54 +0000115 }
116
117 // Create subtractions.
Justin Bognerf9535c42014-10-02 16:43:31 +0000118 for (auto Term : Terms) {
119 if (Term.second >= 0)
Alex Lorenza20a5d52014-07-24 23:57:54 +0000120 continue;
Justin Bognerf9535c42014-10-02 16:43:31 +0000121 for (int I = 0; I < -Term.second; ++I)
Alex Lorenza20a5d52014-07-24 23:57:54 +0000122 C = get(CounterExpression(CounterExpression::Subtract, C,
Justin Bognerf9535c42014-10-02 16:43:31 +0000123 Counter::getCounter(Term.first)));
Alex Lorenza20a5d52014-07-24 23:57:54 +0000124 }
125 return C;
126}
127
128Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
129 return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
130}
131
132Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
133 return simplify(
134 get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
135}
136
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000137void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
Alex Lorenza20a5d52014-07-24 23:57:54 +0000138 switch (C.getKind()) {
139 case Counter::Zero:
140 OS << '0';
141 return;
142 case Counter::CounterValueReference:
143 OS << '#' << C.getCounterID();
144 break;
145 case Counter::Expression: {
146 if (C.getExpressionID() >= Expressions.size())
147 return;
148 const auto &E = Expressions[C.getExpressionID()];
149 OS << '(';
Alex Lorenza422911c2014-07-29 19:58:16 +0000150 dump(E.LHS, OS);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000151 OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
Alex Lorenza422911c2014-07-29 19:58:16 +0000152 dump(E.RHS, OS);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000153 OS << ')';
154 break;
155 }
156 }
157 if (CounterValues.empty())
158 return;
Vedant Kumar9152fd12016-05-19 03:54:45 +0000159 Expected<int64_t> Value = evaluate(C);
160 if (auto E = Value.takeError()) {
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000161 consumeError(std::move(E));
Alex Lorenza20a5d52014-07-24 23:57:54 +0000162 return;
Vedant Kumar9152fd12016-05-19 03:54:45 +0000163 }
Justin Bogner85b0a032014-09-08 21:04:00 +0000164 OS << '[' << *Value << ']';
Alex Lorenza20a5d52014-07-24 23:57:54 +0000165}
166
Vedant Kumar9152fd12016-05-19 03:54:45 +0000167Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
Alex Lorenza20a5d52014-07-24 23:57:54 +0000168 switch (C.getKind()) {
169 case Counter::Zero:
170 return 0;
171 case Counter::CounterValueReference:
Justin Bogner85b0a032014-09-08 21:04:00 +0000172 if (C.getCounterID() >= CounterValues.size())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000173 return errorCodeToError(errc::argument_out_of_domain);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000174 return CounterValues[C.getCounterID()];
175 case Counter::Expression: {
Justin Bogner85b0a032014-09-08 21:04:00 +0000176 if (C.getExpressionID() >= Expressions.size())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000177 return errorCodeToError(errc::argument_out_of_domain);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000178 const auto &E = Expressions[C.getExpressionID()];
Vedant Kumar9152fd12016-05-19 03:54:45 +0000179 Expected<int64_t> LHS = evaluate(E.LHS);
Justin Bogner85b0a032014-09-08 21:04:00 +0000180 if (!LHS)
181 return LHS;
Vedant Kumar9152fd12016-05-19 03:54:45 +0000182 Expected<int64_t> RHS = evaluate(E.RHS);
Justin Bogner85b0a032014-09-08 21:04:00 +0000183 if (!RHS)
184 return RHS;
185 return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000186 }
187 }
Justin Bogner85b0a032014-09-08 21:04:00 +0000188 llvm_unreachable("Unhandled CounterKind");
Alex Lorenza20a5d52014-07-24 23:57:54 +0000189}
Justin Bogner953e2402014-09-20 15:31:56 +0000190
Justin Bognerd5fca922014-11-14 01:50:32 +0000191void FunctionRecordIterator::skipOtherFiles() {
192 while (Current != Records.end() && !Filename.empty() &&
193 Filename != Current->Filenames[0])
194 ++Current;
195 if (Current == Records.end())
196 *this = FunctionRecordIterator();
197}
198
Vedant Kumar68216d72016-10-12 22:27:45 +0000199Error CoverageMapping::loadFunctionRecord(
200 const CoverageMappingRecord &Record,
201 IndexedInstrProfReader &ProfileReader) {
Vedant Kumar743574b2016-10-14 17:16:53 +0000202 StringRef OrigFuncName = Record.FunctionName;
Vedant Kumarb1d331a2017-06-20 02:05:35 +0000203 if (OrigFuncName.empty())
204 return make_error<CoverageMapError>(coveragemap_error::malformed);
205
Vedant Kumar743574b2016-10-14 17:16:53 +0000206 if (Record.Filenames.empty())
207 OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
208 else
209 OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
210
211 // Don't load records for functions we've already seen.
212 if (!FunctionNames.insert(OrigFuncName).second)
213 return Error::success();
214
Vedant Kumar68216d72016-10-12 22:27:45 +0000215 CounterMappingContext Ctx(Record.Expressions);
216
217 std::vector<uint64_t> Counts;
218 if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName,
219 Record.FunctionHash, Counts)) {
220 instrprof_error IPE = InstrProfError::take(std::move(E));
221 if (IPE == instrprof_error::hash_mismatch) {
222 MismatchedFunctionCount++;
223 return Error::success();
224 } else if (IPE != instrprof_error::unknown_function)
225 return make_error<InstrProfError>(IPE);
226 Counts.assign(Record.MappingRegions.size(), 0);
227 }
228 Ctx.setCounts(Counts);
229
230 assert(!Record.MappingRegions.empty() && "Function has no regions");
231
Vedant Kumar68216d72016-10-12 22:27:45 +0000232 FunctionRecord Function(OrigFuncName, Record.Filenames);
233 for (const auto &Region : Record.MappingRegions) {
234 Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
235 if (auto E = ExecutionCount.takeError()) {
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000236 consumeError(std::move(E));
Vedant Kumar68216d72016-10-12 22:27:45 +0000237 return Error::success();
238 }
239 Function.pushRegion(Region, *ExecutionCount);
240 }
241 if (Function.CountedRegions.size() != Record.MappingRegions.size()) {
242 MismatchedFunctionCount++;
243 return Error::success();
244 }
245
246 Functions.push_back(std::move(Function));
247 return Error::success();
248}
249
Vedant Kumar9152fd12016-05-19 03:54:45 +0000250Expected<std::unique_ptr<CoverageMapping>>
Justin Bogner1d29c082015-02-18 18:01:14 +0000251CoverageMapping::load(CoverageMappingReader &CoverageReader,
Justin Bogner953e2402014-09-20 15:31:56 +0000252 IndexedInstrProfReader &ProfileReader) {
253 auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
254
Vedant Kumar68216d72016-10-12 22:27:45 +0000255 for (const auto &Record : CoverageReader)
256 if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
257 return std::move(E);
Justin Bogner953e2402014-09-20 15:31:56 +0000258
259 return std::move(Coverage);
260}
261
Vedant Kumar743574b2016-10-14 17:16:53 +0000262Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
263 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
264 IndexedInstrProfReader &ProfileReader) {
265 auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
266
267 for (const auto &CoverageReader : CoverageReaders)
268 for (const auto &Record : *CoverageReader)
269 if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader))
270 return std::move(E);
271
272 return std::move(Coverage);
273}
274
Vedant Kumar9152fd12016-05-19 03:54:45 +0000275Expected<std::unique_ptr<CoverageMapping>>
Vedant Kumar743574b2016-10-14 17:16:53 +0000276CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
277 StringRef ProfileFilename, StringRef Arch) {
Justin Bognerab89ed72015-02-16 21:28:58 +0000278 auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
Vedant Kumar9152fd12016-05-19 03:54:45 +0000279 if (Error E = ProfileReaderOrErr.takeError())
280 return std::move(E);
Justin Bognerab89ed72015-02-16 21:28:58 +0000281 auto ProfileReader = std::move(ProfileReaderOrErr.get());
Vedant Kumar743574b2016-10-14 17:16:53 +0000282
283 SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers;
284 SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
285 for (StringRef ObjectFilename : ObjectFilenames) {
286 auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
287 if (std::error_code EC = CovMappingBufOrErr.getError())
288 return errorCodeToError(EC);
289 auto CoverageReaderOrErr =
290 BinaryCoverageReader::create(CovMappingBufOrErr.get(), Arch);
291 if (Error E = CoverageReaderOrErr.takeError())
292 return std::move(E);
293 Readers.push_back(std::move(CoverageReaderOrErr.get()));
294 Buffers.push_back(std::move(CovMappingBufOrErr.get()));
295 }
296 return load(Readers, *ProfileReader);
Justin Bogner19a93ba2014-09-20 17:19:52 +0000297}
298
Justin Bogner953e2402014-09-20 15:31:56 +0000299namespace {
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000300
Justin Bogner953e2402014-09-20 15:31:56 +0000301/// \brief Distributes functions into instantiation sets.
302///
303/// An instantiation set is a collection of functions that have the same source
304/// code, ie, template functions specializations.
305class FunctionInstantiationSetCollector {
306 typedef DenseMap<std::pair<unsigned, unsigned>,
307 std::vector<const FunctionRecord *>> MapT;
308 MapT InstantiatedFunctions;
309
310public:
311 void insert(const FunctionRecord &Function, unsigned FileID) {
312 auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
313 while (I != E && I->FileID != FileID)
314 ++I;
315 assert(I != E && "function does not cover the given file");
316 auto &Functions = InstantiatedFunctions[I->startLoc()];
317 Functions.push_back(&Function);
318 }
319
320 MapT::iterator begin() { return InstantiatedFunctions.begin(); }
321
322 MapT::iterator end() { return InstantiatedFunctions.end(); }
323};
324
325class SegmentBuilder {
Igor Kudrinc0774e62016-04-14 09:10:00 +0000326 std::vector<CoverageSegment> &Segments;
Justin Bogner953e2402014-09-20 15:31:56 +0000327 SmallVector<const CountedRegion *, 8> ActiveRegions;
328
Igor Kudrinc0774e62016-04-14 09:10:00 +0000329 SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
330
Justin Bogner953e2402014-09-20 15:31:56 +0000331 /// Start a segment with no count specified.
332 void startSegment(unsigned Line, unsigned Col) {
Justin Bognerb35a72a2014-09-25 00:34:18 +0000333 DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n");
Justin Bogner953e2402014-09-20 15:31:56 +0000334 Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false);
335 }
336
337 /// Start a segment with the given Region's count.
338 void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
339 const CountedRegion &Region) {
Justin Bogner953e2402014-09-20 15:31:56 +0000340 // Avoid creating empty regions.
Igor Kudrined99a962016-04-25 09:43:37 +0000341 if (!Segments.empty() && Segments.back().Line == Line &&
342 Segments.back().Col == Col)
343 Segments.pop_back();
Justin Bognerb35a72a2014-09-25 00:34:18 +0000344 DEBUG(dbgs() << "Segment at " << Line << ":" << Col);
Justin Bogner953e2402014-09-20 15:31:56 +0000345 // Set this region's count.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000346 if (Region.Kind != CounterMappingRegion::SkippedRegion) {
Justin Bognerb35a72a2014-09-25 00:34:18 +0000347 DEBUG(dbgs() << " with count " << Region.ExecutionCount);
Igor Kudrined99a962016-04-25 09:43:37 +0000348 Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry);
349 } else
350 Segments.emplace_back(Line, Col, IsRegionEntry);
Justin Bognerb35a72a2014-09-25 00:34:18 +0000351 DEBUG(dbgs() << "\n");
Justin Bogner953e2402014-09-20 15:31:56 +0000352 }
353
354 /// Start a segment for the given region.
355 void startSegment(const CountedRegion &Region) {
356 startSegment(Region.LineStart, Region.ColumnStart, true, Region);
357 }
358
359 /// Pop the top region off of the active stack, starting a new segment with
360 /// the containing Region's count.
361 void popRegion() {
362 const CountedRegion *Active = ActiveRegions.back();
363 unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
364 ActiveRegions.pop_back();
365 if (ActiveRegions.empty())
366 startSegment(Line, Col);
367 else
368 startSegment(Line, Col, false, *ActiveRegions.back());
369 }
370
Igor Kudrinc0774e62016-04-14 09:10:00 +0000371 void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
Justin Bogner953e2402014-09-20 15:31:56 +0000372 for (const auto &Region : Regions) {
373 // Pop any regions that end before this one starts.
374 while (!ActiveRegions.empty() &&
375 ActiveRegions.back()->endLoc() <= Region.startLoc())
376 popRegion();
Igor Kudrined99a962016-04-25 09:43:37 +0000377 // Add this region to the stack.
378 ActiveRegions.push_back(&Region);
379 startSegment(Region);
Justin Bogner953e2402014-09-20 15:31:56 +0000380 }
381 // Pop any regions that are left in the stack.
382 while (!ActiveRegions.empty())
383 popRegion();
Igor Kudrinc0774e62016-04-14 09:10:00 +0000384 }
385
Igor Kudrined99a962016-04-25 09:43:37 +0000386 /// Sort a nested sequence of regions from a single file.
387 static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
Igor Kudrin27d8dd32016-05-05 09:39:45 +0000388 std::sort(Regions.begin(), Regions.end(), [](const CountedRegion &LHS,
389 const CountedRegion &RHS) {
390 if (LHS.startLoc() != RHS.startLoc())
391 return LHS.startLoc() < RHS.startLoc();
392 if (LHS.endLoc() != RHS.endLoc())
393 // When LHS completely contains RHS, we sort LHS first.
394 return RHS.endLoc() < LHS.endLoc();
395 // If LHS and RHS cover the same area, we need to sort them according
396 // to their kinds so that the most suitable region will become "active"
397 // in combineRegions(). Because we accumulate counter values only from
398 // regions of the same kind as the first region of the area, prefer
399 // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000400 static_assert(CounterMappingRegion::CodeRegion <
401 CounterMappingRegion::ExpansionRegion &&
402 CounterMappingRegion::ExpansionRegion <
403 CounterMappingRegion::SkippedRegion,
Igor Kudrin27d8dd32016-05-05 09:39:45 +0000404 "Unexpected order of region kind values");
405 return LHS.Kind < RHS.Kind;
406 });
Igor Kudrined99a962016-04-25 09:43:37 +0000407 }
408
409 /// Combine counts of regions which cover the same area.
410 static ArrayRef<CountedRegion>
411 combineRegions(MutableArrayRef<CountedRegion> Regions) {
412 if (Regions.empty())
413 return Regions;
414 auto Active = Regions.begin();
415 auto End = Regions.end();
416 for (auto I = Regions.begin() + 1; I != End; ++I) {
417 if (Active->startLoc() != I->startLoc() ||
418 Active->endLoc() != I->endLoc()) {
419 // Shift to the next region.
420 ++Active;
421 if (Active != I)
422 *Active = *I;
423 continue;
424 }
425 // Merge duplicate region.
Igor Kudrin27d8dd32016-05-05 09:39:45 +0000426 // If CodeRegions and ExpansionRegions cover the same area, it's probably
427 // a macro which is fully expanded to another macro. In that case, we need
428 // to accumulate counts only from CodeRegions, or else the area will be
429 // counted twice.
430 // On the other hand, a macro may have a nested macro in its body. If the
431 // outer macro is used several times, the ExpansionRegion for the nested
432 // macro will also be added several times. These ExpansionRegions cover
433 // the same source locations and have to be combined to reach the correct
434 // value for that area.
435 // We add counts of the regions of the same kind as the active region
436 // to handle the both situations.
437 if (I->Kind == Active->Kind)
Igor Kudrined99a962016-04-25 09:43:37 +0000438 Active->ExecutionCount += I->ExecutionCount;
439 }
440 return Regions.drop_back(std::distance(++Active, End));
441 }
442
Igor Kudrinc0774e62016-04-14 09:10:00 +0000443public:
Igor Kudrined99a962016-04-25 09:43:37 +0000444 /// Build a list of CoverageSegments from a list of Regions.
Igor Kudrinc0774e62016-04-14 09:10:00 +0000445 static std::vector<CoverageSegment>
Igor Kudrined99a962016-04-25 09:43:37 +0000446 buildSegments(MutableArrayRef<CountedRegion> Regions) {
Igor Kudrinc0774e62016-04-14 09:10:00 +0000447 std::vector<CoverageSegment> Segments;
448 SegmentBuilder Builder(Segments);
Igor Kudrined99a962016-04-25 09:43:37 +0000449
450 sortNestedRegions(Regions);
451 ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
452
453 Builder.buildSegmentsImpl(CombinedRegions);
Justin Bogner953e2402014-09-20 15:31:56 +0000454 return Segments;
455 }
456};
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000457
458} // end anonymous namespace
Justin Bogner953e2402014-09-20 15:31:56 +0000459
Justin Bognerd5fca922014-11-14 01:50:32 +0000460std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
Justin Bogner953e2402014-09-20 15:31:56 +0000461 std::vector<StringRef> Filenames;
462 for (const auto &Function : getCoveredFunctions())
Benjamin Kramer6cd780f2015-02-17 15:29:18 +0000463 Filenames.insert(Filenames.end(), Function.Filenames.begin(),
464 Function.Filenames.end());
Justin Bogner953e2402014-09-20 15:31:56 +0000465 std::sort(Filenames.begin(), Filenames.end());
466 auto Last = std::unique(Filenames.begin(), Filenames.end());
467 Filenames.erase(Last, Filenames.end());
468 return Filenames;
469}
470
Benjamin Kramer71e1eb52015-02-12 16:18:07 +0000471static SmallBitVector gatherFileIDs(StringRef SourceFile,
472 const FunctionRecord &Function) {
473 SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
Justin Bogner953e2402014-09-20 15:31:56 +0000474 for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
475 if (SourceFile == Function.Filenames[I])
476 FilenameEquivalence[I] = true;
Benjamin Kramer71e1eb52015-02-12 16:18:07 +0000477 return FilenameEquivalence;
478}
479
Igor Kudrin1c14dc42016-04-18 15:36:30 +0000480/// Return the ID of the file where the definition of the function is located.
Justin Bogner953e2402014-09-20 15:31:56 +0000481static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
Benjamin Kramer40957cc2015-02-12 16:30:00 +0000482 SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
Justin Bogner953e2402014-09-20 15:31:56 +0000483 for (const auto &CR : Function.CountedRegions)
484 if (CR.Kind == CounterMappingRegion::ExpansionRegion)
Benjamin Kramer40957cc2015-02-12 16:30:00 +0000485 IsNotExpandedFile[CR.ExpandedFileID] = false;
Benjamin Kramer71e1eb52015-02-12 16:18:07 +0000486 int I = IsNotExpandedFile.find_first();
Justin Bognerc4f5a5e2015-02-20 07:28:28 +0000487 if (I == -1)
488 return None;
489 return I;
Justin Bogner953e2402014-09-20 15:31:56 +0000490}
491
Igor Kudrin1c14dc42016-04-18 15:36:30 +0000492/// Check if SourceFile is the file that contains the definition of
493/// the Function. Return the ID of the file in that case or None otherwise.
494static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
495 const FunctionRecord &Function) {
496 Optional<unsigned> I = findMainViewFileID(Function);
497 if (I && SourceFile == Function.Filenames[*I])
498 return I;
499 return None;
500}
501
Justin Bogner953e2402014-09-20 15:31:56 +0000502static bool isExpansion(const CountedRegion &R, unsigned FileID) {
503 return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
504}
505
Vedant Kumar7fcc5472016-07-13 23:12:23 +0000506CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
Justin Bogner953e2402014-09-20 15:31:56 +0000507 CoverageData FileCoverage(Filename);
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000508 std::vector<CountedRegion> Regions;
Justin Bogner953e2402014-09-20 15:31:56 +0000509
510 for (const auto &Function : Functions) {
511 auto MainFileID = findMainViewFileID(Filename, Function);
Justin Bogner953e2402014-09-20 15:31:56 +0000512 auto FileIDs = gatherFileIDs(Filename, Function);
513 for (const auto &CR : Function.CountedRegions)
Benjamin Kramer71e1eb52015-02-12 16:18:07 +0000514 if (FileIDs.test(CR.FileID)) {
Justin Bogner953e2402014-09-20 15:31:56 +0000515 Regions.push_back(CR);
Igor Kudrin1c14dc42016-04-18 15:36:30 +0000516 if (MainFileID && isExpansion(CR, *MainFileID))
Justin Bogner953e2402014-09-20 15:31:56 +0000517 FileCoverage.Expansions.emplace_back(CR, Function);
518 }
519 }
520
Justin Bogner3c0f1242015-01-24 20:58:52 +0000521 DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
Igor Kudrinc0774e62016-04-14 09:10:00 +0000522 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
Justin Bogner953e2402014-09-20 15:31:56 +0000523
524 return FileCoverage;
525}
526
527std::vector<const FunctionRecord *>
Vedant Kumarf681e2e2016-07-15 01:19:33 +0000528CoverageMapping::getInstantiations(StringRef Filename) const {
Justin Bogner953e2402014-09-20 15:31:56 +0000529 FunctionInstantiationSetCollector InstantiationSetCollector;
530 for (const auto &Function : Functions) {
531 auto MainFileID = findMainViewFileID(Filename, Function);
532 if (!MainFileID)
533 continue;
534 InstantiationSetCollector.insert(Function, *MainFileID);
535 }
536
537 std::vector<const FunctionRecord *> Result;
538 for (const auto &InstantiationSet : InstantiationSetCollector) {
539 if (InstantiationSet.second.size() < 2)
540 continue;
Benjamin Kramer6cd780f2015-02-17 15:29:18 +0000541 Result.insert(Result.end(), InstantiationSet.second.begin(),
542 InstantiationSet.second.end());
Justin Bogner953e2402014-09-20 15:31:56 +0000543 }
544 return Result;
545}
546
547CoverageData
Vedant Kumarf681e2e2016-07-15 01:19:33 +0000548CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
Justin Bogner953e2402014-09-20 15:31:56 +0000549 auto MainFileID = findMainViewFileID(Function);
550 if (!MainFileID)
551 return CoverageData();
552
553 CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000554 std::vector<CountedRegion> Regions;
Justin Bogner953e2402014-09-20 15:31:56 +0000555 for (const auto &CR : Function.CountedRegions)
556 if (CR.FileID == *MainFileID) {
557 Regions.push_back(CR);
558 if (isExpansion(CR, *MainFileID))
559 FunctionCoverage.Expansions.emplace_back(CR, Function);
560 }
561
Justin Bogner3c0f1242015-01-24 20:58:52 +0000562 DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n");
Igor Kudrinc0774e62016-04-14 09:10:00 +0000563 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
Justin Bogner953e2402014-09-20 15:31:56 +0000564
565 return FunctionCoverage;
566}
567
Vedant Kumarf681e2e2016-07-15 01:19:33 +0000568CoverageData CoverageMapping::getCoverageForExpansion(
569 const ExpansionRecord &Expansion) const {
Justin Bogner953e2402014-09-20 15:31:56 +0000570 CoverageData ExpansionCoverage(
571 Expansion.Function.Filenames[Expansion.FileID]);
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000572 std::vector<CountedRegion> Regions;
Justin Bogner953e2402014-09-20 15:31:56 +0000573 for (const auto &CR : Expansion.Function.CountedRegions)
574 if (CR.FileID == Expansion.FileID) {
575 Regions.push_back(CR);
576 if (isExpansion(CR, Expansion.FileID))
577 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
578 }
579
Justin Bogner3c0f1242015-01-24 20:58:52 +0000580 DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID
581 << "\n");
Igor Kudrinc0774e62016-04-14 09:10:00 +0000582 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
Justin Bogner953e2402014-09-20 15:31:56 +0000583
584 return ExpansionCoverage;
585}
Justin Bogner367a9f22015-05-06 23:19:35 +0000586
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000587static std::string getCoverageMapErrString(coveragemap_error Err) {
Vedant Kumar9152fd12016-05-19 03:54:45 +0000588 switch (Err) {
589 case coveragemap_error::success:
590 return "Success";
591 case coveragemap_error::eof:
592 return "End of File";
593 case coveragemap_error::no_data_found:
594 return "No coverage data found";
595 case coveragemap_error::unsupported_version:
596 return "Unsupported coverage format version";
597 case coveragemap_error::truncated:
598 return "Truncated coverage data";
599 case coveragemap_error::malformed:
600 return "Malformed coverage data";
601 }
602 llvm_unreachable("A value of coveragemap_error has no message.");
603}
604
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000605namespace {
606
Peter Collingbourne4718f8b2016-05-24 20:13:46 +0000607// FIXME: This class is only here to support the transition to llvm::Error. It
608// will be removed once this transition is complete. Clients should prefer to
609// deal with the Error value directly, rather than converting to error_code.
Justin Bogner367a9f22015-05-06 23:19:35 +0000610class CoverageMappingErrorCategoryType : public std::error_category {
Reid Kleckner990504e2016-10-19 23:52:38 +0000611 const char *name() const noexcept override { return "llvm.coveragemap"; }
Justin Bogner367a9f22015-05-06 23:19:35 +0000612 std::string message(int IE) const override {
Vedant Kumar9152fd12016-05-19 03:54:45 +0000613 return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
Justin Bogner367a9f22015-05-06 23:19:35 +0000614 }
615};
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000616
Vedant Kumar9152fd12016-05-19 03:54:45 +0000617} // end anonymous namespace
618
619std::string CoverageMapError::message() const {
620 return getCoverageMapErrString(Err);
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000621}
Justin Bogner367a9f22015-05-06 23:19:35 +0000622
623static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
624
Xinliang David Li8a5bdb52016-01-10 21:56:33 +0000625const std::error_category &llvm::coverage::coveragemap_category() {
Justin Bogner367a9f22015-05-06 23:19:35 +0000626 return *ErrorCategory;
627}
Vedant Kumar9152fd12016-05-19 03:54:45 +0000628
629char CoverageMapError::ID = 0;