1 //===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===//
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"
38 } // end GCOV namespace
40 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
44 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
46 /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
47 GCOV::GCOVFormat readGCOVFormat() {
48 StringRef Magic = Buffer->getBuffer().slice(0, 8);
50 if (Magic == "oncg*404")
51 return GCOV::GCNO_404;
52 else if (Magic == "oncg*204")
53 return GCOV::GCNO_402;
54 else if (Magic == "adcg*404")
55 return GCOV::GCDA_404;
56 else if (Magic == "adcg*204")
57 return GCOV::GCDA_402;
60 return GCOV::InvalidGCOV;
63 /// readFunctionTag - If cursor points to a function tag then increment the
64 /// cursor and return true otherwise return false.
65 bool readFunctionTag() {
66 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
68 Tag[0] != '\0' || Tag[1] != '\0' ||
69 Tag[2] != '\0' || Tag[3] != '\1') {
76 /// readBlockTag - If cursor points to a block tag then increment the
77 /// cursor and return true otherwise return false.
79 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
81 Tag[0] != '\0' || Tag[1] != '\0' ||
82 Tag[2] != '\x41' || Tag[3] != '\x01') {
89 /// readEdgeTag - If cursor points to an edge tag then increment the
90 /// cursor and return true otherwise return false.
92 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
94 Tag[0] != '\0' || Tag[1] != '\0' ||
95 Tag[2] != '\x43' || Tag[3] != '\x01') {
102 /// readLineTag - If cursor points to a line tag then increment the
103 /// cursor and return true otherwise return false.
105 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
107 Tag[0] != '\0' || Tag[1] != '\0' ||
108 Tag[2] != '\x45' || Tag[3] != '\x01') {
115 /// readArcTag - If cursor points to an gcda arc 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] != '\xa1' || Tag[3] != '\1') {
128 /// readObjectTag - If cursor points to an object summary tag then increment
129 /// the cursor and return true otherwise return false.
130 bool readObjectTag() {
131 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
133 Tag[0] != '\0' || Tag[1] != '\0' ||
134 Tag[2] != '\0' || Tag[3] != '\xa1') {
141 /// readProgramTag - If cursor points to a program summary tag then increment
142 /// the cursor and return true otherwise return false.
143 bool readProgramTag() {
144 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
146 Tag[0] != '\0' || Tag[1] != '\0' ||
147 Tag[2] != '\0' || Tag[3] != '\xa3') {
154 bool readInt(uint32_t &Val) {
155 if (Buffer->getBuffer().size() < Cursor+4) {
156 errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
159 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
161 Val = *(const uint32_t *)(Str.data());
165 bool readInt64(uint64_t &Val) {
167 if (!readInt(Lo) || !readInt(Hi)) return false;
168 Val = ((uint64_t)Hi << 32) | Lo;
172 bool readString(StringRef &Str) {
174 if (!readInt(Len)) return false;
176 if (Buffer->getBuffer().size() < Cursor+Len) {
177 errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
180 Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
185 uint64_t getCursor() const { return Cursor; }
186 void advanceCursor(uint32_t n) { Cursor += n*4; }
188 MemoryBuffer *Buffer;
192 /// GCOVFile - Collects coverage information for one pair of coverage file
193 /// (.gcno and .gcda).
196 GCOVFile() : Checksum(0), Functions(), RunCount(0), ProgramCount(0) {}
198 bool read(GCOVBuffer &Buffer);
200 void collectLineCounts(FileInfo &FI);
203 SmallVector<GCOVFunction *, 16> Functions;
205 uint32_t ProgramCount;
209 GCOVEdge(GCOVBlock *S, GCOVBlock *D): Src(S), Dst(D), Count(0) {}
216 /// GCOVFunction - Collects function information.
219 GCOVFunction() : Ident(0), LineNumber(0) {}
221 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVFormat Format);
222 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVFormat Format);
223 StringRef getFilename() const { return Filename; }
225 void collectLineCounts(FileInfo &FI);
231 SmallVector<GCOVBlock *, 16> Blocks;
232 SmallVector<GCOVEdge *, 16> Edges;
235 /// GCOVBlock - Collects block information.
238 typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
240 GCOVBlock(GCOVFunction &P, uint32_t N) :
241 Parent(P), Number(N), Counter(0), SrcEdges(), DstEdges(), Lines() {}
243 void addSrcEdge(GCOVEdge *Edge) {
244 assert(Edge->Dst == this); // up to caller to ensure edge is valid
245 SrcEdges.push_back(Edge);
247 void addDstEdge(GCOVEdge *Edge) {
248 assert(Edge->Src == this); // up to caller to ensure edge is valid
249 DstEdges.push_back(Edge);
251 void addLine(uint32_t N) { Lines.push_back(N); }
252 void addCount(size_t DstEdgeNo, uint64_t N);
253 uint64_t getCount() const { return Counter; }
254 size_t getNumSrcEdges() const { return SrcEdges.size(); }
255 size_t getNumDstEdges() const { return DstEdges.size(); }
257 EdgeIterator src_begin() const { return SrcEdges.begin(); }
258 EdgeIterator src_end() const { return SrcEdges.end(); }
259 EdgeIterator dst_begin() const { return DstEdges.begin(); }
260 EdgeIterator dst_end() const { return DstEdges.end(); }
263 void collectLineCounts(FileInfo &FI);
265 GCOVFunction &Parent;
268 SmallVector<GCOVEdge *, 16> SrcEdges;
269 SmallVector<GCOVEdge *, 16> DstEdges;
270 SmallVector<uint32_t, 16> Lines;
273 typedef SmallVector<const GCOVBlock *, 4> BlockVector;
274 typedef DenseMap<uint32_t, BlockVector> LineData;
277 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
278 LineInfo[Filename][Line-1].push_back(Block);
280 void setRunCount(uint32_t Runs) { RunCount = Runs; }
281 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
282 void print(raw_fd_ostream &OS, StringRef gcnoFile, StringRef gcdaFile) const;
284 StringMap<LineData> LineInfo;
286 uint32_t ProgramCount;