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