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