InstrProf: Give coverage its own errors instead of piggy backing on instrprof
[oota-llvm.git] / lib / ProfileData / CoverageMapping.cpp
1 //=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=//
2 //
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
15 #include "llvm/ProfileData/CoverageMapping.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/Optional.h"
18 #include "llvm/ADT/SmallBitVector.h"
19 #include "llvm/ProfileData/CoverageMappingReader.h"
20 #include "llvm/ProfileData/InstrProfReader.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/ManagedStatic.h"
24 #include "llvm/Support/Path.h"
25 #include "llvm/Support/raw_ostream.h"
26
27 using namespace llvm;
28 using namespace coverage;
29
30 #define DEBUG_TYPE "coverage-mapping"
31
32 Counter CounterExpressionBuilder::get(const CounterExpression &E) {
33   auto It = ExpressionIndices.find(E);
34   if (It != ExpressionIndices.end())
35     return Counter::getExpression(It->second);
36   unsigned I = Expressions.size();
37   Expressions.push_back(E);
38   ExpressionIndices[E] = I;
39   return Counter::getExpression(I);
40 }
41
42 void CounterExpressionBuilder::extractTerms(
43     Counter C, int Sign, SmallVectorImpl<std::pair<unsigned, int>> &Terms) {
44   switch (C.getKind()) {
45   case Counter::Zero:
46     break;
47   case Counter::CounterValueReference:
48     Terms.push_back(std::make_pair(C.getCounterID(), Sign));
49     break;
50   case Counter::Expression:
51     const auto &E = Expressions[C.getExpressionID()];
52     extractTerms(E.LHS, Sign, Terms);
53     extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign,
54                  Terms);
55     break;
56   }
57 }
58
59 Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
60   // Gather constant terms.
61   llvm::SmallVector<std::pair<unsigned, int>, 32> Terms;
62   extractTerms(ExpressionTree, +1, Terms);
63
64   // If there are no terms, this is just a zero. The algorithm below assumes at
65   // least one term.
66   if (Terms.size() == 0)
67     return Counter::getZero();
68
69   // Group the terms by counter ID.
70   std::sort(Terms.begin(), Terms.end(),
71             [](const std::pair<unsigned, int> &LHS,
72                const std::pair<unsigned, int> &RHS) {
73     return LHS.first < RHS.first;
74   });
75
76   // Combine terms by counter ID to eliminate counters that sum to zero.
77   auto Prev = Terms.begin();
78   for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
79     if (I->first == Prev->first) {
80       Prev->second += I->second;
81       continue;
82     }
83     ++Prev;
84     *Prev = *I;
85   }
86   Terms.erase(++Prev, Terms.end());
87
88   Counter C;
89   // Create additions. We do this before subtractions to avoid constructs like
90   // ((0 - X) + Y), as opposed to (Y - X).
91   for (auto Term : Terms) {
92     if (Term.second <= 0)
93       continue;
94     for (int I = 0; I < Term.second; ++I)
95       if (C.isZero())
96         C = Counter::getCounter(Term.first);
97       else
98         C = get(CounterExpression(CounterExpression::Add, C,
99                                   Counter::getCounter(Term.first)));
100   }
101
102   // Create subtractions.
103   for (auto Term : Terms) {
104     if (Term.second >= 0)
105       continue;
106     for (int I = 0; I < -Term.second; ++I)
107       C = get(CounterExpression(CounterExpression::Subtract, C,
108                                 Counter::getCounter(Term.first)));
109   }
110   return C;
111 }
112
113 Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
114   return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
115 }
116
117 Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
118   return simplify(
119       get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
120 }
121
122 void CounterMappingContext::dump(const Counter &C,
123                                  llvm::raw_ostream &OS) const {
124   switch (C.getKind()) {
125   case Counter::Zero:
126     OS << '0';
127     return;
128   case Counter::CounterValueReference:
129     OS << '#' << C.getCounterID();
130     break;
131   case Counter::Expression: {
132     if (C.getExpressionID() >= Expressions.size())
133       return;
134     const auto &E = Expressions[C.getExpressionID()];
135     OS << '(';
136     dump(E.LHS, OS);
137     OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
138     dump(E.RHS, OS);
139     OS << ')';
140     break;
141   }
142   }
143   if (CounterValues.empty())
144     return;
145   ErrorOr<int64_t> Value = evaluate(C);
146   if (!Value)
147     return;
148   OS << '[' << *Value << ']';
149 }
150
151 ErrorOr<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
152   switch (C.getKind()) {
153   case Counter::Zero:
154     return 0;
155   case Counter::CounterValueReference:
156     if (C.getCounterID() >= CounterValues.size())
157       return std::make_error_code(std::errc::argument_out_of_domain);
158     return CounterValues[C.getCounterID()];
159   case Counter::Expression: {
160     if (C.getExpressionID() >= Expressions.size())
161       return std::make_error_code(std::errc::argument_out_of_domain);
162     const auto &E = Expressions[C.getExpressionID()];
163     ErrorOr<int64_t> LHS = evaluate(E.LHS);
164     if (!LHS)
165       return LHS;
166     ErrorOr<int64_t> RHS = evaluate(E.RHS);
167     if (!RHS)
168       return RHS;
169     return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
170   }
171   }
172   llvm_unreachable("Unhandled CounterKind");
173 }
174
175 void FunctionRecordIterator::skipOtherFiles() {
176   while (Current != Records.end() && !Filename.empty() &&
177          Filename != Current->Filenames[0])
178     ++Current;
179   if (Current == Records.end())
180     *this = FunctionRecordIterator();
181 }
182
183 /// Get the function name from the record, removing the filename prefix if
184 /// necessary.
185 static StringRef getFuncNameWithoutPrefix(const CoverageMappingRecord &Record) {
186   StringRef FunctionName = Record.FunctionName;
187   if (Record.Filenames.empty())
188     return FunctionName;
189   StringRef Filename = sys::path::filename(Record.Filenames[0]);
190   if (FunctionName.startswith(Filename))
191     FunctionName = FunctionName.drop_front(Filename.size() + 1);
192   return FunctionName;
193 }
194
195 ErrorOr<std::unique_ptr<CoverageMapping>>
196 CoverageMapping::load(CoverageMappingReader &CoverageReader,
197                       IndexedInstrProfReader &ProfileReader) {
198   auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
199
200   std::vector<uint64_t> Counts;
201   for (const auto &Record : CoverageReader) {
202     CounterMappingContext Ctx(Record.Expressions);
203
204     Counts.clear();
205     if (std::error_code EC = ProfileReader.getFunctionCounts(
206             Record.FunctionName, Record.FunctionHash, Counts)) {
207       if (EC == instrprof_error::hash_mismatch) {
208         Coverage->MismatchedFunctionCount++;
209         continue;
210       } else if (EC != instrprof_error::unknown_function)
211         return EC;
212     } else
213       Ctx.setCounts(Counts);
214
215     assert(!Record.MappingRegions.empty() && "Function has no regions");
216
217     FunctionRecord Function(getFuncNameWithoutPrefix(Record), Record.Filenames);
218     for (const auto &Region : Record.MappingRegions) {
219       ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
220       if (!ExecutionCount)
221         break;
222       Function.pushRegion(Region, *ExecutionCount);
223     }
224     if (Function.CountedRegions.size() != Record.MappingRegions.size()) {
225       Coverage->MismatchedFunctionCount++;
226       continue;
227     }
228
229     Coverage->Functions.push_back(std::move(Function));
230   }
231
232   return std::move(Coverage);
233 }
234
235 ErrorOr<std::unique_ptr<CoverageMapping>>
236 CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename,
237                       Triple::ArchType Arch) {
238   auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
239   if (std::error_code EC = CounterMappingBuff.getError())
240     return EC;
241   auto CoverageReaderOrErr =
242       BinaryCoverageReader::create(CounterMappingBuff.get(), Arch);
243   if (std::error_code EC = CoverageReaderOrErr.getError())
244     return EC;
245   auto CoverageReader = std::move(CoverageReaderOrErr.get());
246   auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
247   if (auto EC = ProfileReaderOrErr.getError())
248     return EC;
249   auto ProfileReader = std::move(ProfileReaderOrErr.get());
250   return load(*CoverageReader, *ProfileReader);
251 }
252
253 namespace {
254 /// \brief Distributes functions into instantiation sets.
255 ///
256 /// An instantiation set is a collection of functions that have the same source
257 /// code, ie, template functions specializations.
258 class FunctionInstantiationSetCollector {
259   typedef DenseMap<std::pair<unsigned, unsigned>,
260                    std::vector<const FunctionRecord *>> MapT;
261   MapT InstantiatedFunctions;
262
263 public:
264   void insert(const FunctionRecord &Function, unsigned FileID) {
265     auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
266     while (I != E && I->FileID != FileID)
267       ++I;
268     assert(I != E && "function does not cover the given file");
269     auto &Functions = InstantiatedFunctions[I->startLoc()];
270     Functions.push_back(&Function);
271   }
272
273   MapT::iterator begin() { return InstantiatedFunctions.begin(); }
274
275   MapT::iterator end() { return InstantiatedFunctions.end(); }
276 };
277
278 class SegmentBuilder {
279   std::vector<CoverageSegment> Segments;
280   SmallVector<const CountedRegion *, 8> ActiveRegions;
281
282   /// Start a segment with no count specified.
283   void startSegment(unsigned Line, unsigned Col) {
284     DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n");
285     Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false);
286   }
287
288   /// Start a segment with the given Region's count.
289   void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
290                     const CountedRegion &Region) {
291     if (Segments.empty())
292       Segments.emplace_back(Line, Col, IsRegionEntry);
293     CoverageSegment S = Segments.back();
294     // Avoid creating empty regions.
295     if (S.Line != Line || S.Col != Col) {
296       Segments.emplace_back(Line, Col, IsRegionEntry);
297       S = Segments.back();
298     }
299     DEBUG(dbgs() << "Segment at " << Line << ":" << Col);
300     // Set this region's count.
301     if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) {
302       DEBUG(dbgs() << " with count " << Region.ExecutionCount);
303       Segments.back().setCount(Region.ExecutionCount);
304     }
305     DEBUG(dbgs() << "\n");
306   }
307
308   /// Start a segment for the given region.
309   void startSegment(const CountedRegion &Region) {
310     startSegment(Region.LineStart, Region.ColumnStart, true, Region);
311   }
312
313   /// Pop the top region off of the active stack, starting a new segment with
314   /// the containing Region's count.
315   void popRegion() {
316     const CountedRegion *Active = ActiveRegions.back();
317     unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
318     ActiveRegions.pop_back();
319     if (ActiveRegions.empty())
320       startSegment(Line, Col);
321     else
322       startSegment(Line, Col, false, *ActiveRegions.back());
323   }
324
325 public:
326   /// Build a list of CoverageSegments from a sorted list of Regions.
327   std::vector<CoverageSegment> buildSegments(ArrayRef<CountedRegion> Regions) {
328     const CountedRegion *PrevRegion = nullptr;
329     for (const auto &Region : Regions) {
330       // Pop any regions that end before this one starts.
331       while (!ActiveRegions.empty() &&
332              ActiveRegions.back()->endLoc() <= Region.startLoc())
333         popRegion();
334       if (PrevRegion && PrevRegion->startLoc() == Region.startLoc() &&
335           PrevRegion->endLoc() == Region.endLoc()) {
336         if (Region.Kind == coverage::CounterMappingRegion::CodeRegion)
337           Segments.back().addCount(Region.ExecutionCount);
338       } else {
339         // Add this region to the stack.
340         ActiveRegions.push_back(&Region);
341         startSegment(Region);
342       }
343       PrevRegion = &Region;
344     }
345     // Pop any regions that are left in the stack.
346     while (!ActiveRegions.empty())
347       popRegion();
348     return Segments;
349   }
350 };
351 }
352
353 std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
354   std::vector<StringRef> Filenames;
355   for (const auto &Function : getCoveredFunctions())
356     Filenames.insert(Filenames.end(), Function.Filenames.begin(),
357                      Function.Filenames.end());
358   std::sort(Filenames.begin(), Filenames.end());
359   auto Last = std::unique(Filenames.begin(), Filenames.end());
360   Filenames.erase(Last, Filenames.end());
361   return Filenames;
362 }
363
364 static SmallBitVector gatherFileIDs(StringRef SourceFile,
365                                     const FunctionRecord &Function) {
366   SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
367   for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
368     if (SourceFile == Function.Filenames[I])
369       FilenameEquivalence[I] = true;
370   return FilenameEquivalence;
371 }
372
373 static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
374                                              const FunctionRecord &Function) {
375   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
376   SmallBitVector FilenameEquivalence = gatherFileIDs(SourceFile, Function);
377   for (const auto &CR : Function.CountedRegions)
378     if (CR.Kind == CounterMappingRegion::ExpansionRegion &&
379         FilenameEquivalence[CR.FileID])
380       IsNotExpandedFile[CR.ExpandedFileID] = false;
381   IsNotExpandedFile &= FilenameEquivalence;
382   int I = IsNotExpandedFile.find_first();
383   if (I == -1)
384     return None;
385   return I;
386 }
387
388 static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
389   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
390   for (const auto &CR : Function.CountedRegions)
391     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
392       IsNotExpandedFile[CR.ExpandedFileID] = false;
393   int I = IsNotExpandedFile.find_first();
394   if (I == -1)
395     return None;
396   return I;
397 }
398
399 /// Sort a nested sequence of regions from a single file.
400 template <class It> static void sortNestedRegions(It First, It Last) {
401   std::sort(First, Last,
402             [](const CountedRegion &LHS, const CountedRegion &RHS) {
403     if (LHS.startLoc() == RHS.startLoc())
404       // When LHS completely contains RHS, we sort LHS first.
405       return RHS.endLoc() < LHS.endLoc();
406     return LHS.startLoc() < RHS.startLoc();
407   });
408 }
409
410 static bool isExpansion(const CountedRegion &R, unsigned FileID) {
411   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
412 }
413
414 CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) {
415   CoverageData FileCoverage(Filename);
416   std::vector<coverage::CountedRegion> Regions;
417
418   for (const auto &Function : Functions) {
419     auto MainFileID = findMainViewFileID(Filename, Function);
420     if (!MainFileID)
421       continue;
422     auto FileIDs = gatherFileIDs(Filename, Function);
423     for (const auto &CR : Function.CountedRegions)
424       if (FileIDs.test(CR.FileID)) {
425         Regions.push_back(CR);
426         if (isExpansion(CR, *MainFileID))
427           FileCoverage.Expansions.emplace_back(CR, Function);
428       }
429   }
430
431   sortNestedRegions(Regions.begin(), Regions.end());
432   DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
433   FileCoverage.Segments = SegmentBuilder().buildSegments(Regions);
434
435   return FileCoverage;
436 }
437
438 std::vector<const FunctionRecord *>
439 CoverageMapping::getInstantiations(StringRef Filename) {
440   FunctionInstantiationSetCollector InstantiationSetCollector;
441   for (const auto &Function : Functions) {
442     auto MainFileID = findMainViewFileID(Filename, Function);
443     if (!MainFileID)
444       continue;
445     InstantiationSetCollector.insert(Function, *MainFileID);
446   }
447
448   std::vector<const FunctionRecord *> Result;
449   for (const auto &InstantiationSet : InstantiationSetCollector) {
450     if (InstantiationSet.second.size() < 2)
451       continue;
452     Result.insert(Result.end(), InstantiationSet.second.begin(),
453                   InstantiationSet.second.end());
454   }
455   return Result;
456 }
457
458 CoverageData
459 CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) {
460   auto MainFileID = findMainViewFileID(Function);
461   if (!MainFileID)
462     return CoverageData();
463
464   CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
465   std::vector<coverage::CountedRegion> Regions;
466   for (const auto &CR : Function.CountedRegions)
467     if (CR.FileID == *MainFileID) {
468       Regions.push_back(CR);
469       if (isExpansion(CR, *MainFileID))
470         FunctionCoverage.Expansions.emplace_back(CR, Function);
471     }
472
473   sortNestedRegions(Regions.begin(), Regions.end());
474   DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n");
475   FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
476
477   return FunctionCoverage;
478 }
479
480 CoverageData
481 CoverageMapping::getCoverageForExpansion(const ExpansionRecord &Expansion) {
482   CoverageData ExpansionCoverage(
483       Expansion.Function.Filenames[Expansion.FileID]);
484   std::vector<coverage::CountedRegion> Regions;
485   for (const auto &CR : Expansion.Function.CountedRegions)
486     if (CR.FileID == Expansion.FileID) {
487       Regions.push_back(CR);
488       if (isExpansion(CR, Expansion.FileID))
489         ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
490     }
491
492   sortNestedRegions(Regions.begin(), Regions.end());
493   DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID
494                << "\n");
495   ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
496
497   return ExpansionCoverage;
498 }
499
500 namespace {
501 class CoverageMappingErrorCategoryType : public std::error_category {
502   const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; }
503   std::string message(int IE) const override {
504     auto E = static_cast<coveragemap_error>(IE);
505     switch (E) {
506     case coveragemap_error::success:
507       return "Success";
508     case coveragemap_error::eof:
509       return "End of File";
510     case coveragemap_error::no_data_found:
511       return "No coverage data found";
512     case coveragemap_error::unsupported_version:
513       return "Unsupported coverage format version";
514     case coveragemap_error::truncated:
515       return "Truncated coverage data";
516     case coveragemap_error::malformed:
517       return "Malformed coverage data";
518     }
519     llvm_unreachable("A value of coveragemap_error has no message.");
520   }
521 };
522 }
523
524 static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
525
526 const std::error_category &llvm::coveragemap_category() {
527   return *ErrorCategory;
528 }