1//===-- llvm/Support/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_GCOV_H
16#define LLVM_GCOV_H
17
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/StringMap.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/raw_ostream.h"
22
23namespace llvm {
24
25class GCOVFunction;
26class GCOVBlock;
27class GCOVLines;
28class FileInfo;
29
30namespace GCOV {
31  enum GCOVFormat {
32    InvalidGCOV,
33    GCNO_402,
34    GCNO_404,
35    GCDA_402,
36    GCDA_404
37  };
38} // end GCOV namespace
39
40/// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
41/// read operations.
42class GCOVBuffer {
43public:
44  GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
45
46  /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
47  GCOV::GCOVFormat readGCOVFormat() {
48    StringRef Magic = Buffer->getBuffer().slice(0, 12);
49    Cursor = 12;
50    if (Magic == "oncg*404MVLL")
51      return GCOV::GCNO_404;
52    else if (Magic == "oncg*204MVLL")
53      return GCOV::GCNO_402;
54    else if (Magic == "adcg*404MVLL")
55      return GCOV::GCDA_404;
56    else if (Magic == "adcg*204MVLL")
57      return GCOV::GCDA_402;
58
59    Cursor = 0;
60    return GCOV::InvalidGCOV;
61  }
62
63  /// readFunctionTag - If cursor points to a function tag then increment the
64  /// cursor and return true otherwise return false.
65  bool readFunctionTag() {
66    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
67    if (Tag.empty() ||
68        Tag[0] != '\0' || Tag[1] != '\0' ||
69        Tag[2] != '\0' || Tag[3] != '\1') {
70      return false;
71    }
72    Cursor += 4;
73    return true;
74  }
75
76  /// readBlockTag - If cursor points to a block tag then increment the
77  /// cursor and return true otherwise return false.
78  bool readBlockTag() {
79    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
80    if (Tag.empty() ||
81        Tag[0] != '\0' || Tag[1] != '\0' ||
82        Tag[2] != '\x41' || Tag[3] != '\x01') {
83      return false;
84    }
85    Cursor += 4;
86    return true;
87  }
88
89  /// readEdgeTag - If cursor points to an edge tag then increment the
90  /// cursor and return true otherwise return false.
91  bool readEdgeTag() {
92    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
93    if (Tag.empty() ||
94        Tag[0] != '\0' || Tag[1] != '\0' ||
95        Tag[2] != '\x43' || Tag[3] != '\x01') {
96      return false;
97    }
98    Cursor += 4;
99    return true;
100  }
101
102  /// readLineTag - If cursor points to a line tag then increment the
103  /// cursor and return true otherwise return false.
104  bool readLineTag() {
105    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
106    if (Tag.empty() ||
107        Tag[0] != '\0' || Tag[1] != '\0' ||
108        Tag[2] != '\x45' || Tag[3] != '\x01') {
109      return false;
110    }
111    Cursor += 4;
112    return true;
113  }
114
115  /// readArcTag - If cursor points to an gcda arc tag then increment the
116  /// cursor and return true otherwise return false.
117  bool readArcTag() {
118    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
119    if (Tag.empty() ||
120        Tag[0] != '\0' || Tag[1] != '\0' ||
121        Tag[2] != '\xa1' || Tag[3] != '\1') {
122      return false;
123    }
124    Cursor += 4;
125    return true;
126  }
127
128  uint32_t readInt() {
129    uint32_t Result;
130    StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
131    assert (Str.empty() == false && "Unexpected memory buffer end!");
132    Cursor += 4;
133    Result = *(const uint32_t *)(Str.data());
134    return Result;
135  }
136
137  uint64_t readInt64() {
138    uint64_t Lo = readInt();
139    uint64_t Hi = readInt();
140    uint64_t Result = Lo | (Hi << 32);
141    return Result;
142  }
143
144  StringRef readString() {
145    uint32_t Len = readInt() * 4;
146    StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
147    Cursor += Len;
148    return Str;
149  }
150
151  uint64_t getCursor() const { return Cursor; }
152private:
153  MemoryBuffer *Buffer;
154  uint64_t Cursor;
155};
156
157/// GCOVFile - Collects coverage information for one pair of coverage file
158/// (.gcno and .gcda).
159class GCOVFile {
160public:
161  GCOVFile() {}
162  ~GCOVFile();
163  bool read(GCOVBuffer &Buffer);
164  void dump();
165  void collectLineCounts(FileInfo &FI);
166private:
167  SmallVector<GCOVFunction *, 16> Functions;
168};
169
170/// GCOVFunction - Collects function information.
171class GCOVFunction {
172public:
173  GCOVFunction() : Ident(0), LineNumber(0) {}
174  ~GCOVFunction();
175  bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format);
176  void dump();
177  void collectLineCounts(FileInfo &FI);
178private:
179  uint32_t Ident;
180  uint32_t LineNumber;
181  StringRef Name;
182  StringRef Filename;
183  SmallVector<GCOVBlock *, 16> Blocks;
184};
185
186/// GCOVBlock - Collects block information.
187class GCOVBlock {
188public:
189  GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
190  ~GCOVBlock();
191  void addEdge(uint32_t N) { Edges.push_back(N); }
192  void addLine(StringRef Filename, uint32_t LineNo);
193  void addCount(uint64_t N) { Counter = N; }
194  void dump();
195  void collectLineCounts(FileInfo &FI);
196private:
197  uint32_t Number;
198  uint64_t Counter;
199  SmallVector<uint32_t, 16> Edges;
200  StringMap<GCOVLines *> Lines;
201};
202
203/// GCOVLines - A wrapper around a vector of int to keep track of line nos.
204class GCOVLines {
205public:
206  ~GCOVLines() { Lines.clear(); }
207  void add(uint32_t N) { Lines.push_back(N); }
208  void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count);
209  void dump();
210
211private:
212  SmallVector<uint32_t, 4> Lines;
213};
214
215typedef SmallVector<uint32_t, 16> LineCounts;
216class FileInfo {
217public:
218  void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
219  void print();
220private:
221  StringMap<LineCounts> LineInfo;
222};
223
224}
225
226#endif
227