blob: 4534e086b39e21fc13b9b6bd40b2f7cd5589aa1a [file] [log] [blame]
Eugene Zelenko72208a82017-06-21 23:19:47 +00001//===- CoverageMapping.cpp - Code coverage mapping support ----------------===//
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 {
Eugene Zelenko72208a82017-06-21 23:19:47 +0000306 using MapT = DenseMap<std::pair<unsigned, unsigned>,
307 std::vector<const FunctionRecord *>>;
Justin Bogner953e2402014-09-20 15:31:56 +0000308 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(); }
Justin Bogner953e2402014-09-20 15:31:56 +0000321 MapT::iterator end() { return InstantiatedFunctions.end(); }
322};
323
324class SegmentBuilder {
Igor Kudrinc0774e62016-04-14 09:10:00 +0000325 std::vector<CoverageSegment> &Segments;
Justin Bogner953e2402014-09-20 15:31:56 +0000326 SmallVector<const CountedRegion *, 8> ActiveRegions;
327
Igor Kudrinc0774e62016-04-14 09:10:00 +0000328 SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {}
329
Justin Bogner953e2402014-09-20 15:31:56 +0000330 /// Start a segment with no count specified.
331 void startSegment(unsigned Line, unsigned Col) {
Justin Bognerb35a72a2014-09-25 00:34:18 +0000332 DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n");
Justin Bogner953e2402014-09-20 15:31:56 +0000333 Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false);
334 }
335
336 /// Start a segment with the given Region's count.
337 void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
338 const CountedRegion &Region) {
Justin Bogner953e2402014-09-20 15:31:56 +0000339 // Avoid creating empty regions.
Igor Kudrined99a962016-04-25 09:43:37 +0000340 if (!Segments.empty() && Segments.back().Line == Line &&
341 Segments.back().Col == Col)
342 Segments.pop_back();
Justin Bognerb35a72a2014-09-25 00:34:18 +0000343 DEBUG(dbgs() << "Segment at " << Line << ":" << Col);
Justin Bogner953e2402014-09-20 15:31:56 +0000344 // Set this region's count.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000345 if (Region.Kind != CounterMappingRegion::SkippedRegion) {
Justin Bognerb35a72a2014-09-25 00:34:18 +0000346 DEBUG(dbgs() << " with count " << Region.ExecutionCount);
Igor Kudrined99a962016-04-25 09:43:37 +0000347 Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry);
348 } else
349 Segments.emplace_back(Line, Col, IsRegionEntry);
Justin Bognerb35a72a2014-09-25 00:34:18 +0000350 DEBUG(dbgs() << "\n");
Justin Bogner953e2402014-09-20 15:31:56 +0000351 }
352
353 /// Start a segment for the given region.
354 void startSegment(const CountedRegion &Region) {
355 startSegment(Region.LineStart, Region.ColumnStart, true, Region);
356 }
357
358 /// Pop the top region off of the active stack, starting a new segment with
359 /// the containing Region's count.
360 void popRegion() {
361 const CountedRegion *Active = ActiveRegions.back();
362 unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
363 ActiveRegions.pop_back();
364 if (ActiveRegions.empty())
365 startSegment(Line, Col);
366 else
367 startSegment(Line, Col, false, *ActiveRegions.back());
368 }
369
Igor Kudrinc0774e62016-04-14 09:10:00 +0000370 void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) {
Justin Bogner953e2402014-09-20 15:31:56 +0000371 for (const auto &Region : Regions) {
372 // Pop any regions that end before this one starts.
373 while (!ActiveRegions.empty() &&
374 ActiveRegions.back()->endLoc() <= Region.startLoc())
375 popRegion();
Igor Kudrined99a962016-04-25 09:43:37 +0000376 // Add this region to the stack.
377 ActiveRegions.push_back(&Region);
378 startSegment(Region);
Justin Bogner953e2402014-09-20 15:31:56 +0000379 }
380 // Pop any regions that are left in the stack.
381 while (!ActiveRegions.empty())
382 popRegion();
Igor Kudrinc0774e62016-04-14 09:10:00 +0000383 }
384
Igor Kudrined99a962016-04-25 09:43:37 +0000385 /// Sort a nested sequence of regions from a single file.
386 static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
Igor Kudrin27d8dd32016-05-05 09:39:45 +0000387 std::sort(Regions.begin(), Regions.end(), [](const CountedRegion &LHS,
388 const CountedRegion &RHS) {
389 if (LHS.startLoc() != RHS.startLoc())
390 return LHS.startLoc() < RHS.startLoc();
391 if (LHS.endLoc() != RHS.endLoc())
392 // When LHS completely contains RHS, we sort LHS first.
393 return RHS.endLoc() < LHS.endLoc();
394 // If LHS and RHS cover the same area, we need to sort them according
395 // to their kinds so that the most suitable region will become "active"
396 // in combineRegions(). Because we accumulate counter values only from
397 // regions of the same kind as the first region of the area, prefer
398 // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000399 static_assert(CounterMappingRegion::CodeRegion <
400 CounterMappingRegion::ExpansionRegion &&
401 CounterMappingRegion::ExpansionRegion <
402 CounterMappingRegion::SkippedRegion,
Igor Kudrin27d8dd32016-05-05 09:39:45 +0000403 "Unexpected order of region kind values");
404 return LHS.Kind < RHS.Kind;
405 });
Igor Kudrined99a962016-04-25 09:43:37 +0000406 }
407
408 /// Combine counts of regions which cover the same area.
409 static ArrayRef<CountedRegion>
410 combineRegions(MutableArrayRef<CountedRegion> Regions) {
411 if (Regions.empty())
412 return Regions;
413 auto Active = Regions.begin();
414 auto End = Regions.end();
415 for (auto I = Regions.begin() + 1; I != End; ++I) {
416 if (Active->startLoc() != I->startLoc() ||
417 Active->endLoc() != I->endLoc()) {
418 // Shift to the next region.
419 ++Active;
420 if (Active != I)
421 *Active = *I;
422 continue;
423 }
424 // Merge duplicate region.
Igor Kudrin27d8dd32016-05-05 09:39:45 +0000425 // If CodeRegions and ExpansionRegions cover the same area, it's probably
426 // a macro which is fully expanded to another macro. In that case, we need
427 // to accumulate counts only from CodeRegions, or else the area will be
428 // counted twice.
429 // On the other hand, a macro may have a nested macro in its body. If the
430 // outer macro is used several times, the ExpansionRegion for the nested
431 // macro will also be added several times. These ExpansionRegions cover
432 // the same source locations and have to be combined to reach the correct
433 // value for that area.
434 // We add counts of the regions of the same kind as the active region
435 // to handle the both situations.
436 if (I->Kind == Active->Kind)
Igor Kudrined99a962016-04-25 09:43:37 +0000437 Active->ExecutionCount += I->ExecutionCount;
438 }
439 return Regions.drop_back(std::distance(++Active, End));
440 }
441
Igor Kudrinc0774e62016-04-14 09:10:00 +0000442public:
Igor Kudrined99a962016-04-25 09:43:37 +0000443 /// Build a list of CoverageSegments from a list of Regions.
Igor Kudrinc0774e62016-04-14 09:10:00 +0000444 static std::vector<CoverageSegment>
Igor Kudrined99a962016-04-25 09:43:37 +0000445 buildSegments(MutableArrayRef<CountedRegion> Regions) {
Igor Kudrinc0774e62016-04-14 09:10:00 +0000446 std::vector<CoverageSegment> Segments;
447 SegmentBuilder Builder(Segments);
Igor Kudrined99a962016-04-25 09:43:37 +0000448
449 sortNestedRegions(Regions);
450 ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
451
452 Builder.buildSegmentsImpl(CombinedRegions);
Justin Bogner953e2402014-09-20 15:31:56 +0000453 return Segments;
454 }
455};
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000456
457} // end anonymous namespace
Justin Bogner953e2402014-09-20 15:31:56 +0000458
Justin Bognerd5fca922014-11-14 01:50:32 +0000459std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
Justin Bogner953e2402014-09-20 15:31:56 +0000460 std::vector<StringRef> Filenames;
461 for (const auto &Function : getCoveredFunctions())
Benjamin Kramer6cd780f2015-02-17 15:29:18 +0000462 Filenames.insert(Filenames.end(), Function.Filenames.begin(),
463 Function.Filenames.end());
Justin Bogner953e2402014-09-20 15:31:56 +0000464 std::sort(Filenames.begin(), Filenames.end());
465 auto Last = std::unique(Filenames.begin(), Filenames.end());
466 Filenames.erase(Last, Filenames.end());
467 return Filenames;
468}
469
Benjamin Kramer71e1eb52015-02-12 16:18:07 +0000470static SmallBitVector gatherFileIDs(StringRef SourceFile,
471 const FunctionRecord &Function) {
472 SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
Justin Bogner953e2402014-09-20 15:31:56 +0000473 for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
474 if (SourceFile == Function.Filenames[I])
475 FilenameEquivalence[I] = true;
Benjamin Kramer71e1eb52015-02-12 16:18:07 +0000476 return FilenameEquivalence;
477}
478
Igor Kudrin1c14dc42016-04-18 15:36:30 +0000479/// Return the ID of the file where the definition of the function is located.
Justin Bogner953e2402014-09-20 15:31:56 +0000480static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
Benjamin Kramer40957cc2015-02-12 16:30:00 +0000481 SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
Justin Bogner953e2402014-09-20 15:31:56 +0000482 for (const auto &CR : Function.CountedRegions)
483 if (CR.Kind == CounterMappingRegion::ExpansionRegion)
Benjamin Kramer40957cc2015-02-12 16:30:00 +0000484 IsNotExpandedFile[CR.ExpandedFileID] = false;
Benjamin Kramer71e1eb52015-02-12 16:18:07 +0000485 int I = IsNotExpandedFile.find_first();
Justin Bognerc4f5a5e2015-02-20 07:28:28 +0000486 if (I == -1)
487 return None;
488 return I;
Justin Bogner953e2402014-09-20 15:31:56 +0000489}
490
Igor Kudrin1c14dc42016-04-18 15:36:30 +0000491/// Check if SourceFile is the file that contains the definition of
492/// the Function. Return the ID of the file in that case or None otherwise.
493static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
494 const FunctionRecord &Function) {
495 Optional<unsigned> I = findMainViewFileID(Function);
496 if (I && SourceFile == Function.Filenames[*I])
497 return I;
498 return None;
499}
500
Justin Bogner953e2402014-09-20 15:31:56 +0000501static bool isExpansion(const CountedRegion &R, unsigned FileID) {
502 return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
503}
504
Vedant Kumar7fcc5472016-07-13 23:12:23 +0000505CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
Justin Bogner953e2402014-09-20 15:31:56 +0000506 CoverageData FileCoverage(Filename);
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000507 std::vector<CountedRegion> Regions;
Justin Bogner953e2402014-09-20 15:31:56 +0000508
509 for (const auto &Function : Functions) {
510 auto MainFileID = findMainViewFileID(Filename, Function);
Justin Bogner953e2402014-09-20 15:31:56 +0000511 auto FileIDs = gatherFileIDs(Filename, Function);
512 for (const auto &CR : Function.CountedRegions)
Benjamin Kramer71e1eb52015-02-12 16:18:07 +0000513 if (FileIDs.test(CR.FileID)) {
Justin Bogner953e2402014-09-20 15:31:56 +0000514 Regions.push_back(CR);
Igor Kudrin1c14dc42016-04-18 15:36:30 +0000515 if (MainFileID && isExpansion(CR, *MainFileID))
Justin Bogner953e2402014-09-20 15:31:56 +0000516 FileCoverage.Expansions.emplace_back(CR, Function);
517 }
518 }
519
Justin Bogner3c0f1242015-01-24 20:58:52 +0000520 DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
Igor Kudrinc0774e62016-04-14 09:10:00 +0000521 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
Justin Bogner953e2402014-09-20 15:31:56 +0000522
523 return FileCoverage;
524}
525
526std::vector<const FunctionRecord *>
Vedant Kumarf681e2e2016-07-15 01:19:33 +0000527CoverageMapping::getInstantiations(StringRef Filename) const {
Justin Bogner953e2402014-09-20 15:31:56 +0000528 FunctionInstantiationSetCollector InstantiationSetCollector;
529 for (const auto &Function : Functions) {
530 auto MainFileID = findMainViewFileID(Filename, Function);
531 if (!MainFileID)
532 continue;
533 InstantiationSetCollector.insert(Function, *MainFileID);
534 }
535
536 std::vector<const FunctionRecord *> Result;
537 for (const auto &InstantiationSet : InstantiationSetCollector) {
538 if (InstantiationSet.second.size() < 2)
539 continue;
Benjamin Kramer6cd780f2015-02-17 15:29:18 +0000540 Result.insert(Result.end(), InstantiationSet.second.begin(),
541 InstantiationSet.second.end());
Justin Bogner953e2402014-09-20 15:31:56 +0000542 }
543 return Result;
544}
545
546CoverageData
Vedant Kumarf681e2e2016-07-15 01:19:33 +0000547CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
Justin Bogner953e2402014-09-20 15:31:56 +0000548 auto MainFileID = findMainViewFileID(Function);
549 if (!MainFileID)
550 return CoverageData();
551
552 CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000553 std::vector<CountedRegion> Regions;
Justin Bogner953e2402014-09-20 15:31:56 +0000554 for (const auto &CR : Function.CountedRegions)
555 if (CR.FileID == *MainFileID) {
556 Regions.push_back(CR);
557 if (isExpansion(CR, *MainFileID))
558 FunctionCoverage.Expansions.emplace_back(CR, Function);
559 }
560
Justin Bogner3c0f1242015-01-24 20:58:52 +0000561 DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n");
Igor Kudrinc0774e62016-04-14 09:10:00 +0000562 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
Justin Bogner953e2402014-09-20 15:31:56 +0000563
564 return FunctionCoverage;
565}
566
Vedant Kumarf681e2e2016-07-15 01:19:33 +0000567CoverageData CoverageMapping::getCoverageForExpansion(
568 const ExpansionRecord &Expansion) const {
Justin Bogner953e2402014-09-20 15:31:56 +0000569 CoverageData ExpansionCoverage(
570 Expansion.Function.Filenames[Expansion.FileID]);
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000571 std::vector<CountedRegion> Regions;
Justin Bogner953e2402014-09-20 15:31:56 +0000572 for (const auto &CR : Expansion.Function.CountedRegions)
573 if (CR.FileID == Expansion.FileID) {
574 Regions.push_back(CR);
575 if (isExpansion(CR, Expansion.FileID))
576 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
577 }
578
Justin Bogner3c0f1242015-01-24 20:58:52 +0000579 DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID
580 << "\n");
Igor Kudrinc0774e62016-04-14 09:10:00 +0000581 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
Justin Bogner953e2402014-09-20 15:31:56 +0000582
583 return ExpansionCoverage;
584}
Justin Bogner367a9f22015-05-06 23:19:35 +0000585
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000586static std::string getCoverageMapErrString(coveragemap_error Err) {
Vedant Kumar9152fd12016-05-19 03:54:45 +0000587 switch (Err) {
588 case coveragemap_error::success:
589 return "Success";
590 case coveragemap_error::eof:
591 return "End of File";
592 case coveragemap_error::no_data_found:
593 return "No coverage data found";
594 case coveragemap_error::unsupported_version:
595 return "Unsupported coverage format version";
596 case coveragemap_error::truncated:
597 return "Truncated coverage data";
598 case coveragemap_error::malformed:
599 return "Malformed coverage data";
600 }
601 llvm_unreachable("A value of coveragemap_error has no message.");
602}
603
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000604namespace {
605
Peter Collingbourne4718f8b2016-05-24 20:13:46 +0000606// FIXME: This class is only here to support the transition to llvm::Error. It
607// will be removed once this transition is complete. Clients should prefer to
608// deal with the Error value directly, rather than converting to error_code.
Justin Bogner367a9f22015-05-06 23:19:35 +0000609class CoverageMappingErrorCategoryType : public std::error_category {
Reid Kleckner990504e2016-10-19 23:52:38 +0000610 const char *name() const noexcept override { return "llvm.coveragemap"; }
Justin Bogner367a9f22015-05-06 23:19:35 +0000611 std::string message(int IE) const override {
Vedant Kumar9152fd12016-05-19 03:54:45 +0000612 return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
Justin Bogner367a9f22015-05-06 23:19:35 +0000613 }
614};
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000615
Vedant Kumar9152fd12016-05-19 03:54:45 +0000616} // end anonymous namespace
617
618std::string CoverageMapError::message() const {
619 return getCoverageMapErrString(Err);
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000620}
Justin Bogner367a9f22015-05-06 23:19:35 +0000621
622static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
623
Xinliang David Li8a5bdb52016-01-10 21:56:33 +0000624const std::error_category &llvm::coverage::coveragemap_category() {
Justin Bogner367a9f22015-05-06 23:19:35 +0000625 return *ErrorCategory;
626}
Vedant Kumar9152fd12016-05-19 03:54:45 +0000627
628char CoverageMapError::ID = 0;