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