Use a map instead of vector to store line counts.
[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   uint32_t readInt() {
130     uint32_t Result;
131     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
132     assert (Str.empty() == false && "Unexpected memory buffer end!");
133     Cursor += 4;
134     Result = *(const uint32_t *)(Str.data());
135     return Result;
136   }
137
138   uint64_t readInt64() {
139     uint64_t Lo = readInt();
140     uint64_t Hi = readInt();
141     uint64_t Result = Lo | (Hi << 32);
142     return Result;
143   }
144
145   StringRef readString() {
146     uint32_t Len = readInt() * 4;
147     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
148     Cursor += Len;
149     return Str.split('\0').first;
150   }
151
152   uint64_t getCursor() const { return Cursor; }
153 private:
154   MemoryBuffer *Buffer;
155   uint64_t Cursor;
156 };
157
158 /// GCOVFile - Collects coverage information for one pair of coverage file
159 /// (.gcno and .gcda).
160 class GCOVFile {
161 public:
162   GCOVFile() {}
163   ~GCOVFile();
164   bool read(GCOVBuffer &Buffer);
165   void dump();
166   void collectLineCounts(FileInfo &FI);
167 private:
168   SmallVector<GCOVFunction *, 16> Functions;
169 };
170
171 /// GCOVFunction - Collects function information.
172 class GCOVFunction {
173 public:
174   GCOVFunction() : Ident(0), LineNumber(0) {}
175   ~GCOVFunction();
176   bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format);
177   void dump();
178   void collectLineCounts(FileInfo &FI);
179 private:
180   uint32_t Ident;
181   uint32_t LineNumber;
182   StringRef Name;
183   StringRef Filename;
184   SmallVector<GCOVBlock *, 16> Blocks;
185 };
186
187 /// GCOVBlock - Collects block information.
188 class GCOVBlock {
189 public:
190   GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
191   ~GCOVBlock();
192   void addEdge(uint32_t N) { Edges.push_back(N); }
193   void addLine(StringRef Filename, uint32_t LineNo);
194   void addCount(uint64_t N) { Counter = N; }
195   void dump();
196   void collectLineCounts(FileInfo &FI);
197 private:
198   uint32_t Number;
199   uint64_t Counter;
200   SmallVector<uint32_t, 16> Edges;
201   StringMap<GCOVLines *> Lines;
202 };
203
204 /// GCOVLines - A wrapper around a vector of int to keep track of line nos.
205 class GCOVLines {
206 public:
207   ~GCOVLines() { Lines.clear(); }
208   void add(uint32_t N) { Lines.push_back(N); }
209   void collectLineCounts(FileInfo &FI, StringRef Filename, uint64_t Count);
210   void dump();
211
212 private:
213   SmallVector<uint32_t, 4> Lines;
214 };
215
216 typedef DenseMap<uint32_t, uint64_t> LineCounts;
217 class FileInfo {
218 public:
219   void addLineCount(StringRef Filename, uint32_t Line, uint64_t Count) {
220     LineInfo[Filename][Line-1] = Count;
221   }
222   void print(StringRef gcnoFile, StringRef gcdaFile);
223 private:
224   StringMap<LineCounts> LineInfo;
225 };
226
227 }
228
229 #endif