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