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