Revert r240137 (Fixed/added namespace ending comments using clang-tidy. NFC)
[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/ADT/iterator.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 namespace llvm {
27
28 class GCOVFunction;
29 class GCOVBlock;
30 class FileInfo;
31
32 namespace GCOV {
33 enum GCOVVersion { V402, V404 };
34 } // end GCOV namespace
35
36 /// GCOVOptions - A struct for passing gcov options between functions.
37 struct GCOVOptions {
38   GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
39       : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
40         PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {}
41
42   bool AllBlocks;
43   bool BranchInfo;
44   bool BranchCount;
45   bool FuncCoverage;
46   bool PreservePaths;
47   bool UncondBranch;
48   bool LongFileNames;
49   bool NoOutput;
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() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
102         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() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
114         Tag[3] != '\x01') {
115       return false;
116     }
117     Cursor += 4;
118     return true;
119   }
120
121   /// readEdgeTag - If cursor points to an edge tag then increment the
122   /// cursor and return true otherwise return false.
123   bool readEdgeTag() {
124     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
125     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
126         Tag[3] != '\x01') {
127       return false;
128     }
129     Cursor += 4;
130     return true;
131   }
132
133   /// readLineTag - If cursor points to a line tag then increment the
134   /// cursor and return true otherwise return false.
135   bool readLineTag() {
136     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
137     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
138         Tag[3] != '\x01') {
139       return false;
140     }
141     Cursor += 4;
142     return true;
143   }
144
145   /// readArcTag - If cursor points to an gcda arc tag then increment the
146   /// cursor and return true otherwise return false.
147   bool readArcTag() {
148     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
149     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
150         Tag[3] != '\1') {
151       return false;
152     }
153     Cursor += 4;
154     return true;
155   }
156
157   /// readObjectTag - If cursor points to an object summary tag then increment
158   /// the cursor and return true otherwise return false.
159   bool readObjectTag() {
160     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
161     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
162         Tag[3] != '\xa1') {
163       return false;
164     }
165     Cursor += 4;
166     return true;
167   }
168
169   /// readProgramTag - If cursor points to a program summary tag then increment
170   /// the cursor and return true otherwise return false.
171   bool readProgramTag() {
172     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
173     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
174         Tag[3] != '\xa3') {
175       return false;
176     }
177     Cursor += 4;
178     return true;
179   }
180
181   bool readInt(uint32_t &Val) {
182     if (Buffer->getBuffer().size() < Cursor + 4) {
183       errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
184       return false;
185     }
186     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
187     Cursor += 4;
188     Val = *(const uint32_t *)(Str.data());
189     return true;
190   }
191
192   bool readInt64(uint64_t &Val) {
193     uint32_t Lo, Hi;
194     if (!readInt(Lo) || !readInt(Hi))
195       return false;
196     Val = ((uint64_t)Hi << 32) | Lo;
197     return true;
198   }
199
200   bool readString(StringRef &Str) {
201     uint32_t Len = 0;
202     // Keep reading until we find a non-zero length. This emulates gcov's
203     // behaviour, which appears to do the same.
204     while (Len == 0)
205       if (!readInt(Len))
206         return false;
207     Len *= 4;
208     if (Buffer->getBuffer().size() < Cursor + Len) {
209       errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
210       return false;
211     }
212     Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
213     Cursor += Len;
214     return true;
215   }
216
217   uint64_t getCursor() const { return Cursor; }
218   void advanceCursor(uint32_t n) { Cursor += n * 4; }
219
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()
230       : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
231         ProgramCount(0) {}
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
238 private:
239   bool GCNOInitialized;
240   GCOV::GCOVVersion Version;
241   uint32_t Checksum;
242   SmallVector<std::unique_ptr<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 pointee_iterator<SmallVectorImpl<
260       std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator;
261
262   GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
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   iterator_range<BlockIterator> blocks() const {
274     return make_range(block_begin(), block_end());
275   }
276
277   void dump() const;
278   void collectLineCounts(FileInfo &FI);
279
280 private:
281   GCOVFile &Parent;
282   uint32_t Ident;
283   uint32_t Checksum;
284   uint32_t LineNumber;
285   StringRef Name;
286   StringRef Filename;
287   SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks;
288   SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges;
289 };
290
291 /// GCOVBlock - Collects block information.
292 class GCOVBlock {
293   struct EdgeWeight {
294     EdgeWeight(GCOVBlock *D) : Dst(D), Count(0) {}
295
296     GCOVBlock *Dst;
297     uint64_t Count;
298   };
299
300   struct SortDstEdgesFunctor {
301     bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
302       return E1->Dst.Number < E2->Dst.Number;
303     }
304   };
305
306 public:
307   typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
308
309   GCOVBlock(GCOVFunction &P, uint32_t N)
310       : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(),
311         DstEdges(), Lines() {}
312   ~GCOVBlock();
313   const GCOVFunction &getParent() const { return Parent; }
314   void addLine(uint32_t N) { Lines.push_back(N); }
315   uint32_t getLastLine() const { return Lines.back(); }
316   void addCount(size_t DstEdgeNo, uint64_t N);
317   uint64_t getCount() const { return Counter; }
318
319   void addSrcEdge(GCOVEdge *Edge) {
320     assert(&Edge->Dst == this); // up to caller to ensure edge is valid
321     SrcEdges.push_back(Edge);
322   }
323   void addDstEdge(GCOVEdge *Edge) {
324     assert(&Edge->Src == this); // up to caller to ensure edge is valid
325     // Check if adding this edge causes list to become unsorted.
326     if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
327       DstEdgesAreSorted = false;
328     DstEdges.push_back(Edge);
329   }
330   size_t getNumSrcEdges() const { return SrcEdges.size(); }
331   size_t getNumDstEdges() const { return DstEdges.size(); }
332   void sortDstEdges();
333
334   EdgeIterator src_begin() const { return SrcEdges.begin(); }
335   EdgeIterator src_end() const { return SrcEdges.end(); }
336   iterator_range<EdgeIterator> srcs() const {
337     return make_range(src_begin(), src_end());
338   }
339
340   EdgeIterator dst_begin() const { return DstEdges.begin(); }
341   EdgeIterator dst_end() const { return DstEdges.end(); }
342   iterator_range<EdgeIterator> dsts() const {
343     return make_range(dst_begin(), dst_end());
344   }
345
346   void dump() const;
347   void collectLineCounts(FileInfo &FI);
348
349 private:
350   GCOVFunction &Parent;
351   uint32_t Number;
352   uint64_t Counter;
353   bool DstEdgesAreSorted;
354   SmallVector<GCOVEdge *, 16> SrcEdges;
355   SmallVector<GCOVEdge *, 16> DstEdges;
356   SmallVector<uint32_t, 16> Lines;
357 };
358
359 class FileInfo {
360   // It is unlikely--but possible--for multiple functions to be on the same
361   // line.
362   // Therefore this typedef allows LineData.Functions to store multiple
363   // functions
364   // per instance. This is rare, however, so optimize for the common case.
365   typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
366   typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
367   typedef SmallVector<const GCOVBlock *, 4> BlockVector;
368   typedef DenseMap<uint32_t, BlockVector> BlockLines;
369
370   struct LineData {
371     LineData() : LastLine(0) {}
372     BlockLines Blocks;
373     FunctionLines Functions;
374     uint32_t LastLine;
375   };
376
377   struct GCOVCoverage {
378     GCOVCoverage(StringRef Name)
379         : Name(Name), LogicalLines(0), LinesExec(0), Branches(0),
380           BranchesExec(0), BranchesTaken(0) {}
381
382     StringRef Name;
383
384     uint32_t LogicalLines;
385     uint32_t LinesExec;
386
387     uint32_t Branches;
388     uint32_t BranchesExec;
389     uint32_t BranchesTaken;
390   };
391
392 public:
393   FileInfo(const GCOVOptions &Options)
394       : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
395
396   void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
397     if (Line > LineInfo[Filename].LastLine)
398       LineInfo[Filename].LastLine = Line;
399     LineInfo[Filename].Blocks[Line - 1].push_back(Block);
400   }
401   void addFunctionLine(StringRef Filename, uint32_t Line,
402                        const GCOVFunction *Function) {
403     if (Line > LineInfo[Filename].LastLine)
404       LineInfo[Filename].LastLine = Line;
405     LineInfo[Filename].Functions[Line - 1].push_back(Function);
406   }
407   void setRunCount(uint32_t Runs) { RunCount = Runs; }
408   void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
409   void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
410              StringRef GCDAFile);
411
412 private:
413   std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
414   std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
415   void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
416   void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
417                       uint32_t LineIndex, uint32_t &BlockNo) const;
418   void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
419                        GCOVCoverage &Coverage, uint32_t &EdgeNo);
420   void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
421                              uint64_t Count) const;
422
423   void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
424   void printFuncCoverage(raw_ostream &OS) const;
425   void printFileCoverage(raw_ostream &OS) const;
426
427   const GCOVOptions &Options;
428   StringMap<LineData> LineInfo;
429   uint32_t RunCount;
430   uint32_t ProgramCount;
431
432   typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList;
433   typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
434
435   FileCoverageList FileCoverages;
436   FuncCoverageMap FuncCoverages;
437 };
438 }
439
440 #endif