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