Use unique_ptr to manage ownership of GCOVFunctions, Blocks, and Edges.
[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   bool readGCNO(GCOVBuffer &Buffer);
236   bool readGCDA(GCOVBuffer &Buffer);
237   uint32_t getChecksum() const { return Checksum; }
238   void dump() const;
239   void collectLineCounts(FileInfo &FI);
240 private:
241   bool GCNOInitialized;
242   GCOV::GCOVVersion Version;
243   uint32_t Checksum;
244   SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions;
245   uint32_t RunCount;
246   uint32_t ProgramCount;
247 };
248
249 /// GCOVEdge - Collects edge information.
250 struct GCOVEdge {
251   GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {}
252
253   GCOVBlock &Src;
254   GCOVBlock &Dst;
255   uint64_t Count;
256 };
257
258 /// GCOVFunction - Collects function information.
259 class GCOVFunction {
260 public:
261   typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator
262   BlockIterator;
263
264   GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
265   bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
266   bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
267   StringRef getName() const { return Name; }
268   StringRef getFilename() const { return Filename; }
269   size_t getNumBlocks() const { return Blocks.size(); }
270   uint64_t getEntryCount() const;
271   uint64_t getExitCount() const;
272
273   BlockIterator block_begin() const { return Blocks.begin(); }
274   BlockIterator block_end() const { return Blocks.end(); }
275
276   void dump() const;
277   void collectLineCounts(FileInfo &FI);
278 private:
279   GCOVFile &Parent;
280   uint32_t Ident;
281   uint32_t Checksum;
282   uint32_t LineNumber;
283   StringRef Name;
284   StringRef Filename;
285   SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks;
286   SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges;
287 };
288
289 /// GCOVBlock - Collects block information.
290 class GCOVBlock {
291   struct EdgeWeight {
292     EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {}
293
294     GCOVBlock *Dst;
295     uint64_t Count;
296   };
297
298   struct SortDstEdgesFunctor {
299     bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
300       return E1->Dst.Number < E2->Dst.Number;
301     }
302   };
303 public:
304   typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
305
306   GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0),
307     DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {}
308   ~GCOVBlock();
309   const GCOVFunction &getParent() const { return Parent; }
310   void addLine(uint32_t N) { Lines.push_back(N); }
311   uint32_t getLastLine() const { return Lines.back(); }
312   void addCount(size_t DstEdgeNo, uint64_t N);
313   uint64_t getCount() const { return Counter; }
314
315   void addSrcEdge(GCOVEdge *Edge) {
316     assert(&Edge->Dst == this); // up to caller to ensure edge is valid
317     SrcEdges.push_back(Edge);
318   }
319   void addDstEdge(GCOVEdge *Edge) {
320     assert(&Edge->Src == this); // up to caller to ensure edge is valid
321     // Check if adding this edge causes list to become unsorted.
322     if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
323       DstEdgesAreSorted = false;
324     DstEdges.push_back(Edge);
325   }
326   size_t getNumSrcEdges() const { return SrcEdges.size(); }
327   size_t getNumDstEdges() const { return DstEdges.size(); }
328   void sortDstEdges();
329
330   EdgeIterator src_begin() const { return SrcEdges.begin(); }
331   EdgeIterator src_end() const { return SrcEdges.end(); }
332   EdgeIterator dst_begin() const { return DstEdges.begin(); }
333   EdgeIterator dst_end() const { return DstEdges.end(); }
334
335   void dump() const;
336   void collectLineCounts(FileInfo &FI);
337 private:
338   GCOVFunction &Parent;
339   uint32_t Number;
340   uint64_t Counter;
341   bool DstEdgesAreSorted;
342   SmallVector<GCOVEdge *, 16> SrcEdges;
343   SmallVector<GCOVEdge *, 16> DstEdges;
344   SmallVector<uint32_t, 16> Lines;
345 };
346
347 class FileInfo {
348   // It is unlikely--but possible--for multiple functions to be on the same line.
349   // Therefore this typedef allows LineData.Functions to store multiple functions
350   // per instance. This is rare, however, so optimize for the common case.
351   typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
352   typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
353   typedef SmallVector<const GCOVBlock *, 4> BlockVector;
354   typedef DenseMap<uint32_t, BlockVector> BlockLines;
355
356   struct LineData {
357     BlockLines Blocks;
358     FunctionLines Functions;
359   };
360
361   struct GCOVCoverage {
362     GCOVCoverage(StringRef Name) :
363       Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0),
364       BranchesTaken(0) {}
365
366     StringRef Name;
367
368     uint32_t LogicalLines;
369     uint32_t LinesExec;
370
371     uint32_t Branches;
372     uint32_t BranchesExec;
373     uint32_t BranchesTaken;
374   };
375 public:
376   FileInfo(const GCOVOptions &Options) :
377     Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
378
379   void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
380     LineInfo[Filename].Blocks[Line-1].push_back(Block);
381   }
382   void addFunctionLine(StringRef Filename, uint32_t Line,
383                        const GCOVFunction *Function) {
384     LineInfo[Filename].Functions[Line-1].push_back(Function);
385   }
386   void setRunCount(uint32_t Runs) { RunCount = Runs; }
387   void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
388   void print(StringRef GCNOFile, StringRef GCDAFile);
389 private:
390   void printFunctionSummary(raw_fd_ostream &OS,
391                             const FunctionVector &Funcs) const;
392   void printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
393                       uint32_t LineIndex, uint32_t &BlockNo) const;
394   void printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
395                        GCOVCoverage &Coverage, uint32_t &EdgeNo);
396   void printUncondBranchInfo(raw_fd_ostream &OS, uint32_t &EdgeNo,
397                              uint64_t Count) const;
398
399   void printCoverage(const GCOVCoverage &Coverage) const;
400   void printFuncCoverage() const;
401   void printFileCoverage() const;
402
403   const GCOVOptions &Options;
404   StringMap<LineData> LineInfo;
405   uint32_t RunCount;
406   uint32_t ProgramCount;
407
408   typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4>
409       FileCoverageList;
410   typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
411
412   FileCoverageList FileCoverages;
413   FuncCoverageMap FuncCoverages;
414 };
415
416 }
417
418 #endif