llvm-cov: clang-format the GCOV files (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/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 { V402, V404 };
33 } // end GCOV namespace
34
35 /// GCOVOptions - A struct for passing gcov options between functions.
36 struct GCOVOptions {
37   GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
38       : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
39         PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {}
40
41   bool AllBlocks;
42   bool BranchInfo;
43   bool BranchCount;
44   bool FuncCoverage;
45   bool PreservePaths;
46   bool UncondBranch;
47   bool LongFileNames;
48   bool NoOutput;
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() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
101         Tag[3] != '\1') {
102       return false;
103     }
104     Cursor += 4;
105     return true;
106   }
107
108   /// readBlockTag - If cursor points to a block tag then increment the
109   /// cursor and return true otherwise return false.
110   bool readBlockTag() {
111     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
112     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
113         Tag[3] != '\x01') {
114       return false;
115     }
116     Cursor += 4;
117     return true;
118   }
119
120   /// readEdgeTag - If cursor points to an edge tag then increment the
121   /// cursor and return true otherwise return false.
122   bool readEdgeTag() {
123     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
124     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
125         Tag[3] != '\x01') {
126       return false;
127     }
128     Cursor += 4;
129     return true;
130   }
131
132   /// readLineTag - If cursor points to a line tag then increment the
133   /// cursor and return true otherwise return false.
134   bool readLineTag() {
135     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
136     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
137         Tag[3] != '\x01') {
138       return false;
139     }
140     Cursor += 4;
141     return true;
142   }
143
144   /// readArcTag - If cursor points to an gcda arc tag then increment the
145   /// cursor and return true otherwise return false.
146   bool readArcTag() {
147     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
148     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
149         Tag[3] != '\1') {
150       return false;
151     }
152     Cursor += 4;
153     return true;
154   }
155
156   /// readObjectTag - If cursor points to an object summary tag then increment
157   /// the cursor and return true otherwise return false.
158   bool readObjectTag() {
159     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
160     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
161         Tag[3] != '\xa1') {
162       return false;
163     }
164     Cursor += 4;
165     return true;
166   }
167
168   /// readProgramTag - If cursor points to a program summary tag then increment
169   /// the cursor and return true otherwise return false.
170   bool readProgramTag() {
171     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
172     if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
173         Tag[3] != '\xa3') {
174       return false;
175     }
176     Cursor += 4;
177     return true;
178   }
179
180   bool readInt(uint32_t &Val) {
181     if (Buffer->getBuffer().size() < Cursor + 4) {
182       errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
183       return false;
184     }
185     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
186     Cursor += 4;
187     Val = *(const uint32_t *)(Str.data());
188     return true;
189   }
190
191   bool readInt64(uint64_t &Val) {
192     uint32_t Lo, Hi;
193     if (!readInt(Lo) || !readInt(Hi))
194       return false;
195     Val = ((uint64_t)Hi << 32) | Lo;
196     return true;
197   }
198
199   bool readString(StringRef &Str) {
200     uint32_t Len = 0;
201     // Keep reading until we find a non-zero length. This emulates gcov's
202     // behaviour, which appears to do the same.
203     while (Len == 0)
204       if (!readInt(Len))
205         return false;
206     Len *= 4;
207     if (Buffer->getBuffer().size() < Cursor + Len) {
208       errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
209       return false;
210     }
211     Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
212     Cursor += Len;
213     return true;
214   }
215
216   uint64_t getCursor() const { return Cursor; }
217   void advanceCursor(uint32_t n) { Cursor += n * 4; }
218
219 private:
220   MemoryBuffer *Buffer;
221   uint64_t Cursor;
222 };
223
224 /// GCOVFile - Collects coverage information for one pair of coverage file
225 /// (.gcno and .gcda).
226 class GCOVFile {
227 public:
228   GCOVFile()
229       : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
230         ProgramCount(0) {}
231   bool readGCNO(GCOVBuffer &Buffer);
232   bool readGCDA(GCOVBuffer &Buffer);
233   uint32_t getChecksum() const { return Checksum; }
234   void dump() const;
235   void collectLineCounts(FileInfo &FI);
236
237 private:
238   bool GCNOInitialized;
239   GCOV::GCOVVersion Version;
240   uint32_t Checksum;
241   SmallVector<std::unique_ptr<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<std::unique_ptr<GCOVBlock>>::const_iterator
259       BlockIterator;
260
261   GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
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
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<std::unique_ptr<GCOVBlock>, 16> Blocks;
284   SmallVector<std::unique_ptr<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
302 public:
303   typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
304
305   GCOVBlock(GCOVFunction &P, uint32_t N)
306       : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(),
307         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
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
350   // line.
351   // Therefore this typedef allows LineData.Functions to store multiple
352   // functions
353   // per instance. This is rare, however, so optimize for the common case.
354   typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
355   typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
356   typedef SmallVector<const GCOVBlock *, 4> BlockVector;
357   typedef DenseMap<uint32_t, BlockVector> BlockLines;
358
359   struct LineData {
360     LineData() : LastLine(0) {}
361     BlockLines Blocks;
362     FunctionLines Functions;
363     uint32_t LastLine;
364   };
365
366   struct GCOVCoverage {
367     GCOVCoverage(StringRef Name)
368         : Name(Name), LogicalLines(0), LinesExec(0), Branches(0),
369           BranchesExec(0), BranchesTaken(0) {}
370
371     StringRef Name;
372
373     uint32_t LogicalLines;
374     uint32_t LinesExec;
375
376     uint32_t Branches;
377     uint32_t BranchesExec;
378     uint32_t BranchesTaken;
379   };
380
381 public:
382   FileInfo(const GCOVOptions &Options)
383       : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
384
385   void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
386     if (Line > LineInfo[Filename].LastLine)
387       LineInfo[Filename].LastLine = Line;
388     LineInfo[Filename].Blocks[Line - 1].push_back(Block);
389   }
390   void addFunctionLine(StringRef Filename, uint32_t Line,
391                        const GCOVFunction *Function) {
392     if (Line > LineInfo[Filename].LastLine)
393       LineInfo[Filename].LastLine = Line;
394     LineInfo[Filename].Functions[Line - 1].push_back(Function);
395   }
396   void setRunCount(uint32_t Runs) { RunCount = Runs; }
397   void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
398   void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile);
399
400 private:
401   std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
402   std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
403   void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
404   void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
405                       uint32_t LineIndex, uint32_t &BlockNo) const;
406   void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
407                        GCOVCoverage &Coverage, uint32_t &EdgeNo);
408   void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
409                              uint64_t Count) const;
410
411   void printCoverage(const GCOVCoverage &Coverage) const;
412   void printFuncCoverage() const;
413   void printFileCoverage() const;
414
415   const GCOVOptions &Options;
416   StringMap<LineData> LineInfo;
417   uint32_t RunCount;
418   uint32_t ProgramCount;
419
420   typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList;
421   typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
422
423   FileCoverageList FileCoverages;
424   FuncCoverageMap FuncCoverages;
425 };
426 }
427
428 #endif