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, bool B, bool C, bool U) :
40 AllBlocks(A), BranchInfo(B), BranchCount(C), UncondBranch(U) {}
48 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
52 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
54 /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
55 bool readGCNOFormat() {
56 StringRef File = Buffer->getBuffer().slice(0, 4);
58 errs() << "Unexpected file type: " << File << ".\n";
65 /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
66 bool readGCDAFormat() {
67 StringRef File = Buffer->getBuffer().slice(0, 4);
69 errs() << "Unexpected file type: " << File << ".\n";
76 /// readGCOVVersion - Read GCOV version.
77 bool readGCOVVersion(GCOV::GCOVVersion &Version) {
78 StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4);
79 if (VersionStr == "*204") {
84 if (VersionStr == "*404") {
89 errs() << "Unexpected version: " << VersionStr << ".\n";
93 /// readFunctionTag - If cursor points to a function tag then increment the
94 /// cursor and return true otherwise return false.
95 bool readFunctionTag() {
96 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
98 Tag[0] != '\0' || Tag[1] != '\0' ||
99 Tag[2] != '\0' || Tag[3] != '\1') {
106 /// readBlockTag - If cursor points to a block tag then increment the
107 /// cursor and return true otherwise return false.
108 bool readBlockTag() {
109 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
111 Tag[0] != '\0' || Tag[1] != '\0' ||
112 Tag[2] != '\x41' || Tag[3] != '\x01') {
119 /// readEdgeTag - If cursor points to an edge tag then increment the
120 /// cursor and return true otherwise return false.
122 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
124 Tag[0] != '\0' || Tag[1] != '\0' ||
125 Tag[2] != '\x43' || Tag[3] != '\x01') {
132 /// readLineTag - If cursor points to a line tag then increment the
133 /// cursor and return true otherwise return false.
135 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
137 Tag[0] != '\0' || Tag[1] != '\0' ||
138 Tag[2] != '\x45' || Tag[3] != '\x01') {
145 /// readArcTag - If cursor points to an gcda arc tag then increment the
146 /// cursor and return true otherwise return false.
148 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
150 Tag[0] != '\0' || Tag[1] != '\0' ||
151 Tag[2] != '\xa1' || Tag[3] != '\1') {
158 /// readObjectTag - If cursor points to an object summary tag then increment
159 /// the cursor and return true otherwise return false.
160 bool readObjectTag() {
161 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
163 Tag[0] != '\0' || Tag[1] != '\0' ||
164 Tag[2] != '\0' || Tag[3] != '\xa1') {
171 /// readProgramTag - If cursor points to a program summary tag then increment
172 /// the cursor and return true otherwise return false.
173 bool readProgramTag() {
174 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
176 Tag[0] != '\0' || Tag[1] != '\0' ||
177 Tag[2] != '\0' || Tag[3] != '\xa3') {
184 bool readInt(uint32_t &Val) {
185 if (Buffer->getBuffer().size() < Cursor+4) {
186 errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
189 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
191 Val = *(const uint32_t *)(Str.data());
195 bool readInt64(uint64_t &Val) {
197 if (!readInt(Lo) || !readInt(Hi)) return false;
198 Val = ((uint64_t)Hi << 32) | Lo;
202 bool readString(StringRef &Str) {
204 if (!readInt(Len)) return false;
206 if (Buffer->getBuffer().size() < Cursor+Len) {
207 errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
210 Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
215 uint64_t getCursor() const { return Cursor; }
216 void advanceCursor(uint32_t n) { Cursor += n*4; }
218 MemoryBuffer *Buffer;
222 /// GCOVFile - Collects coverage information for one pair of coverage file
223 /// (.gcno and .gcda).
226 GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
229 bool readGCNO(GCOVBuffer &Buffer);
230 bool readGCDA(GCOVBuffer &Buffer);
231 uint32_t getChecksum() const { return Checksum; }
233 void collectLineCounts(FileInfo &FI);
235 bool GCNOInitialized;
236 GCOV::GCOVVersion Version;
238 SmallVector<GCOVFunction *, 16> Functions;
240 uint32_t ProgramCount;
243 /// GCOVEdge - Collects edge information.
245 GCOVEdge(GCOVBlock *S, GCOVBlock *D): Src(S), Dst(D), Count(0) {}
252 /// GCOVFunction - Collects function information.
255 typedef SmallVectorImpl<GCOVBlock *>::const_iterator BlockIterator;
257 GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
259 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
260 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
261 StringRef getName() const { return Name; }
262 StringRef getFilename() const { return Filename; }
263 size_t getNumBlocks() const { return Blocks.size(); }
264 uint64_t getEntryCount() const;
265 uint64_t getExitCount() const;
267 BlockIterator block_begin() const { return Blocks.begin(); }
268 BlockIterator block_end() const { return Blocks.end(); }
271 void collectLineCounts(FileInfo &FI);
279 SmallVector<GCOVBlock *, 16> Blocks;
280 SmallVector<GCOVEdge *, 16> Edges;
283 /// GCOVBlock - Collects block information.
286 EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {}
292 struct SortDstEdgesFunctor {
293 bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
294 return E1->Dst->Number < E2->Dst->Number;
298 typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
300 GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0),
301 DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {}
303 void addLine(uint32_t N) { Lines.push_back(N); }
304 uint32_t getLastLine() const { return Lines.back(); }
305 void addCount(size_t DstEdgeNo, uint64_t N);
306 uint64_t getCount() const { return Counter; }
308 void addSrcEdge(GCOVEdge *Edge) {
309 assert(Edge->Dst == this); // up to caller to ensure edge is valid
310 SrcEdges.push_back(Edge);
312 void addDstEdge(GCOVEdge *Edge) {
313 assert(Edge->Src == this); // up to caller to ensure edge is valid
314 // Check if adding this edge causes list to become unsorted.
315 if (DstEdges.size() && DstEdges.back()->Dst->Number > Edge->Dst->Number)
316 DstEdgesAreSorted = false;
317 DstEdges.push_back(Edge);
319 size_t getNumSrcEdges() const { return SrcEdges.size(); }
320 size_t getNumDstEdges() const { return DstEdges.size(); }
323 EdgeIterator src_begin() const { return SrcEdges.begin(); }
324 EdgeIterator src_end() const { return SrcEdges.end(); }
325 EdgeIterator dst_begin() const { return DstEdges.begin(); }
326 EdgeIterator dst_end() const { return DstEdges.end(); }
329 void collectLineCounts(FileInfo &FI);
331 GCOVFunction &Parent;
334 bool DstEdgesAreSorted;
335 SmallVector<GCOVEdge *, 16> SrcEdges;
336 SmallVector<GCOVEdge *, 16> DstEdges;
337 SmallVector<uint32_t, 16> Lines;
341 // It is unlikely--but possible--for multiple functions to be on the same line.
342 // Therefore this typedef allows LineData.Functions to store multiple functions
343 // per instance. This is rare, however, so optimize for the common case.
344 typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
345 typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
346 typedef SmallVector<const GCOVBlock *, 4> BlockVector;
347 typedef DenseMap<uint32_t, BlockVector> BlockLines;
351 FunctionLines Functions;
354 struct GCOVCoverage {
356 LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0),
359 uint32_t LogicalLines;
363 uint32_t BranchesExec;
364 uint32_t BranchesTaken;
367 FileInfo(const GCOVOptions &Options) :
368 Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
370 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
371 LineInfo[Filename].Blocks[Line-1].push_back(Block);
373 void addFunctionLine(StringRef Filename, uint32_t Line,
374 const GCOVFunction *Function) {
375 LineInfo[Filename].Functions[Line-1].push_back(Function);
377 void setRunCount(uint32_t Runs) { RunCount = Runs; }
378 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
379 void print(StringRef GCNOFile, StringRef GCDAFile) const;
381 void printFunctionSummary(raw_fd_ostream &OS,
382 const FunctionVector &Funcs) const;
383 void printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
384 uint32_t LineIndex, uint32_t &BlockNo) const;
385 void printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
386 GCOVCoverage &Coverage, uint32_t &EdgeNo) const;
387 void printUncondBranchInfo(raw_fd_ostream &OS, uint32_t &EdgeNo,
388 uint64_t Count) const;
389 void printFileCoverage(StringRef Filename, GCOVCoverage &Coverage) const;
391 const GCOVOptions &Options;
392 StringMap<LineData> LineInfo;
394 uint32_t ProgramCount;