LLVM  8.0.1
GCOV.h
Go to the documentation of this file.
1 //===- GCOV.h - LLVM coverage tool ------------------------------*- 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 header provides the interface to read and write coverage files that
11 // use 'gcov' format.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_PROFILEDATA_GCOV_H
16 #define LLVM_PROFILEDATA_GCOV_H
17 
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/MapVector.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/iterator.h"
27 #include <algorithm>
28 #include <cassert>
29 #include <cstddef>
30 #include <cstdint>
31 #include <limits>
32 #include <memory>
33 #include <string>
34 #include <utility>
35 
36 namespace llvm {
37 
38 class GCOVFunction;
39 class GCOVBlock;
40 class FileInfo;
41 
42 namespace GCOV {
43 
45 
46 /// A struct for passing gcov options between functions.
47 struct Options {
48  Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
51 
52  bool AllBlocks;
53  bool BranchInfo;
59  bool NoOutput;
60 };
61 
62 } // end namespace GCOV
63 
64 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
65 /// read operations.
66 class GCOVBuffer {
67 public:
68  GCOVBuffer(MemoryBuffer *B) : Buffer(B) {}
69 
70  /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
71  bool readGCNOFormat() {
72  StringRef File = Buffer->getBuffer().slice(0, 4);
73  if (File != "oncg") {
74  errs() << "Unexpected file type: " << File << ".\n";
75  return false;
76  }
77  Cursor = 4;
78  return true;
79  }
80 
81  /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
82  bool readGCDAFormat() {
83  StringRef File = Buffer->getBuffer().slice(0, 4);
84  if (File != "adcg") {
85  errs() << "Unexpected file type: " << File << ".\n";
86  return false;
87  }
88  Cursor = 4;
89  return true;
90  }
91 
92  /// readGCOVVersion - Read GCOV version.
94  StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4);
95  if (VersionStr == "*204") {
96  Cursor += 4;
97  Version = GCOV::V402;
98  return true;
99  }
100  if (VersionStr == "*404") {
101  Cursor += 4;
102  Version = GCOV::V404;
103  return true;
104  }
105  if (VersionStr == "*704") {
106  Cursor += 4;
107  Version = GCOV::V704;
108  return true;
109  }
110  errs() << "Unexpected version: " << VersionStr << ".\n";
111  return false;
112  }
113 
114  /// readFunctionTag - If cursor points to a function tag then increment the
115  /// cursor and return true otherwise return false.
117  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
118  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
119  Tag[3] != '\1') {
120  return false;
121  }
122  Cursor += 4;
123  return true;
124  }
125 
126  /// readBlockTag - If cursor points to a block tag then increment the
127  /// cursor and return true otherwise return false.
128  bool readBlockTag() {
129  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
130  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
131  Tag[3] != '\x01') {
132  return false;
133  }
134  Cursor += 4;
135  return true;
136  }
137 
138  /// readEdgeTag - If cursor points to an edge tag then increment the
139  /// cursor and return true otherwise return false.
140  bool readEdgeTag() {
141  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
142  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
143  Tag[3] != '\x01') {
144  return false;
145  }
146  Cursor += 4;
147  return true;
148  }
149 
150  /// readLineTag - If cursor points to a line tag then increment the
151  /// cursor and return true otherwise return false.
152  bool readLineTag() {
153  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
154  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
155  Tag[3] != '\x01') {
156  return false;
157  }
158  Cursor += 4;
159  return true;
160  }
161 
162  /// readArcTag - If cursor points to an gcda arc tag then increment the
163  /// cursor and return true otherwise return false.
164  bool readArcTag() {
165  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
166  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
167  Tag[3] != '\1') {
168  return false;
169  }
170  Cursor += 4;
171  return true;
172  }
173 
174  /// readObjectTag - If cursor points to an object summary tag then increment
175  /// the cursor and return true otherwise return false.
176  bool readObjectTag() {
177  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
178  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
179  Tag[3] != '\xa1') {
180  return false;
181  }
182  Cursor += 4;
183  return true;
184  }
185 
186  /// readProgramTag - If cursor points to a program summary tag then increment
187  /// the cursor and return true otherwise return false.
188  bool readProgramTag() {
189  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
190  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
191  Tag[3] != '\xa3') {
192  return false;
193  }
194  Cursor += 4;
195  return true;
196  }
197 
198  bool readInt(uint32_t &Val) {
199  if (Buffer->getBuffer().size() < Cursor + 4) {
200  errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
201  return false;
202  }
203  StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
204  Cursor += 4;
205  Val = *(const uint32_t *)(Str.data());
206  return true;
207  }
208 
209  bool readInt64(uint64_t &Val) {
210  uint32_t Lo, Hi;
211  if (!readInt(Lo) || !readInt(Hi))
212  return false;
213  Val = ((uint64_t)Hi << 32) | Lo;
214  return true;
215  }
216 
217  bool readString(StringRef &Str) {
218  uint32_t Len = 0;
219  // Keep reading until we find a non-zero length. This emulates gcov's
220  // behaviour, which appears to do the same.
221  while (Len == 0)
222  if (!readInt(Len))
223  return false;
224  Len *= 4;
225  if (Buffer->getBuffer().size() < Cursor + Len) {
226  errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
227  return false;
228  }
229  Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
230  Cursor += Len;
231  return true;
232  }
233 
234  uint64_t getCursor() const { return Cursor; }
235  void advanceCursor(uint32_t n) { Cursor += n * 4; }
236 
237 private:
238  MemoryBuffer *Buffer;
239  uint64_t Cursor = 0;
240 };
241 
242 /// GCOVFile - Collects coverage information for one pair of coverage file
243 /// (.gcno and .gcda).
244 class GCOVFile {
245 public:
246  GCOVFile() = default;
247 
248  bool readGCNO(GCOVBuffer &Buffer);
249  bool readGCDA(GCOVBuffer &Buffer);
250  uint32_t getChecksum() const { return Checksum; }
251  void print(raw_ostream &OS) const;
252  void dump() const;
253  void collectLineCounts(FileInfo &FI);
254 
255 private:
256  bool GCNOInitialized = false;
258  uint32_t Checksum = 0;
260  uint32_t RunCount = 0;
261  uint32_t ProgramCount = 0;
262 };
263 
264 /// GCOVEdge - Collects edge information.
265 struct GCOVEdge {
266  GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D) {}
267 
270  uint64_t Count = 0;
271  uint64_t CyclesCount = 0;
272 };
273 
274 /// GCOVFunction - Collects function information.
276 public:
279 
280  GCOVFunction(GCOVFile &P) : Parent(P) {}
281 
282  bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
283  bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
284  StringRef getName() const { return Name; }
285  StringRef getFilename() const { return Filename; }
286  size_t getNumBlocks() const { return Blocks.size(); }
287  uint64_t getEntryCount() const;
288  uint64_t getExitCount() const;
289 
290  BlockIterator block_begin() const { return Blocks.begin(); }
291  BlockIterator block_end() const { return Blocks.end(); }
293  return make_range(block_begin(), block_end());
294  }
295 
296  void print(raw_ostream &OS) const;
297  void dump() const;
298  void collectLineCounts(FileInfo &FI);
299 
300 private:
301  GCOVFile &Parent;
302  uint32_t Ident = 0;
303  uint32_t Checksum;
304  uint32_t LineNumber = 0;
305  StringRef Name;
306  StringRef Filename;
309 };
310 
311 /// GCOVBlock - Collects block information.
312 class GCOVBlock {
313  struct EdgeWeight {
314  EdgeWeight(GCOVBlock *D) : Dst(D) {}
315 
316  GCOVBlock *Dst;
317  uint64_t Count = 0;
318  };
319 
320  struct SortDstEdgesFunctor {
321  bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
322  return E1->Dst.Number < E2->Dst.Number;
323  }
324  };
325 
326 public:
331 
332  GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N) {}
333  ~GCOVBlock();
334 
335  const GCOVFunction &getParent() const { return Parent; }
336  void addLine(uint32_t N) { Lines.push_back(N); }
337  uint32_t getLastLine() const { return Lines.back(); }
338  void addCount(size_t DstEdgeNo, uint64_t N);
339  uint64_t getCount() const { return Counter; }
340 
341  void addSrcEdge(GCOVEdge *Edge) {
342  assert(&Edge->Dst == this); // up to caller to ensure edge is valid
343  SrcEdges.push_back(Edge);
344  }
345 
346  void addDstEdge(GCOVEdge *Edge) {
347  assert(&Edge->Src == this); // up to caller to ensure edge is valid
348  // Check if adding this edge causes list to become unsorted.
349  if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
350  DstEdgesAreSorted = false;
351  DstEdges.push_back(Edge);
352  }
353 
354  size_t getNumSrcEdges() const { return SrcEdges.size(); }
355  size_t getNumDstEdges() const { return DstEdges.size(); }
356  void sortDstEdges();
357 
358  EdgeIterator src_begin() const { return SrcEdges.begin(); }
359  EdgeIterator src_end() const { return SrcEdges.end(); }
361  return make_range(src_begin(), src_end());
362  }
363 
364  EdgeIterator dst_begin() const { return DstEdges.begin(); }
365  EdgeIterator dst_end() const { return DstEdges.end(); }
367  return make_range(dst_begin(), dst_end());
368  }
369 
370  void print(raw_ostream &OS) const;
371  void dump() const;
372  void collectLineCounts(FileInfo &FI);
373 
374  static uint64_t getCycleCount(const Edges &Path);
375  static void unblock(const GCOVBlock *U, BlockVector &Blocked,
376  BlockVectorLists &BlockLists);
377  static bool lookForCircuit(const GCOVBlock *V, const GCOVBlock *Start,
378  Edges &Path, BlockVector &Blocked,
379  BlockVectorLists &BlockLists,
380  const BlockVector &Blocks, uint64_t &Count);
381  static void getCyclesCount(const BlockVector &Blocks, uint64_t &Count);
382  static uint64_t getLineCount(const BlockVector &Blocks);
383 
384 private:
385  GCOVFunction &Parent;
387  uint64_t Counter = 0;
388  bool DstEdgesAreSorted = true;
392 };
393 
394 class FileInfo {
395 protected:
396  // It is unlikely--but possible--for multiple functions to be on the same
397  // line.
398  // Therefore this typedef allows LineData.Functions to store multiple
399  // functions
400  // per instance. This is rare, however, so optimize for the common case.
405 
406  struct LineData {
407  LineData() = default;
408 
411  uint32_t LastLine = 0;
412  };
413 
414  struct GCOVCoverage {
415  GCOVCoverage(StringRef Name) : Name(Name) {}
416 
418 
419  uint32_t LogicalLines = 0;
420  uint32_t LinesExec = 0;
421 
422  uint32_t Branches = 0;
423  uint32_t BranchesExec = 0;
424  uint32_t BranchesTaken = 0;
425  };
426 
427 public:
428  FileInfo(const GCOV::Options &Options) : Options(Options) {}
429 
430  void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
431  if (Line > LineInfo[Filename].LastLine)
432  LineInfo[Filename].LastLine = Line;
433  LineInfo[Filename].Blocks[Line - 1].push_back(Block);
434  }
435 
436  void addFunctionLine(StringRef Filename, uint32_t Line,
437  const GCOVFunction *Function) {
438  if (Line > LineInfo[Filename].LastLine)
439  LineInfo[Filename].LastLine = Line;
440  LineInfo[Filename].Functions[Line - 1].push_back(Function);
441  }
442 
443  void setRunCount(uint32_t Runs) { RunCount = Runs; }
444  void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
445  void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
446  StringRef GCDAFile);
447 
448 protected:
449  std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
450  std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
451  void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
452  void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
453  uint32_t LineIndex, uint32_t &BlockNo) const;
454  void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
455  GCOVCoverage &Coverage, uint32_t &EdgeNo);
456  void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
457  uint64_t Count) const;
458 
459  void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
460  void printFuncCoverage(raw_ostream &OS) const;
461  void printFileCoverage(raw_ostream &OS) const;
462 
465  uint32_t RunCount = 0;
466  uint32_t ProgramCount = 0;
467 
470 
473 };
474 
475 } // end namespace llvm
476 
477 #endif // LLVM_SUPPORT_GCOV_H
EdgeIterator dst_begin() const
Definition: GCOV.h:364
uint64_t CallInst * C
bool PreservePaths
Definition: GCOV.h:56
GCOVBlock(GCOVFunction &P, uint32_t N)
Definition: GCOV.h:332
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool readInt(uint32_t &Val)
Definition: GCOV.h:198
typename SuperClass::const_iterator const_iterator
Definition: SmallVector.h:328
EdgeIterator src_end() const
Definition: GCOV.h:359
bool readGCDAFormat()
readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
Definition: GCOV.h:82
GCOVEdge - Collects edge information.
Definition: GCOV.h:265
This class represents lattice values for constants.
Definition: AllocatorList.h:24
bool UncondBranch
Definition: GCOV.h:57
GCOVBlock & Src
Definition: GCOV.h:268
void addFunctionLine(StringRef Filename, uint32_t Line, const GCOVFunction *Function)
Definition: GCOV.h:436
bool AllBlocks
Definition: GCOV.h:52
bool readLineTag()
readLineTag - If cursor points to a line tag then increment the cursor and return true otherwise retu...
Definition: GCOV.h:152
void setProgramCount(uint32_t Programs)
Definition: GCOV.h:444
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
bool readString(StringRef &Str)
Definition: GCOV.h:217
BlockIterator block_begin() const
Definition: GCOV.h:290
iterator_range< EdgeIterator > srcs() const
Definition: GCOV.h:360
void addLine(uint32_t N)
Definition: GCOV.h:336
uint32_t getChecksum() const
Definition: GCOV.h:250
A struct for passing gcov options between functions.
Definition: GCOV.h:47
uint64_t getCursor() const
Definition: GCOV.h:234
F(f)
void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block)
Definition: GCOV.h:430
GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific read operations.
Definition: GCOV.h:66
bool FuncCoverage
Definition: GCOV.h:55
uint32_t getLastLine() const
Definition: GCOV.h:337
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
FuncCoverageMap FuncCoverages
Definition: GCOV.h:472
EdgeIterator src_begin() const
Definition: GCOV.h:358
amdgpu Simplify well known AMD library false Value Value const Twine & Name
uint64_t getCount() const
Definition: GCOV.h:339
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
bool BranchInfo
Definition: GCOV.h:53
GCOVBlock & Dst
Definition: GCOV.h:269
bool readArcTag()
readArcTag - If cursor points to an gcda arc tag then increment the cursor and return true otherwise ...
Definition: GCOV.h:164
StringRef getName() const
Definition: GCOV.h:284
void addDstEdge(GCOVEdge *Edge)
Definition: GCOV.h:346
StringMap< LineData > LineInfo
Definition: GCOV.h:464
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
GCOVBlock - Collects block information.
Definition: GCOV.h:312
GCOVFunction(GCOVFile &P)
Definition: GCOV.h:280
bool BranchCount
Definition: GCOV.h:54
SmallVectorImpl< GCOVEdge * >::const_iterator EdgeIterator
Definition: GCOV.h:327
bool readInt64(uint64_t &Val)
Definition: GCOV.h:209
const GCOV::Options & Options
Definition: GCOV.h:463
#define P(N)
BlockIterator block_end() const
Definition: GCOV.h:291
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
void addSrcEdge(GCOVEdge *Edge)
Definition: GCOV.h:341
iterator_range< EdgeIterator > dsts() const
Definition: GCOV.h:366
bool readBlockTag()
readBlockTag - If cursor points to a block tag then increment the cursor and return true otherwise re...
Definition: GCOV.h:128
size_t getNumSrcEdges() const
Definition: GCOV.h:354
bool readGCNOFormat()
readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
Definition: GCOV.h:71
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
void advanceCursor(uint32_t n)
Definition: GCOV.h:235
const GCOVFunction & getParent() const
Definition: GCOV.h:335
GCOVVersion
Definition: GCOV.h:44
Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
Definition: GCOV.h:48
bool readEdgeTag()
readEdgeTag - If cursor points to an edge tag then increment the cursor and return true otherwise ret...
Definition: GCOV.h:140
StringRef getFilename() const
Definition: GCOV.h:285
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
uint32_t Number
Definition: Profile.cpp:48
GCOVBuffer(MemoryBuffer *B)
Definition: GCOV.h:68
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
iterator_range< BlockIterator > blocks() const
Definition: GCOV.h:292
GCOVEdge(GCOVBlock &S, GCOVBlock &D)
Definition: GCOV.h:266
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:727
An iterator type that allows iterating over the pointees via some other iterator. ...
Definition: iterator.h:287
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:710
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:42
A range adaptor for a pair of iterators.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:220
size_t getNumBlocks() const
Definition: GCOV.h:286
FileInfo(const GCOV::Options &Options)
Definition: GCOV.h:428
size_t getNumDstEdges() const
Definition: GCOV.h:355
GCOVFunction - Collects function information.
Definition: GCOV.h:275
BlockLines Blocks
Definition: GCOV.h:409
FunctionLines Functions
Definition: GCOV.h:410
#define N
FileCoverageList FileCoverages
Definition: GCOV.h:471
bool readObjectTag()
readObjectTag - If cursor points to an object summary tag then increment the cursor and return true o...
Definition: GCOV.h:176
GCOVFile - Collects coverage information for one pair of coverage file (.gcno and ...
Definition: GCOV.h:244
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
EdgeIterator dst_end() const
Definition: GCOV.h:365
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
bool LongFileNames
Definition: GCOV.h:58
bool readProgramTag()
readProgramTag - If cursor points to a program summary tag then increment the cursor and return true ...
Definition: GCOV.h:188
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
bool readFunctionTag()
readFunctionTag - If cursor points to a function tag then increment the cursor and return true otherw...
Definition: GCOV.h:116
void setRunCount(uint32_t Runs)
Definition: GCOV.h:443
bool readGCOVVersion(GCOV::GCOVVersion &Version)
readGCOVVersion - Read GCOV version.
Definition: GCOV.h:93
GCOVCoverage(StringRef Name)
Definition: GCOV.h:415
const uint64_t Version
Definition: InstrProf.h:895