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