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