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/MapVector.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/raw_ostream.h"
36 } // end GCOV namespace
38 /// GCOVOptions - A struct for passing gcov options between functions.
40 GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
41 : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
42 PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {}
54 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
58 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
60 /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
61 bool readGCNOFormat() {
62 StringRef File = Buffer->getBuffer().slice(0, 4);
64 errs() << "Unexpected file type: " << File << ".\n";
71 /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
72 bool readGCDAFormat() {
73 StringRef File = Buffer->getBuffer().slice(0, 4);
75 errs() << "Unexpected file type: " << File << ".\n";
82 /// readGCOVVersion - Read GCOV version.
83 bool readGCOVVersion(GCOV::GCOVVersion &Version) {
84 StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4);
85 if (VersionStr == "*204") {
90 if (VersionStr == "*404") {
95 errs() << "Unexpected version: " << VersionStr << ".\n";
99 /// readFunctionTag - If cursor points to a function tag then increment the
100 /// cursor and return true otherwise return false.
101 bool readFunctionTag() {
102 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
104 Tag[0] != '\0' || Tag[1] != '\0' ||
105 Tag[2] != '\0' || Tag[3] != '\1') {
112 /// readBlockTag - If cursor points to a block tag then increment the
113 /// cursor and return true otherwise return false.
114 bool readBlockTag() {
115 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
117 Tag[0] != '\0' || Tag[1] != '\0' ||
118 Tag[2] != '\x41' || Tag[3] != '\x01') {
125 /// readEdgeTag - If cursor points to an edge tag then increment the
126 /// cursor and return true otherwise return false.
128 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
130 Tag[0] != '\0' || Tag[1] != '\0' ||
131 Tag[2] != '\x43' || Tag[3] != '\x01') {
138 /// readLineTag - If cursor points to a line tag then increment the
139 /// cursor and return true otherwise return false.
141 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
143 Tag[0] != '\0' || Tag[1] != '\0' ||
144 Tag[2] != '\x45' || Tag[3] != '\x01') {
151 /// readArcTag - If cursor points to an gcda arc tag then increment the
152 /// cursor and return true otherwise return false.
154 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
156 Tag[0] != '\0' || Tag[1] != '\0' ||
157 Tag[2] != '\xa1' || Tag[3] != '\1') {
164 /// readObjectTag - If cursor points to an object summary tag then increment
165 /// the cursor and return true otherwise return false.
166 bool readObjectTag() {
167 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
169 Tag[0] != '\0' || Tag[1] != '\0' ||
170 Tag[2] != '\0' || Tag[3] != '\xa1') {
177 /// readProgramTag - If cursor points to a program summary tag then increment
178 /// the cursor and return true otherwise return false.
179 bool readProgramTag() {
180 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
182 Tag[0] != '\0' || Tag[1] != '\0' ||
183 Tag[2] != '\0' || Tag[3] != '\xa3') {
190 bool readInt(uint32_t &Val) {
191 if (Buffer->getBuffer().size() < Cursor+4) {
192 errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
195 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
197 Val = *(const uint32_t *)(Str.data());
201 bool readInt64(uint64_t &Val) {
203 if (!readInt(Lo) || !readInt(Hi)) return false;
204 Val = ((uint64_t)Hi << 32) | Lo;
208 bool readString(StringRef &Str) {
210 // Keep reading until we find a non-zero length. This emulates gcov's
211 // behaviour, which appears to do the same.
213 if (!readInt(Len)) return false;
215 if (Buffer->getBuffer().size() < Cursor+Len) {
216 errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
219 Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
224 uint64_t getCursor() const { return Cursor; }
225 void advanceCursor(uint32_t n) { Cursor += n*4; }
227 MemoryBuffer *Buffer;
231 /// GCOVFile - Collects coverage information for one pair of coverage file
232 /// (.gcno and .gcda).
235 GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
237 bool readGCNO(GCOVBuffer &Buffer);
238 bool readGCDA(GCOVBuffer &Buffer);
239 uint32_t getChecksum() const { return Checksum; }
241 void collectLineCounts(FileInfo &FI);
243 bool GCNOInitialized;
244 GCOV::GCOVVersion Version;
246 SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions;
248 uint32_t ProgramCount;
251 /// GCOVEdge - Collects edge information.
253 GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {}
260 /// GCOVFunction - Collects function information.
263 typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator
266 GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
267 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
268 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
269 StringRef getName() const { return Name; }
270 StringRef getFilename() const { return Filename; }
271 size_t getNumBlocks() const { return Blocks.size(); }
272 uint64_t getEntryCount() const;
273 uint64_t getExitCount() const;
275 BlockIterator block_begin() const { return Blocks.begin(); }
276 BlockIterator block_end() const { return Blocks.end(); }
279 void collectLineCounts(FileInfo &FI);
287 SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks;
288 SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges;
291 /// GCOVBlock - Collects block information.
294 EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {}
300 struct SortDstEdgesFunctor {
301 bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
302 return E1->Dst.Number < E2->Dst.Number;
306 typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
308 GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0),
309 DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {}
311 const GCOVFunction &getParent() const { return Parent; }
312 void addLine(uint32_t N) { Lines.push_back(N); }
313 uint32_t getLastLine() const { return Lines.back(); }
314 void addCount(size_t DstEdgeNo, uint64_t N);
315 uint64_t getCount() const { return Counter; }
317 void addSrcEdge(GCOVEdge *Edge) {
318 assert(&Edge->Dst == this); // up to caller to ensure edge is valid
319 SrcEdges.push_back(Edge);
321 void addDstEdge(GCOVEdge *Edge) {
322 assert(&Edge->Src == this); // up to caller to ensure edge is valid
323 // Check if adding this edge causes list to become unsorted.
324 if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
325 DstEdgesAreSorted = false;
326 DstEdges.push_back(Edge);
328 size_t getNumSrcEdges() const { return SrcEdges.size(); }
329 size_t getNumDstEdges() const { return DstEdges.size(); }
332 EdgeIterator src_begin() const { return SrcEdges.begin(); }
333 EdgeIterator src_end() const { return SrcEdges.end(); }
334 EdgeIterator dst_begin() const { return DstEdges.begin(); }
335 EdgeIterator dst_end() const { return DstEdges.end(); }
338 void collectLineCounts(FileInfo &FI);
340 GCOVFunction &Parent;
343 bool DstEdgesAreSorted;
344 SmallVector<GCOVEdge *, 16> SrcEdges;
345 SmallVector<GCOVEdge *, 16> DstEdges;
346 SmallVector<uint32_t, 16> Lines;
350 // It is unlikely--but possible--for multiple functions to be on the same line.
351 // Therefore this typedef allows LineData.Functions to store multiple functions
352 // per instance. This is rare, however, so optimize for the common case.
353 typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
354 typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
355 typedef SmallVector<const GCOVBlock *, 4> BlockVector;
356 typedef DenseMap<uint32_t, BlockVector> BlockLines;
359 LineData() : LastLine(0) {}
361 FunctionLines Functions;
365 struct GCOVCoverage {
366 GCOVCoverage(StringRef Name) :
367 Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0),
372 uint32_t LogicalLines;
376 uint32_t BranchesExec;
377 uint32_t BranchesTaken;
380 FileInfo(const GCOVOptions &Options) :
381 Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
383 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
384 if (Line > LineInfo[Filename].LastLine)
385 LineInfo[Filename].LastLine = Line;
386 LineInfo[Filename].Blocks[Line-1].push_back(Block);
388 void addFunctionLine(StringRef Filename, uint32_t Line,
389 const GCOVFunction *Function) {
390 if (Line > LineInfo[Filename].LastLine)
391 LineInfo[Filename].LastLine = Line;
392 LineInfo[Filename].Functions[Line-1].push_back(Function);
394 void setRunCount(uint32_t Runs) { RunCount = Runs; }
395 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
396 void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile);
399 std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
400 std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
401 void printFunctionSummary(raw_ostream &OS,
402 const FunctionVector &Funcs) const;
403 void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
404 uint32_t LineIndex, uint32_t &BlockNo) const;
405 void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
406 GCOVCoverage &Coverage, uint32_t &EdgeNo);
407 void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
408 uint64_t Count) const;
410 void printCoverage(const GCOVCoverage &Coverage) const;
411 void printFuncCoverage() const;
412 void printFileCoverage() const;
414 const GCOVOptions &Options;
415 StringMap<LineData> LineInfo;
417 uint32_t ProgramCount;
419 typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4>
421 typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
423 FileCoverageList FileCoverages;
424 FuncCoverageMap FuncCoverages;