1 //===- GCOV.h - LLVM coverage tool ----------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This header provides the interface to read and write coverage files that
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_SUPPORT_GCOV_H
16 #define LLVM_SUPPORT_GCOV_H
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/raw_ostream.h"
35 } // end GCOV namespace
37 /// GCOVOptions - A struct for passing gcov options between functions.
39 GCOVOptions(bool A): AllBlocks(A) {}
44 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
48 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
50 /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
51 bool readGCNOFormat() {
52 StringRef File = Buffer->getBuffer().slice(0, 4);
54 errs() << "Unexpected file type: " << File << ".\n";
61 /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
62 bool readGCDAFormat() {
63 StringRef File = Buffer->getBuffer().slice(0, 4);
65 errs() << "Unexpected file type: " << File << ".\n";
72 /// readGCOVVersion - Read GCOV version.
73 bool readGCOVVersion(GCOV::GCOVVersion &Version) {
74 StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4);
75 if (VersionStr == "*204") {
80 if (VersionStr == "*404") {
85 errs() << "Unexpected version: " << VersionStr << ".\n";
89 /// readFunctionTag - If cursor points to a function tag then increment the
90 /// cursor and return true otherwise return false.
91 bool readFunctionTag() {
92 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
94 Tag[0] != '\0' || Tag[1] != '\0' ||
95 Tag[2] != '\0' || Tag[3] != '\1') {
102 /// readBlockTag - If cursor points to a block tag then increment the
103 /// cursor and return true otherwise return false.
104 bool readBlockTag() {
105 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
107 Tag[0] != '\0' || Tag[1] != '\0' ||
108 Tag[2] != '\x41' || Tag[3] != '\x01') {
115 /// readEdgeTag - If cursor points to an edge tag then increment the
116 /// cursor and return true otherwise return false.
118 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
120 Tag[0] != '\0' || Tag[1] != '\0' ||
121 Tag[2] != '\x43' || Tag[3] != '\x01') {
128 /// readLineTag - If cursor points to a line tag then increment the
129 /// cursor and return true otherwise return false.
131 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
133 Tag[0] != '\0' || Tag[1] != '\0' ||
134 Tag[2] != '\x45' || Tag[3] != '\x01') {
141 /// readArcTag - If cursor points to an gcda arc tag then increment the
142 /// cursor and return true otherwise return false.
144 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
146 Tag[0] != '\0' || Tag[1] != '\0' ||
147 Tag[2] != '\xa1' || Tag[3] != '\1') {
154 /// readObjectTag - If cursor points to an object summary tag then increment
155 /// the cursor and return true otherwise return false.
156 bool readObjectTag() {
157 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
159 Tag[0] != '\0' || Tag[1] != '\0' ||
160 Tag[2] != '\0' || Tag[3] != '\xa1') {
167 /// readProgramTag - If cursor points to a program summary tag then increment
168 /// the cursor and return true otherwise return false.
169 bool readProgramTag() {
170 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
172 Tag[0] != '\0' || Tag[1] != '\0' ||
173 Tag[2] != '\0' || Tag[3] != '\xa3') {
180 bool readInt(uint32_t &Val) {
181 if (Buffer->getBuffer().size() < Cursor+4) {
182 errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
185 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
187 Val = *(const uint32_t *)(Str.data());
191 bool readInt64(uint64_t &Val) {
193 if (!readInt(Lo) || !readInt(Hi)) return false;
194 Val = ((uint64_t)Hi << 32) | Lo;
198 bool readString(StringRef &Str) {
200 if (!readInt(Len)) return false;
202 if (Buffer->getBuffer().size() < Cursor+Len) {
203 errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
206 Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
211 uint64_t getCursor() const { return Cursor; }
212 void advanceCursor(uint32_t n) { Cursor += n*4; }
214 MemoryBuffer *Buffer;
218 /// GCOVFile - Collects coverage information for one pair of coverage file
219 /// (.gcno and .gcda).
222 GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
225 bool readGCNO(GCOVBuffer &Buffer);
226 bool readGCDA(GCOVBuffer &Buffer);
227 uint32_t getChecksum() const { return Checksum; }
229 void collectLineCounts(FileInfo &FI);
231 bool GCNOInitialized;
232 GCOV::GCOVVersion Version;
234 SmallVector<GCOVFunction *, 16> Functions;
236 uint32_t ProgramCount;
240 GCOVEdge(GCOVBlock *S, GCOVBlock *D): Src(S), Dst(D), Count(0) {}
247 /// GCOVFunction - Collects function information.
250 GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
252 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
253 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
254 StringRef getFilename() const { return Filename; }
255 size_t getNumBlocks() const { return Blocks.size(); }
257 void collectLineCounts(FileInfo &FI);
265 SmallVector<GCOVBlock *, 16> Blocks;
266 SmallVector<GCOVEdge *, 16> Edges;
269 /// GCOVBlock - Collects block information.
272 typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
274 GCOVBlock(GCOVFunction &P, uint32_t N) :
275 Parent(P), Number(N), Counter(0), SrcEdges(), DstEdges(), Lines() {}
277 void addSrcEdge(GCOVEdge *Edge) {
278 assert(Edge->Dst == this); // up to caller to ensure edge is valid
279 SrcEdges.push_back(Edge);
281 void addDstEdge(GCOVEdge *Edge) {
282 assert(Edge->Src == this); // up to caller to ensure edge is valid
283 DstEdges.push_back(Edge);
285 void addLine(uint32_t N) { Lines.push_back(N); }
286 uint32_t getLastLine() const { return Lines.back(); }
287 void addCount(size_t DstEdgeNo, uint64_t N);
288 uint64_t getCount() const { return Counter; }
289 size_t getNumSrcEdges() const { return SrcEdges.size(); }
290 size_t getNumDstEdges() const { return DstEdges.size(); }
292 EdgeIterator src_begin() const { return SrcEdges.begin(); }
293 EdgeIterator src_end() const { return SrcEdges.end(); }
294 EdgeIterator dst_begin() const { return DstEdges.begin(); }
295 EdgeIterator dst_end() const { return DstEdges.end(); }
298 void collectLineCounts(FileInfo &FI);
300 GCOVFunction &Parent;
303 SmallVector<GCOVEdge *, 16> SrcEdges;
304 SmallVector<GCOVEdge *, 16> DstEdges;
305 SmallVector<uint32_t, 16> Lines;
308 typedef SmallVector<const GCOVBlock *, 4> BlockVector;
309 typedef DenseMap<uint32_t, BlockVector> LineData;
312 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
313 LineInfo[Filename][Line-1].push_back(Block);
315 void setRunCount(uint32_t Runs) { RunCount = Runs; }
316 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
317 void print(StringRef GCNOFile, StringRef GCDAFile,
318 const GCOVOptions &Options) const;
320 StringMap<LineData> LineInfo;
322 uint32_t ProgramCount;