llvm-cov: Replaced asserts with proper error handling.
[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   /// readObjectTag - If cursor points to an object summary tag then increment
130   /// the cursor and return true otherwise return false.
131   bool readObjectTag() {
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] != '\xa1') {
136       return false;
137     }
138     Cursor += 4;
139     return true;
140   }
141
142   /// readProgramTag - If cursor points to a program summary tag then increment
143   /// the cursor and return true otherwise return false.
144   bool readProgramTag() {
145     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
146     if (Tag.empty() ||
147         Tag[0] != '\0' || Tag[1] != '\0' ||
148         Tag[2] != '\0' || Tag[3] != '\xa3') {
149       return false;
150     }
151     Cursor += 4;
152     return true;
153   }
154
155   bool readInt(uint32_t &Val) {
156     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
157     if (Str.empty()) {
158       errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
159       return false;
160     }
161     Cursor += 4;
162     Val = *(const uint32_t *)(Str.data());
163     return true;
164   }
165
166   bool readInt64(uint64_t &Val) {
167     uint32_t Lo, Hi;
168     if (!readInt(Lo) || !readInt(Hi)) return false;
169     Val = ((uint64_t)Hi << 32) | Lo;
170     return true;
171   }
172
173   bool readString(StringRef &Str) {
174     uint32_t Len;
175     if (!readInt(Len)) return false;
176     Len *= 4;
177     if (Buffer->getBuffer().size() < Cursor+Len) {
178       errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
179       return false;
180     }
181     Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
182     Cursor += Len;
183     return true;
184   }
185
186   uint64_t getCursor() const { return Cursor; }
187   void advanceCursor(uint32_t n) { Cursor += n*4; }
188 private:
189   MemoryBuffer *Buffer;
190   uint64_t Cursor;
191 };
192
193 /// GCOVFile - Collects coverage information for one pair of coverage file
194 /// (.gcno and .gcda).
195 class GCOVFile {
196 public:
197   GCOVFile() : Functions(), RunCount(0), ProgramCount(0) {}
198   ~GCOVFile();
199   bool read(GCOVBuffer &Buffer);
200   void dump();
201   void collectLineCounts(FileInfo &FI);
202 private:
203   SmallVector<GCOVFunction *, 16> Functions;
204   uint32_t RunCount;
205   uint32_t ProgramCount;
206 };
207
208 /// GCOVFunction - Collects function information.
209 class GCOVFunction {
210 public:
211   GCOVFunction() : Ident(0), LineNumber(0) {}
212   ~GCOVFunction();
213   bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format);
214   void dump();
215   void collectLineCounts(FileInfo &FI);
216 private:
217   uint32_t Ident;
218   uint32_t LineNumber;
219   StringRef Name;
220   StringRef Filename;
221   SmallVector<GCOVBlock *, 16> Blocks;
222 };
223
224 /// GCOVBlock - Collects block information.
225 class GCOVBlock {
226 public:
227   GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
228   ~GCOVBlock();
229   void addEdge(uint32_t N) { Edges.push_back(N); }
230   void addLine(StringRef Filename, uint32_t LineNo);
231   void addCount(uint64_t N) { Counter += N; }
232   size_t getNumEdges() { return Edges.size(); }
233   void dump();
234   void collectLineCounts(FileInfo &FI);
235 private:
236   uint32_t Number;
237   uint64_t Counter;
238   SmallVector<uint32_t, 16> Edges;
239   StringMap<GCOVLines *> Lines;
240 };
241
242 /// GCOVLines - A wrapper around a vector of int to keep track of line nos.
243 class GCOVLines {
244 public:
245   ~GCOVLines() { Lines.clear(); }
246   void add(uint32_t N) { Lines.push_back(N); }
247   void collectLineCounts(FileInfo &FI, StringRef Filename, uint64_t Count);
248   void dump();
249
250 private:
251   SmallVector<uint32_t, 4> Lines;
252 };
253
254 typedef DenseMap<uint32_t, uint64_t> LineCounts;
255 class FileInfo {
256 public:
257   void addLineCount(StringRef Filename, uint32_t Line, uint64_t Count) {
258     LineInfo[Filename][Line-1] += Count;
259   }
260   void setRunCount(uint32_t Runs) { RunCount = Runs; }
261   void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
262   void print(raw_fd_ostream &OS, StringRef gcnoFile, StringRef gcdaFile);
263 private:
264   StringMap<LineCounts> LineInfo;
265   uint32_t RunCount;
266   uint32_t ProgramCount;
267 };
268
269 }
270
271 #endif