llvm-cov: Added -a option for block data.
[oota-llvm.git] / include / llvm / Support / GCOV.h
1 //===- GCOV.h - LLVM coverage tool ----------------------------------------===//
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_SUPPORT_GCOV_H
16 #define LLVM_SUPPORT_GCOV_H
17
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/raw_ostream.h"
23
24 namespace llvm {
25
26 class GCOVFunction;
27 class GCOVBlock;
28 class FileInfo;
29
30 namespace GCOV {
31   enum GCOVVersion {
32     V402,
33     V404
34   };
35 } // end GCOV namespace
36
37 /// GCOVOptions - A struct for passing gcov options between functions.
38 struct GCOVOptions {
39   GCOVOptions(bool A): AllBlocks(A) {}
40
41   bool AllBlocks;
42 };
43
44 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
45 /// read operations.
46 class GCOVBuffer {
47 public:
48   GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
49   
50   /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
51   bool readGCNOFormat() {
52     StringRef File = Buffer->getBuffer().slice(0, 4);
53     if (File != "oncg") {
54       errs() << "Unexpected file type: " << File << ".\n";
55       return false;
56     }
57     Cursor = 4;
58     return true;
59   }
60
61   /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
62   bool readGCDAFormat() {
63     StringRef File = Buffer->getBuffer().slice(0, 4);
64     if (File != "adcg") {
65       errs() << "Unexpected file type: " << File << ".\n";
66       return false;
67     }
68     Cursor = 4;
69     return true;
70   }
71
72   /// readGCOVVersion - Read GCOV version.
73   bool readGCOVVersion(GCOV::GCOVVersion &Version) {
74     StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4);
75     if (VersionStr == "*204") {
76       Cursor += 4;
77       Version = GCOV::V402;
78       return true;
79     }
80     if (VersionStr == "*404") {
81       Cursor += 4;
82       Version = GCOV::V404;
83       return true;
84     }
85     errs() << "Unexpected version: " << VersionStr << ".\n";
86     return false;
87   }
88
89   /// readFunctionTag - If cursor points to a function tag then increment the
90   /// cursor and return true otherwise return false.
91   bool readFunctionTag() {
92     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
93     if (Tag.empty() || 
94         Tag[0] != '\0' || Tag[1] != '\0' ||
95         Tag[2] != '\0' || Tag[3] != '\1') {
96       return false;
97     }
98     Cursor += 4;
99     return true;
100   }
101
102   /// readBlockTag - If cursor points to a block tag then increment the
103   /// cursor and return true otherwise return false.
104   bool readBlockTag() {
105     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
106     if (Tag.empty() || 
107         Tag[0] != '\0' || Tag[1] != '\0' ||
108         Tag[2] != '\x41' || Tag[3] != '\x01') {
109       return false;
110     }
111     Cursor += 4;
112     return true;
113   }
114
115   /// readEdgeTag - If cursor points to an edge tag then increment the
116   /// cursor and return true otherwise return false.
117   bool readEdgeTag() {
118     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
119     if (Tag.empty() || 
120         Tag[0] != '\0' || Tag[1] != '\0' ||
121         Tag[2] != '\x43' || Tag[3] != '\x01') {
122       return false;
123     }
124     Cursor += 4;
125     return true;
126   }
127
128   /// readLineTag - If cursor points to a line tag then increment the
129   /// cursor and return true otherwise return false.
130   bool readLineTag() {
131     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
132     if (Tag.empty() || 
133         Tag[0] != '\0' || Tag[1] != '\0' ||
134         Tag[2] != '\x45' || Tag[3] != '\x01') {
135       return false;
136     }
137     Cursor += 4;
138     return true;
139   }
140
141   /// readArcTag - If cursor points to an gcda arc tag then increment the
142   /// cursor and return true otherwise return false.
143   bool readArcTag() {
144     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
145     if (Tag.empty() || 
146         Tag[0] != '\0' || Tag[1] != '\0' ||
147         Tag[2] != '\xa1' || Tag[3] != '\1') {
148       return false;
149     }
150     Cursor += 4;
151     return true;
152   }
153
154   /// readObjectTag - If cursor points to an object summary tag then increment
155   /// the cursor and return true otherwise return false.
156   bool readObjectTag() {
157     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
158     if (Tag.empty() ||
159         Tag[0] != '\0' || Tag[1] != '\0' ||
160         Tag[2] != '\0' || Tag[3] != '\xa1') {
161       return false;
162     }
163     Cursor += 4;
164     return true;
165   }
166
167   /// readProgramTag - If cursor points to a program summary tag then increment
168   /// the cursor and return true otherwise return false.
169   bool readProgramTag() {
170     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
171     if (Tag.empty() ||
172         Tag[0] != '\0' || Tag[1] != '\0' ||
173         Tag[2] != '\0' || Tag[3] != '\xa3') {
174       return false;
175     }
176     Cursor += 4;
177     return true;
178   }
179
180   bool readInt(uint32_t &Val) {
181     if (Buffer->getBuffer().size() < Cursor+4) {
182       errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
183       return false;
184     }
185     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
186     Cursor += 4;
187     Val = *(const uint32_t *)(Str.data());
188     return true;
189   }
190
191   bool readInt64(uint64_t &Val) {
192     uint32_t Lo, Hi;
193     if (!readInt(Lo) || !readInt(Hi)) return false;
194     Val = ((uint64_t)Hi << 32) | Lo;
195     return true;
196   }
197
198   bool readString(StringRef &Str) {
199     uint32_t Len;
200     if (!readInt(Len)) return false;
201     Len *= 4;
202     if (Buffer->getBuffer().size() < Cursor+Len) {
203       errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
204       return false;
205     }
206     Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
207     Cursor += Len;
208     return true;
209   }
210
211   uint64_t getCursor() const { return Cursor; }
212   void advanceCursor(uint32_t n) { Cursor += n*4; }
213 private:
214   MemoryBuffer *Buffer;
215   uint64_t Cursor;
216 };
217
218 /// GCOVFile - Collects coverage information for one pair of coverage file
219 /// (.gcno and .gcda).
220 class GCOVFile {
221 public:
222   GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
223                ProgramCount(0) {}
224   ~GCOVFile();
225   bool readGCNO(GCOVBuffer &Buffer);
226   bool readGCDA(GCOVBuffer &Buffer);
227   uint32_t getChecksum() const { return Checksum; }
228   void dump() const;
229   void collectLineCounts(FileInfo &FI);
230 private:
231   bool GCNOInitialized;
232   GCOV::GCOVVersion Version;
233   uint32_t Checksum;
234   SmallVector<GCOVFunction *, 16> Functions;
235   uint32_t RunCount;
236   uint32_t ProgramCount;
237 };
238
239 struct GCOVEdge {
240   GCOVEdge(GCOVBlock *S, GCOVBlock *D): Src(S), Dst(D), Count(0) {}
241
242   GCOVBlock *Src;
243   GCOVBlock *Dst;
244   uint64_t Count;
245 };
246
247 /// GCOVFunction - Collects function information.
248 class GCOVFunction {
249 public:
250   GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
251   ~GCOVFunction();
252   bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
253   bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
254   StringRef getFilename() const { return Filename; }
255   size_t getNumBlocks() const { return Blocks.size(); }
256   void dump() const;
257   void collectLineCounts(FileInfo &FI);
258 private:
259   GCOVFile &Parent;
260   uint32_t Ident;
261   uint32_t Checksum;
262   uint32_t LineNumber;
263   StringRef Name;
264   StringRef Filename;
265   SmallVector<GCOVBlock *, 16> Blocks;
266   SmallVector<GCOVEdge *, 16> Edges;
267 };
268
269 /// GCOVBlock - Collects block information.
270 class GCOVBlock {
271 public:
272   typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
273
274   GCOVBlock(GCOVFunction &P, uint32_t N) :
275     Parent(P), Number(N), Counter(0), SrcEdges(), DstEdges(), Lines() {}
276   ~GCOVBlock();
277   void addSrcEdge(GCOVEdge *Edge) {
278     assert(Edge->Dst == this); // up to caller to ensure edge is valid
279     SrcEdges.push_back(Edge);
280   }
281   void addDstEdge(GCOVEdge *Edge) {
282     assert(Edge->Src == this); // up to caller to ensure edge is valid
283     DstEdges.push_back(Edge);
284   }
285   void addLine(uint32_t N) { Lines.push_back(N); }
286   uint32_t getLastLine() const { return Lines.back(); }
287   void addCount(size_t DstEdgeNo, uint64_t N);
288   uint64_t getCount() const { return Counter; }
289   size_t getNumSrcEdges() const { return SrcEdges.size(); }
290   size_t getNumDstEdges() const { return DstEdges.size(); }
291
292   EdgeIterator src_begin() const { return SrcEdges.begin(); }
293   EdgeIterator src_end() const { return SrcEdges.end(); }
294   EdgeIterator dst_begin() const { return DstEdges.begin(); }
295   EdgeIterator dst_end() const { return DstEdges.end(); }
296
297   void dump() const;
298   void collectLineCounts(FileInfo &FI);
299 private:
300   GCOVFunction &Parent;
301   uint32_t Number;
302   uint64_t Counter;
303   SmallVector<GCOVEdge *, 16> SrcEdges;
304   SmallVector<GCOVEdge *, 16> DstEdges;
305   SmallVector<uint32_t, 16> Lines;
306 };
307
308 typedef SmallVector<const GCOVBlock *, 4> BlockVector;
309 typedef DenseMap<uint32_t, BlockVector> LineData;
310 class FileInfo {
311 public:
312   void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
313     LineInfo[Filename][Line-1].push_back(Block);
314   }
315   void setRunCount(uint32_t Runs) { RunCount = Runs; }
316   void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
317   void print(StringRef GCNOFile, StringRef GCDAFile,
318              const GCOVOptions &Options) const;
319 private:
320   StringMap<LineData> LineInfo;
321   uint32_t RunCount;
322   uint32_t ProgramCount;
323 };
324
325 }
326
327 #endif