902f2dbc83bf018dba3db05d26ae862235a13bb8
[oota-llvm.git] / include / llvm / Support / GCOV.h
1 //===- GCOV.h - LLVM coverage tool ----------------------------------------===//
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/MapVector.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/raw_ostream.h"
24
25 namespace llvm {
26
27 class GCOVFunction;
28 class GCOVBlock;
29 class FileInfo;
30
31 namespace GCOV {
32   enum GCOVVersion {
33     V402,
34     V404
35   };
36 } // end GCOV namespace
37
38 /// GCOVOptions - A struct for passing gcov options between functions.
39 struct GCOVOptions {
40   GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U)
41       : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
42         PreservePaths(P), UncondBranch(U) {}
43
44   bool AllBlocks;
45   bool BranchInfo;
46   bool BranchCount;
47   bool FuncCoverage;
48   bool PreservePaths;
49   bool UncondBranch;
50 };
51
52 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
53 /// read operations.
54 class GCOVBuffer {
55 public:
56   GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
57   
58   /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
59   bool readGCNOFormat() {
60     StringRef File = Buffer->getBuffer().slice(0, 4);
61     if (File != "oncg") {
62       errs() << "Unexpected file type: " << File << ".\n";
63       return false;
64     }
65     Cursor = 4;
66     return true;
67   }
68
69   /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
70   bool readGCDAFormat() {
71     StringRef File = Buffer->getBuffer().slice(0, 4);
72     if (File != "adcg") {
73       errs() << "Unexpected file type: " << File << ".\n";
74       return false;
75     }
76     Cursor = 4;
77     return true;
78   }
79
80   /// readGCOVVersion - Read GCOV version.
81   bool readGCOVVersion(GCOV::GCOVVersion &Version) {
82     StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4);
83     if (VersionStr == "*204") {
84       Cursor += 4;
85       Version = GCOV::V402;
86       return true;
87     }
88     if (VersionStr == "*404") {
89       Cursor += 4;
90       Version = GCOV::V404;
91       return true;
92     }
93     errs() << "Unexpected version: " << VersionStr << ".\n";
94     return false;
95   }
96
97   /// readFunctionTag - If cursor points to a function tag then increment the
98   /// cursor and return true otherwise return false.
99   bool readFunctionTag() {
100     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
101     if (Tag.empty() || 
102         Tag[0] != '\0' || Tag[1] != '\0' ||
103         Tag[2] != '\0' || Tag[3] != '\1') {
104       return false;
105     }
106     Cursor += 4;
107     return true;
108   }
109
110   /// readBlockTag - If cursor points to a block tag then increment the
111   /// cursor and return true otherwise return false.
112   bool readBlockTag() {
113     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
114     if (Tag.empty() || 
115         Tag[0] != '\0' || Tag[1] != '\0' ||
116         Tag[2] != '\x41' || Tag[3] != '\x01') {
117       return false;
118     }
119     Cursor += 4;
120     return true;
121   }
122
123   /// readEdgeTag - If cursor points to an edge tag then increment the
124   /// cursor and return true otherwise return false.
125   bool readEdgeTag() {
126     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
127     if (Tag.empty() || 
128         Tag[0] != '\0' || Tag[1] != '\0' ||
129         Tag[2] != '\x43' || Tag[3] != '\x01') {
130       return false;
131     }
132     Cursor += 4;
133     return true;
134   }
135
136   /// readLineTag - If cursor points to a line tag then increment the
137   /// cursor and return true otherwise return false.
138   bool readLineTag() {
139     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
140     if (Tag.empty() || 
141         Tag[0] != '\0' || Tag[1] != '\0' ||
142         Tag[2] != '\x45' || Tag[3] != '\x01') {
143       return false;
144     }
145     Cursor += 4;
146     return true;
147   }
148
149   /// readArcTag - If cursor points to an gcda arc tag then increment the
150   /// cursor and return true otherwise return false.
151   bool readArcTag() {
152     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
153     if (Tag.empty() || 
154         Tag[0] != '\0' || Tag[1] != '\0' ||
155         Tag[2] != '\xa1' || Tag[3] != '\1') {
156       return false;
157     }
158     Cursor += 4;
159     return true;
160   }
161
162   /// readObjectTag - If cursor points to an object summary tag then increment
163   /// the cursor and return true otherwise return false.
164   bool readObjectTag() {
165     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
166     if (Tag.empty() ||
167         Tag[0] != '\0' || Tag[1] != '\0' ||
168         Tag[2] != '\0' || Tag[3] != '\xa1') {
169       return false;
170     }
171     Cursor += 4;
172     return true;
173   }
174
175   /// readProgramTag - If cursor points to a program summary tag then increment
176   /// the cursor and return true otherwise return false.
177   bool readProgramTag() {
178     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
179     if (Tag.empty() ||
180         Tag[0] != '\0' || Tag[1] != '\0' ||
181         Tag[2] != '\0' || Tag[3] != '\xa3') {
182       return false;
183     }
184     Cursor += 4;
185     return true;
186   }
187
188   bool readInt(uint32_t &Val) {
189     if (Buffer->getBuffer().size() < Cursor+4) {
190       errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
191       return false;
192     }
193     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
194     Cursor += 4;
195     Val = *(const uint32_t *)(Str.data());
196     return true;
197   }
198
199   bool readInt64(uint64_t &Val) {
200     uint32_t Lo, Hi;
201     if (!readInt(Lo) || !readInt(Hi)) return false;
202     Val = ((uint64_t)Hi << 32) | Lo;
203     return true;
204   }
205
206   bool readString(StringRef &Str) {
207     uint32_t Len = 0;
208     // Keep reading until we find a non-zero length. This emulates gcov's
209     // behaviour, which appears to do the same.
210     while (Len == 0)
211       if (!readInt(Len)) return false;
212     Len *= 4;
213     if (Buffer->getBuffer().size() < Cursor+Len) {
214       errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
215       return false;
216     }
217     Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
218     Cursor += Len;
219     return true;
220   }
221
222   uint64_t getCursor() const { return Cursor; }
223   void advanceCursor(uint32_t n) { Cursor += n*4; }
224 private:
225   MemoryBuffer *Buffer;
226   uint64_t Cursor;
227 };
228
229 /// GCOVFile - Collects coverage information for one pair of coverage file
230 /// (.gcno and .gcda).
231 class GCOVFile {
232 public:
233   GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
234                ProgramCount(0) {}
235   ~GCOVFile();
236   bool readGCNO(GCOVBuffer &Buffer);
237   bool readGCDA(GCOVBuffer &Buffer);
238   uint32_t getChecksum() const { return Checksum; }
239   void dump() const;
240   void collectLineCounts(FileInfo &FI);
241 private:
242   bool GCNOInitialized;
243   GCOV::GCOVVersion Version;
244   uint32_t Checksum;
245   SmallVector<GCOVFunction *, 16> Functions;
246   uint32_t RunCount;
247   uint32_t ProgramCount;
248 };
249
250 /// GCOVEdge - Collects edge information.
251 struct GCOVEdge {
252   GCOVEdge(GCOVBlock *S, GCOVBlock *D): Src(S), Dst(D), Count(0) {}
253
254   GCOVBlock *Src;
255   GCOVBlock *Dst;
256   uint64_t Count;
257 };
258
259 /// GCOVFunction - Collects function information.
260 class GCOVFunction {
261 public:
262   typedef SmallVectorImpl<GCOVBlock *>::const_iterator BlockIterator;
263
264   GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
265   ~GCOVFunction();
266   bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
267   bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
268   StringRef getName() const { return Name; }
269   StringRef getFilename() const { return Filename; }
270   size_t getNumBlocks() const { return Blocks.size(); }
271   uint64_t getEntryCount() const;
272   uint64_t getExitCount() const;
273
274   BlockIterator block_begin() const { return Blocks.begin(); }
275   BlockIterator block_end() const { return Blocks.end(); }
276
277   void dump() const;
278   void collectLineCounts(FileInfo &FI);
279 private:
280   GCOVFile &Parent;
281   uint32_t Ident;
282   uint32_t Checksum;
283   uint32_t LineNumber;
284   StringRef Name;
285   StringRef Filename;
286   SmallVector<GCOVBlock *, 16> Blocks;
287   SmallVector<GCOVEdge *, 16> Edges;
288 };
289
290 /// GCOVBlock - Collects block information.
291 class GCOVBlock {
292   struct EdgeWeight {
293     EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {}
294
295     GCOVBlock *Dst;
296     uint64_t Count;
297   };
298
299   struct SortDstEdgesFunctor {
300     bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
301       return E1->Dst->Number < E2->Dst->Number;
302     }
303   };
304 public:
305   typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
306
307   GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0),
308     DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {}
309   ~GCOVBlock();
310   const GCOVFunction &getParent() const { return Parent; }
311   void addLine(uint32_t N) { Lines.push_back(N); }
312   uint32_t getLastLine() const { return Lines.back(); }
313   void addCount(size_t DstEdgeNo, uint64_t N);
314   uint64_t getCount() const { return Counter; }
315
316   void addSrcEdge(GCOVEdge *Edge) {
317     assert(Edge->Dst == this); // up to caller to ensure edge is valid
318     SrcEdges.push_back(Edge);
319   }
320   void addDstEdge(GCOVEdge *Edge) {
321     assert(Edge->Src == this); // up to caller to ensure edge is valid
322     // Check if adding this edge causes list to become unsorted.
323     if (DstEdges.size() && DstEdges.back()->Dst->Number > Edge->Dst->Number)
324       DstEdgesAreSorted = false;
325     DstEdges.push_back(Edge);
326   }
327   size_t getNumSrcEdges() const { return SrcEdges.size(); }
328   size_t getNumDstEdges() const { return DstEdges.size(); }
329   void sortDstEdges();
330
331   EdgeIterator src_begin() const { return SrcEdges.begin(); }
332   EdgeIterator src_end() const { return SrcEdges.end(); }
333   EdgeIterator dst_begin() const { return DstEdges.begin(); }
334   EdgeIterator dst_end() const { return DstEdges.end(); }
335
336   void dump() const;
337   void collectLineCounts(FileInfo &FI);
338 private:
339   GCOVFunction &Parent;
340   uint32_t Number;
341   uint64_t Counter;
342   bool DstEdgesAreSorted;
343   SmallVector<GCOVEdge *, 16> SrcEdges;
344   SmallVector<GCOVEdge *, 16> DstEdges;
345   SmallVector<uint32_t, 16> Lines;
346 };
347
348 class FileInfo {
349   // It is unlikely--but possible--for multiple functions to be on the same line.
350   // Therefore this typedef allows LineData.Functions to store multiple functions
351   // per instance. This is rare, however, so optimize for the common case.
352   typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
353   typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
354   typedef SmallVector<const GCOVBlock *, 4> BlockVector;
355   typedef DenseMap<uint32_t, BlockVector> BlockLines;
356
357   struct LineData {
358     BlockLines Blocks;
359     FunctionLines Functions;
360   };
361
362   struct GCOVCoverage {
363     GCOVCoverage(StringRef Name) :
364       Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0),
365       BranchesTaken(0) {}
366
367     StringRef Name;
368
369     uint32_t LogicalLines;
370     uint32_t LinesExec;
371
372     uint32_t Branches;
373     uint32_t BranchesExec;
374     uint32_t BranchesTaken;
375   };
376 public:
377   FileInfo(const GCOVOptions &Options) :
378     Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
379
380   void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
381     LineInfo[Filename].Blocks[Line-1].push_back(Block);
382   }
383   void addFunctionLine(StringRef Filename, uint32_t Line,
384                        const GCOVFunction *Function) {
385     LineInfo[Filename].Functions[Line-1].push_back(Function);
386   }
387   void setRunCount(uint32_t Runs) { RunCount = Runs; }
388   void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
389   void print(StringRef GCNOFile, StringRef GCDAFile);
390 private:
391   void printFunctionSummary(raw_fd_ostream &OS,
392                             const FunctionVector &Funcs) const;
393   void printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
394                       uint32_t LineIndex, uint32_t &BlockNo) const;
395   void printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
396                        GCOVCoverage &Coverage, uint32_t &EdgeNo);
397   void printUncondBranchInfo(raw_fd_ostream &OS, uint32_t &EdgeNo,
398                              uint64_t Count) const;
399
400   void printCoverage(const GCOVCoverage &Coverage) const;
401   void printFuncCoverage() const;
402   void printFileCoverage() const;
403
404   const GCOVOptions &Options;
405   StringMap<LineData> LineInfo;
406   uint32_t RunCount;
407   uint32_t ProgramCount;
408
409   typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4>
410       FileCoverageList;
411   typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
412
413   FileCoverageList FileCoverages;
414   FuncCoverageMap FuncCoverages;
415 };
416
417 }
418
419 #endif