• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===//
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_GCOV_H
16 #define LLVM_GCOV_H
17 
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/raw_ostream.h"
22 
23 namespace llvm {
24 
25 class GCOVFunction;
26 class GCOVBlock;
27 class GCOVLines;
28 class FileInfo;
29 
30 enum GCOVFormat {
31   InvalidGCOV,
32   GCNO_402,
33   GCNO_404,
34   GCDA_402,
35   GCDA_404
36 };
37 
38 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
39 /// read operations.
40 class GCOVBuffer {
41 public:
GCOVBuffer(MemoryBuffer * B)42   GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
43 
44   /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
readGCOVFormat()45   enum GCOVFormat readGCOVFormat() {
46     StringRef Magic = Buffer->getBuffer().slice(0, 12);
47     Cursor = 12;
48     if (Magic == "oncg*404MVLL")
49       return GCNO_404;
50     else if (Magic == "oncg*204MVLL")
51       return GCNO_402;
52     else if (Magic == "adcg*404MVLL")
53       return GCDA_404;
54     else if (Magic == "adcg*204MVLL")
55       return GCDA_402;
56 
57     Cursor = 0;
58     return InvalidGCOV;
59   }
60 
61   /// readFunctionTag - If cursor points to a function tag then increment the
62   /// cursor and return true otherwise return false.
readFunctionTag()63   bool readFunctionTag() {
64     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
65     if (Tag.empty() ||
66 	Tag[0] != '\0' || Tag[1] != '\0' ||
67 	Tag[2] != '\0' || Tag[3] != '\1') {
68       return false;
69     }
70     Cursor += 4;
71     return true;
72   }
73 
74   /// readBlockTag - If cursor points to a block tag then increment the
75   /// cursor and return true otherwise return false.
readBlockTag()76   bool readBlockTag() {
77     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
78     if (Tag.empty() ||
79 	Tag[0] != '\0' || Tag[1] != '\0' ||
80 	Tag[2] != '\x41' || Tag[3] != '\x01') {
81       return false;
82     }
83     Cursor += 4;
84     return true;
85   }
86 
87   /// readEdgeTag - If cursor points to an edge tag then increment the
88   /// cursor and return true otherwise return false.
readEdgeTag()89   bool readEdgeTag() {
90     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
91     if (Tag.empty() ||
92 	Tag[0] != '\0' || Tag[1] != '\0' ||
93 	Tag[2] != '\x43' || Tag[3] != '\x01') {
94       return false;
95     }
96     Cursor += 4;
97     return true;
98   }
99 
100   /// readLineTag - If cursor points to a line tag then increment the
101   /// cursor and return true otherwise return false.
readLineTag()102   bool readLineTag() {
103     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
104     if (Tag.empty() ||
105 	Tag[0] != '\0' || Tag[1] != '\0' ||
106 	Tag[2] != '\x45' || Tag[3] != '\x01') {
107       return false;
108     }
109     Cursor += 4;
110     return true;
111   }
112 
113   /// readArcTag - If cursor points to an gcda arc tag then increment the
114   /// cursor and return true otherwise return false.
readArcTag()115   bool readArcTag() {
116     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
117     if (Tag.empty() ||
118 	Tag[0] != '\0' || Tag[1] != '\0' ||
119 	Tag[2] != '\xa1' || Tag[3] != '\1') {
120       return false;
121     }
122     Cursor += 4;
123     return true;
124   }
125 
readInt()126   uint32_t readInt() {
127     uint32_t Result;
128     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
129     assert (Str.empty() == false && "Unexpected memory buffer end!");
130     Cursor += 4;
131     Result = *(uint32_t *)(Str.data());
132     return Result;
133   }
134 
readInt64()135   uint64_t readInt64() {
136     uint64_t Lo = readInt();
137     uint64_t Hi = readInt();
138     uint64_t Result = Lo | (Hi << 32);
139     return Result;
140   }
141 
readString()142   StringRef readString() {
143     uint32_t Len = readInt() * 4;
144     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
145     Cursor += Len;
146     return Str;
147   }
148 
getCursor()149   uint64_t getCursor() const { return Cursor; }
150 private:
151   MemoryBuffer *Buffer;
152   uint64_t Cursor;
153 };
154 
155 /// GCOVFile - Collects coverage information for one pair of coverage file
156 /// (.gcno and .gcda).
157 class GCOVFile {
158 public:
GCOVFile()159   GCOVFile() {}
160   ~GCOVFile();
161   bool read(GCOVBuffer &Buffer);
162   void dump();
163   void collectLineCounts(FileInfo &FI);
164 private:
165   SmallVector<GCOVFunction *, 16> Functions;
166 };
167 
168 /// GCOVFunction - Collects function information.
169 class GCOVFunction {
170 public:
GCOVFunction()171   GCOVFunction() : Ident(0), LineNumber(0) {}
172   ~GCOVFunction();
173   bool read(GCOVBuffer &Buffer, GCOVFormat Format);
174   void dump();
175   void collectLineCounts(FileInfo &FI);
176 private:
177   uint32_t Ident;
178   uint32_t LineNumber;
179   StringRef Name;
180   StringRef Filename;
181   SmallVector<GCOVBlock *, 16> Blocks;
182 };
183 
184 /// GCOVBlock - Collects block information.
185 class GCOVBlock {
186 public:
GCOVBlock(uint32_t N)187   GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
188   ~GCOVBlock();
addEdge(uint32_t N)189   void addEdge(uint32_t N) { Edges.push_back(N); }
190   void addLine(StringRef Filename, uint32_t LineNo);
addCount(uint64_t N)191   void addCount(uint64_t N) { Counter = N; }
192   void dump();
193   void collectLineCounts(FileInfo &FI);
194 private:
195   uint32_t Number;
196   uint64_t Counter;
197   SmallVector<uint32_t, 16> Edges;
198   StringMap<GCOVLines *> Lines;
199 };
200 
201 /// GCOVLines - A wrapper around a vector of int to keep track of line nos.
202 class GCOVLines {
203 public:
~GCOVLines()204   ~GCOVLines() { Lines.clear(); }
add(uint32_t N)205   void add(uint32_t N) { Lines.push_back(N); }
206   void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count);
207   void dump();
208 
209 private:
210   SmallVector<uint32_t, 4> Lines;
211 };
212 
213 typedef SmallVector<uint32_t, 16> LineCounts;
214 class FileInfo {
215 public:
216   void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
217   void print();
218 private:
219   StringMap<LineCounts> LineInfo;
220 };
221 
222 }
223 
224 #endif
225