CoverageMapping.h revision 314564
1//=-- CoverageMapping.h - 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// Code coverage mapping data is generated by clang and read by
11// llvm-cov to show code coverage statistics for a file.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_PROFILEDATA_COVERAGEMAPPING_H_
16#define LLVM_PROFILEDATA_COVERAGEMAPPING_H_
17
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/Hashing.h"
21#include "llvm/ADT/StringSet.h"
22#include "llvm/ADT/Triple.h"
23#include "llvm/ADT/iterator.h"
24#include "llvm/ProfileData/InstrProf.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/Endian.h"
27#include "llvm/Support/raw_ostream.h"
28#include <system_error>
29#include <tuple>
30
31namespace llvm {
32namespace coverage {
33
34enum class coveragemap_error {
35  success = 0,
36  eof,
37  no_data_found,
38  unsupported_version,
39  truncated,
40  malformed
41};
42
43const std::error_category &coveragemap_category();
44
45inline std::error_code make_error_code(coveragemap_error E) {
46  return std::error_code(static_cast<int>(E), coveragemap_category());
47}
48
49class CoverageMapError : public ErrorInfo<CoverageMapError> {
50public:
51  CoverageMapError(coveragemap_error Err) : Err(Err) {
52    assert(Err != coveragemap_error::success && "Not an error");
53  }
54
55  std::string message() const override;
56
57  void log(raw_ostream &OS) const override { OS << message(); }
58
59  std::error_code convertToErrorCode() const override {
60    return make_error_code(Err);
61  }
62
63  coveragemap_error get() const { return Err; }
64
65  static char ID;
66
67private:
68  coveragemap_error Err;
69};
70
71} // end of coverage namespace.
72} // end of llvm namespace
73
74namespace llvm {
75class IndexedInstrProfReader;
76namespace coverage {
77
78class CoverageMappingReader;
79struct CoverageMappingRecord;
80
81class CoverageMapping;
82struct CounterExpressions;
83
84/// \brief A Counter is an abstract value that describes how to compute the
85/// execution count for a region of code using the collected profile count data.
86struct Counter {
87  enum CounterKind { Zero, CounterValueReference, Expression };
88  static const unsigned EncodingTagBits = 2;
89  static const unsigned EncodingTagMask = 0x3;
90  static const unsigned EncodingCounterTagAndExpansionRegionTagBits =
91      EncodingTagBits + 1;
92
93private:
94  CounterKind Kind;
95  unsigned ID;
96
97  Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
98
99public:
100  Counter() : Kind(Zero), ID(0) {}
101
102  CounterKind getKind() const { return Kind; }
103
104  bool isZero() const { return Kind == Zero; }
105
106  bool isExpression() const { return Kind == Expression; }
107
108  unsigned getCounterID() const { return ID; }
109
110  unsigned getExpressionID() const { return ID; }
111
112  friend bool operator==(const Counter &LHS, const Counter &RHS) {
113    return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID;
114  }
115
116  friend bool operator!=(const Counter &LHS, const Counter &RHS) {
117    return !(LHS == RHS);
118  }
119
120  friend bool operator<(const Counter &LHS, const Counter &RHS) {
121    return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID);
122  }
123
124  /// \brief Return the counter that represents the number zero.
125  static Counter getZero() { return Counter(); }
126
127  /// \brief Return the counter that corresponds to a specific profile counter.
128  static Counter getCounter(unsigned CounterId) {
129    return Counter(CounterValueReference, CounterId);
130  }
131
132  /// \brief Return the counter that corresponds to a specific
133  /// addition counter expression.
134  static Counter getExpression(unsigned ExpressionId) {
135    return Counter(Expression, ExpressionId);
136  }
137};
138
139/// \brief A Counter expression is a value that represents an arithmetic
140/// operation with two counters.
141struct CounterExpression {
142  enum ExprKind { Subtract, Add };
143  ExprKind Kind;
144  Counter LHS, RHS;
145
146  CounterExpression(ExprKind Kind, Counter LHS, Counter RHS)
147      : Kind(Kind), LHS(LHS), RHS(RHS) {}
148};
149
150/// \brief A Counter expression builder is used to construct the
151/// counter expressions. It avoids unnecessary duplication
152/// and simplifies algebraic expressions.
153class CounterExpressionBuilder {
154  /// \brief A list of all the counter expressions
155  std::vector<CounterExpression> Expressions;
156  /// \brief A lookup table for the index of a given expression.
157  llvm::DenseMap<CounterExpression, unsigned> ExpressionIndices;
158
159  /// \brief Return the counter which corresponds to the given expression.
160  ///
161  /// If the given expression is already stored in the builder, a counter
162  /// that references that expression is returned. Otherwise, the given
163  /// expression is added to the builder's collection of expressions.
164  Counter get(const CounterExpression &E);
165
166  /// \brief Gather the terms of the expression tree for processing.
167  ///
168  /// This collects each addition and subtraction referenced by the counter into
169  /// a sequence that can be sorted and combined to build a simplified counter
170  /// expression.
171  void extractTerms(Counter C, int Sign,
172                    SmallVectorImpl<std::pair<unsigned, int>> &Terms);
173
174  /// \brief Simplifies the given expression tree
175  /// by getting rid of algebraically redundant operations.
176  Counter simplify(Counter ExpressionTree);
177
178public:
179  ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
180
181  /// \brief Return a counter that represents the expression
182  /// that adds LHS and RHS.
183  Counter add(Counter LHS, Counter RHS);
184
185  /// \brief Return a counter that represents the expression
186  /// that subtracts RHS from LHS.
187  Counter subtract(Counter LHS, Counter RHS);
188};
189
190/// \brief A Counter mapping region associates a source range with
191/// a specific counter.
192struct CounterMappingRegion {
193  enum RegionKind {
194    /// \brief A CodeRegion associates some code with a counter
195    CodeRegion,
196
197    /// \brief An ExpansionRegion represents a file expansion region that
198    /// associates a source range with the expansion of a virtual source file,
199    /// such as for a macro instantiation or #include file.
200    ExpansionRegion,
201
202    /// \brief A SkippedRegion represents a source range with code that
203    /// was skipped by a preprocessor or similar means.
204    SkippedRegion
205  };
206
207  Counter Count;
208  unsigned FileID, ExpandedFileID;
209  unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
210  RegionKind Kind;
211
212  CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID,
213                       unsigned LineStart, unsigned ColumnStart,
214                       unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind)
215      : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID),
216        LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd),
217        ColumnEnd(ColumnEnd), Kind(Kind) {}
218
219  static CounterMappingRegion
220  makeRegion(Counter Count, unsigned FileID, unsigned LineStart,
221             unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
222    return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart,
223                                LineEnd, ColumnEnd, CodeRegion);
224  }
225
226  static CounterMappingRegion
227  makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
228                unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
229    return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart,
230                                ColumnStart, LineEnd, ColumnEnd,
231                                ExpansionRegion);
232  }
233
234  static CounterMappingRegion
235  makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
236              unsigned LineEnd, unsigned ColumnEnd) {
237    return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart,
238                                LineEnd, ColumnEnd, SkippedRegion);
239  }
240
241
242  inline std::pair<unsigned, unsigned> startLoc() const {
243    return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
244  }
245
246  inline std::pair<unsigned, unsigned> endLoc() const {
247    return std::pair<unsigned, unsigned>(LineEnd, ColumnEnd);
248  }
249};
250
251/// \brief Associates a source range with an execution count.
252struct CountedRegion : public CounterMappingRegion {
253  uint64_t ExecutionCount;
254
255  CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
256      : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {}
257};
258
259/// \brief A Counter mapping context is used to connect the counters,
260/// expressions and the obtained counter values.
261class CounterMappingContext {
262  ArrayRef<CounterExpression> Expressions;
263  ArrayRef<uint64_t> CounterValues;
264
265public:
266  CounterMappingContext(ArrayRef<CounterExpression> Expressions,
267                        ArrayRef<uint64_t> CounterValues = None)
268      : Expressions(Expressions), CounterValues(CounterValues) {}
269
270  void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
271
272  void dump(const Counter &C, llvm::raw_ostream &OS) const;
273  void dump(const Counter &C) const { dump(C, dbgs()); }
274
275  /// \brief Return the number of times that a region of code associated with
276  /// this counter was executed.
277  Expected<int64_t> evaluate(const Counter &C) const;
278};
279
280/// \brief Code coverage information for a single function.
281struct FunctionRecord {
282  /// \brief Raw function name.
283  std::string Name;
284  /// \brief Associated files.
285  std::vector<std::string> Filenames;
286  /// \brief Regions in the function along with their counts.
287  std::vector<CountedRegion> CountedRegions;
288  /// \brief The number of times this function was executed.
289  uint64_t ExecutionCount;
290
291  FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
292      : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
293
294  FunctionRecord(FunctionRecord &&FR) = default;
295  FunctionRecord &operator=(FunctionRecord &&) = default;
296
297  void pushRegion(CounterMappingRegion Region, uint64_t Count) {
298    if (CountedRegions.empty())
299      ExecutionCount = Count;
300    CountedRegions.emplace_back(Region, Count);
301  }
302};
303
304/// \brief Iterator over Functions, optionally filtered to a single file.
305class FunctionRecordIterator
306    : public iterator_facade_base<FunctionRecordIterator,
307                                  std::forward_iterator_tag, FunctionRecord> {
308  ArrayRef<FunctionRecord> Records;
309  ArrayRef<FunctionRecord>::iterator Current;
310  StringRef Filename;
311
312  /// \brief Skip records whose primary file is not \c Filename.
313  void skipOtherFiles();
314
315public:
316  FunctionRecordIterator(ArrayRef<FunctionRecord> Records_,
317                         StringRef Filename = "")
318      : Records(Records_), Current(Records.begin()), Filename(Filename) {
319    skipOtherFiles();
320  }
321
322  FunctionRecordIterator() : Current(Records.begin()) {}
323
324  bool operator==(const FunctionRecordIterator &RHS) const {
325    return Current == RHS.Current && Filename == RHS.Filename;
326  }
327
328  const FunctionRecord &operator*() const { return *Current; }
329
330  FunctionRecordIterator &operator++() {
331    assert(Current != Records.end() && "incremented past end");
332    ++Current;
333    skipOtherFiles();
334    return *this;
335  }
336};
337
338/// \brief Coverage information for a macro expansion or #included file.
339///
340/// When covered code has pieces that can be expanded for more detail, such as a
341/// preprocessor macro use and its definition, these are represented as
342/// expansions whose coverage can be looked up independently.
343struct ExpansionRecord {
344  /// \brief The abstract file this expansion covers.
345  unsigned FileID;
346  /// \brief The region that expands to this record.
347  const CountedRegion &Region;
348  /// \brief Coverage for the expansion.
349  const FunctionRecord &Function;
350
351  ExpansionRecord(const CountedRegion &Region,
352                  const FunctionRecord &Function)
353      : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
354};
355
356/// \brief The execution count information starting at a point in a file.
357///
358/// A sequence of CoverageSegments gives execution counts for a file in format
359/// that's simple to iterate through for processing.
360struct CoverageSegment {
361  /// \brief The line where this segment begins.
362  unsigned Line;
363  /// \brief The column where this segment begins.
364  unsigned Col;
365  /// \brief The execution count, or zero if no count was recorded.
366  uint64_t Count;
367  /// \brief When false, the segment was uninstrumented or skipped.
368  bool HasCount;
369  /// \brief Whether this enters a new region or returns to a previous count.
370  bool IsRegionEntry;
371
372  CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
373      : Line(Line), Col(Col), Count(0), HasCount(false),
374        IsRegionEntry(IsRegionEntry) {}
375
376  CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
377                  bool IsRegionEntry)
378      : Line(Line), Col(Col), Count(Count), HasCount(true),
379        IsRegionEntry(IsRegionEntry) {}
380
381  friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) {
382    return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) ==
383           std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry);
384  }
385};
386
387/// \brief Coverage information to be processed or displayed.
388///
389/// This represents the coverage of an entire file, expansion, or function. It
390/// provides a sequence of CoverageSegments to iterate through, as well as the
391/// list of expansions that can be further processed.
392class CoverageData {
393  std::string Filename;
394  std::vector<CoverageSegment> Segments;
395  std::vector<ExpansionRecord> Expansions;
396  friend class CoverageMapping;
397
398public:
399  CoverageData() {}
400
401  CoverageData(StringRef Filename) : Filename(Filename) {}
402
403  /// \brief Get the name of the file this data covers.
404  StringRef getFilename() const { return Filename; }
405
406  std::vector<CoverageSegment>::const_iterator begin() const {
407    return Segments.begin();
408  }
409  std::vector<CoverageSegment>::const_iterator end() const {
410    return Segments.end();
411  }
412  bool empty() const { return Segments.empty(); }
413
414  /// \brief Expansions that can be further processed.
415  ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; }
416};
417
418/// \brief The mapping of profile information to coverage data.
419///
420/// This is the main interface to get coverage information, using a profile to
421/// fill out execution counts.
422class CoverageMapping {
423  StringSet<> FunctionNames;
424  std::vector<FunctionRecord> Functions;
425  unsigned MismatchedFunctionCount;
426
427  CoverageMapping() : MismatchedFunctionCount(0) {}
428
429  CoverageMapping(const CoverageMapping &) = delete;
430  const CoverageMapping &operator=(const CoverageMapping &) = delete;
431
432  /// \brief Add a function record corresponding to \p Record.
433  Error loadFunctionRecord(const CoverageMappingRecord &Record,
434                           IndexedInstrProfReader &ProfileReader);
435
436public:
437  /// \brief Load the coverage mapping using the given readers.
438  static Expected<std::unique_ptr<CoverageMapping>>
439  load(CoverageMappingReader &CoverageReader,
440       IndexedInstrProfReader &ProfileReader);
441
442  static Expected<std::unique_ptr<CoverageMapping>>
443  load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
444       IndexedInstrProfReader &ProfileReader);
445
446  /// \brief Load the coverage mapping from the given files.
447  static Expected<std::unique_ptr<CoverageMapping>>
448  load(StringRef ObjectFilename, StringRef ProfileFilename,
449       StringRef Arch = StringRef()) {
450    return load(ArrayRef<StringRef>(ObjectFilename), ProfileFilename, Arch);
451  }
452
453  static Expected<std::unique_ptr<CoverageMapping>>
454  load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
455       StringRef Arch = StringRef());
456
457  /// \brief The number of functions that couldn't have their profiles mapped.
458  ///
459  /// This is a count of functions whose profile is out of date or otherwise
460  /// can't be associated with any coverage information.
461  unsigned getMismatchedCount() { return MismatchedFunctionCount; }
462
463  /// \brief Returns a lexicographically sorted, unique list of files that are
464  /// covered.
465  std::vector<StringRef> getUniqueSourceFiles() const;
466
467  /// \brief Get the coverage for a particular file.
468  ///
469  /// The given filename must be the name as recorded in the coverage
470  /// information. That is, only names returned from getUniqueSourceFiles will
471  /// yield a result.
472  CoverageData getCoverageForFile(StringRef Filename) const;
473
474  /// \brief Gets all of the functions covered by this profile.
475  iterator_range<FunctionRecordIterator> getCoveredFunctions() const {
476    return make_range(FunctionRecordIterator(Functions),
477                      FunctionRecordIterator());
478  }
479
480  /// \brief Gets all of the functions in a particular file.
481  iterator_range<FunctionRecordIterator>
482  getCoveredFunctions(StringRef Filename) const {
483    return make_range(FunctionRecordIterator(Functions, Filename),
484                      FunctionRecordIterator());
485  }
486
487  /// \brief Get the list of function instantiations in the file.
488  ///
489  /// Functions that are instantiated more than once, such as C++ template
490  /// specializations, have distinct coverage records for each instantiation.
491  std::vector<const FunctionRecord *>
492  getInstantiations(StringRef Filename) const;
493
494  /// \brief Get the coverage for a particular function.
495  CoverageData getCoverageForFunction(const FunctionRecord &Function) const;
496
497  /// \brief Get the coverage for an expansion within a coverage set.
498  CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const;
499};
500
501// Profile coverage map has the following layout:
502// [CoverageMapFileHeader]
503// [ArrayStart]
504//  [CovMapFunctionRecord]
505//  [CovMapFunctionRecord]
506//  ...
507// [ArrayEnd]
508// [Encoded Region Mapping Data]
509LLVM_PACKED_START
510template <class IntPtrT> struct CovMapFunctionRecordV1 {
511#define COVMAP_V1
512#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
513#include "llvm/ProfileData/InstrProfData.inc"
514#undef COVMAP_V1
515
516  // Return the structural hash associated with the function.
517  template <support::endianness Endian> uint64_t getFuncHash() const {
518    return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
519  }
520  // Return the coverage map data size for the funciton.
521  template <support::endianness Endian> uint32_t getDataSize() const {
522    return support::endian::byte_swap<uint32_t, Endian>(DataSize);
523  }
524  // Return function lookup key. The value is consider opaque.
525  template <support::endianness Endian> IntPtrT getFuncNameRef() const {
526    return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
527  }
528  // Return the PGO name of the function */
529  template <support::endianness Endian>
530  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
531    IntPtrT NameRef = getFuncNameRef<Endian>();
532    uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
533    FuncName = ProfileNames.getFuncName(NameRef, NameS);
534    if (NameS && FuncName.empty())
535      return make_error<CoverageMapError>(coveragemap_error::malformed);
536    return Error::success();
537  }
538};
539
540struct CovMapFunctionRecord {
541#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
542#include "llvm/ProfileData/InstrProfData.inc"
543
544  // Return the structural hash associated with the function.
545  template <support::endianness Endian> uint64_t getFuncHash() const {
546    return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
547  }
548  // Return the coverage map data size for the funciton.
549  template <support::endianness Endian> uint32_t getDataSize() const {
550    return support::endian::byte_swap<uint32_t, Endian>(DataSize);
551  }
552  // Return function lookup key. The value is consider opaque.
553  template <support::endianness Endian> uint64_t getFuncNameRef() const {
554    return support::endian::byte_swap<uint64_t, Endian>(NameRef);
555  }
556  // Return the PGO name of the function */
557  template <support::endianness Endian>
558  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
559    uint64_t NameRef = getFuncNameRef<Endian>();
560    FuncName = ProfileNames.getFuncName(NameRef);
561    return Error::success();
562  }
563};
564
565// Per module coverage mapping data header, i.e. CoverageMapFileHeader
566// documented above.
567struct CovMapHeader {
568#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name;
569#include "llvm/ProfileData/InstrProfData.inc"
570  template <support::endianness Endian> uint32_t getNRecords() const {
571    return support::endian::byte_swap<uint32_t, Endian>(NRecords);
572  }
573  template <support::endianness Endian> uint32_t getFilenamesSize() const {
574    return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize);
575  }
576  template <support::endianness Endian> uint32_t getCoverageSize() const {
577    return support::endian::byte_swap<uint32_t, Endian>(CoverageSize);
578  }
579  template <support::endianness Endian> uint32_t getVersion() const {
580    return support::endian::byte_swap<uint32_t, Endian>(Version);
581  }
582};
583
584LLVM_PACKED_END
585
586enum CovMapVersion {
587  Version1 = 0,
588  // Function's name reference from CovMapFuncRecord is changed from raw
589  // name string pointer to MD5 to support name section compression. Name
590  // section is also compressed.
591  Version2 = 1,
592  // The current version is Version2
593  CurrentVersion = INSTR_PROF_COVMAP_VERSION
594};
595
596template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
597  typedef CovMapFunctionRecord CovMapFuncRecordType;
598  typedef uint64_t NameRefType;
599};
600
601template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
602  typedef CovMapFunctionRecordV1<IntPtrT> CovMapFuncRecordType;
603  typedef IntPtrT NameRefType;
604};
605
606} // end namespace coverage
607
608/// \brief Provide DenseMapInfo for CounterExpression
609template<> struct DenseMapInfo<coverage::CounterExpression> {
610  static inline coverage::CounterExpression getEmptyKey() {
611    using namespace coverage;
612    return CounterExpression(CounterExpression::ExprKind::Subtract,
613                             Counter::getCounter(~0U),
614                             Counter::getCounter(~0U));
615  }
616
617  static inline coverage::CounterExpression getTombstoneKey() {
618    using namespace coverage;
619    return CounterExpression(CounterExpression::ExprKind::Add,
620                             Counter::getCounter(~0U),
621                             Counter::getCounter(~0U));
622  }
623
624  static unsigned getHashValue(const coverage::CounterExpression &V) {
625    return static_cast<unsigned>(
626        hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(),
627                     V.RHS.getKind(), V.RHS.getCounterID()));
628  }
629
630  static bool isEqual(const coverage::CounterExpression &LHS,
631                      const coverage::CounterExpression &RHS) {
632    return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS;
633  }
634};
635
636} // end namespace llvm
637
638#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_
639