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