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/ADT/iterator.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/raw_ostream.h"
33 enum GCOVVersion { V402, V404 };
34 } // end GCOV namespace
36 /// GCOVOptions - A struct for passing gcov options between functions.
38 GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
39 : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
40 PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {}
52 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
56 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
58 /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
59 bool readGCNOFormat() {
60 StringRef File = Buffer->getBuffer().slice(0, 4);
62 errs() << "Unexpected file type: " << File << ".\n";
69 /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
70 bool readGCDAFormat() {
71 StringRef File = Buffer->getBuffer().slice(0, 4);
73 errs() << "Unexpected file type: " << File << ".\n";
80 /// readGCOVVersion - Read GCOV version.
81 bool readGCOVVersion(GCOV::GCOVVersion &Version) {
82 StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4);
83 if (VersionStr == "*204") {
88 if (VersionStr == "*404") {
93 errs() << "Unexpected version: " << VersionStr << ".\n";
97 /// readFunctionTag - If cursor points to a function tag then increment the
98 /// cursor and return true otherwise return false.
99 bool readFunctionTag() {
100 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
101 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
109 /// readBlockTag - If cursor points to a block tag then increment the
110 /// cursor and return true otherwise return false.
111 bool readBlockTag() {
112 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
113 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
121 /// readEdgeTag - If cursor points to an edge tag then increment the
122 /// cursor and return true otherwise return false.
124 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
125 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
133 /// readLineTag - If cursor points to a line tag then increment the
134 /// cursor and return true otherwise return false.
136 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
137 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
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);
149 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
157 /// readObjectTag - If cursor points to an object summary tag then increment
158 /// the cursor and return true otherwise return false.
159 bool readObjectTag() {
160 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
161 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
169 /// readProgramTag - If cursor points to a program summary tag then increment
170 /// the cursor and return true otherwise return false.
171 bool readProgramTag() {
172 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
173 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
181 bool readInt(uint32_t &Val) {
182 if (Buffer->getBuffer().size() < Cursor + 4) {
183 errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
186 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
188 Val = *(const uint32_t *)(Str.data());
192 bool readInt64(uint64_t &Val) {
194 if (!readInt(Lo) || !readInt(Hi))
196 Val = ((uint64_t)Hi << 32) | Lo;
200 bool readString(StringRef &Str) {
202 // Keep reading until we find a non-zero length. This emulates gcov's
203 // behaviour, which appears to do the same.
208 if (Buffer->getBuffer().size() < Cursor + Len) {
209 errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
212 Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
217 uint64_t getCursor() const { return Cursor; }
218 void advanceCursor(uint32_t n) { Cursor += n * 4; }
221 MemoryBuffer *Buffer;
225 /// GCOVFile - Collects coverage information for one pair of coverage file
226 /// (.gcno and .gcda).
230 : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
232 bool readGCNO(GCOVBuffer &Buffer);
233 bool readGCDA(GCOVBuffer &Buffer);
234 uint32_t getChecksum() const { return Checksum; }
236 void collectLineCounts(FileInfo &FI);
239 bool GCNOInitialized;
240 GCOV::GCOVVersion Version;
242 SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions;
244 uint32_t ProgramCount;
247 /// GCOVEdge - Collects edge information.
249 GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {}
256 /// GCOVFunction - Collects function information.
259 typedef pointee_iterator<SmallVectorImpl<
260 std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator;
262 GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
263 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
264 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
265 StringRef getName() const { return Name; }
266 StringRef getFilename() const { return Filename; }
267 size_t getNumBlocks() const { return Blocks.size(); }
268 uint64_t getEntryCount() const;
269 uint64_t getExitCount() const;
271 BlockIterator block_begin() const { return Blocks.begin(); }
272 BlockIterator block_end() const { return Blocks.end(); }
273 iterator_range<BlockIterator> blocks() const {
274 return make_range(block_begin(), block_end());
278 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;
307 typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
309 GCOVBlock(GCOVFunction &P, uint32_t N)
310 : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(),
311 DstEdges(), Lines() {}
313 const GCOVFunction &getParent() const { return Parent; }
314 void addLine(uint32_t N) { Lines.push_back(N); }
315 uint32_t getLastLine() const { return Lines.back(); }
316 void addCount(size_t DstEdgeNo, uint64_t N);
317 uint64_t getCount() const { return Counter; }
319 void addSrcEdge(GCOVEdge *Edge) {
320 assert(&Edge->Dst == this); // up to caller to ensure edge is valid
321 SrcEdges.push_back(Edge);
323 void addDstEdge(GCOVEdge *Edge) {
324 assert(&Edge->Src == this); // up to caller to ensure edge is valid
325 // Check if adding this edge causes list to become unsorted.
326 if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
327 DstEdgesAreSorted = false;
328 DstEdges.push_back(Edge);
330 size_t getNumSrcEdges() const { return SrcEdges.size(); }
331 size_t getNumDstEdges() const { return DstEdges.size(); }
334 EdgeIterator src_begin() const { return SrcEdges.begin(); }
335 EdgeIterator src_end() const { return SrcEdges.end(); }
336 iterator_range<EdgeIterator> srcs() const {
337 return make_range(src_begin(), src_end());
340 EdgeIterator dst_begin() const { return DstEdges.begin(); }
341 EdgeIterator dst_end() const { return DstEdges.end(); }
342 iterator_range<EdgeIterator> dsts() const {
343 return make_range(dst_begin(), dst_end());
347 void collectLineCounts(FileInfo &FI);
350 GCOVFunction &Parent;
353 bool DstEdgesAreSorted;
354 SmallVector<GCOVEdge *, 16> SrcEdges;
355 SmallVector<GCOVEdge *, 16> DstEdges;
356 SmallVector<uint32_t, 16> Lines;
360 // It is unlikely--but possible--for multiple functions to be on the same
362 // Therefore this typedef allows LineData.Functions to store multiple
364 // per instance. This is rare, however, so optimize for the common case.
365 typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
366 typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
367 typedef SmallVector<const GCOVBlock *, 4> BlockVector;
368 typedef DenseMap<uint32_t, BlockVector> BlockLines;
371 LineData() : LastLine(0) {}
373 FunctionLines Functions;
377 struct GCOVCoverage {
378 GCOVCoverage(StringRef Name)
379 : Name(Name), LogicalLines(0), LinesExec(0), Branches(0),
380 BranchesExec(0), BranchesTaken(0) {}
384 uint32_t LogicalLines;
388 uint32_t BranchesExec;
389 uint32_t BranchesTaken;
393 FileInfo(const GCOVOptions &Options)
394 : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
396 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
397 if (Line > LineInfo[Filename].LastLine)
398 LineInfo[Filename].LastLine = Line;
399 LineInfo[Filename].Blocks[Line - 1].push_back(Block);
401 void addFunctionLine(StringRef Filename, uint32_t Line,
402 const GCOVFunction *Function) {
403 if (Line > LineInfo[Filename].LastLine)
404 LineInfo[Filename].LastLine = Line;
405 LineInfo[Filename].Functions[Line - 1].push_back(Function);
407 void setRunCount(uint32_t Runs) { RunCount = Runs; }
408 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
409 void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
413 std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
414 std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
415 void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
416 void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
417 uint32_t LineIndex, uint32_t &BlockNo) const;
418 void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
419 GCOVCoverage &Coverage, uint32_t &EdgeNo);
420 void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
421 uint64_t Count) const;
423 void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
424 void printFuncCoverage(raw_ostream &OS) const;
425 void printFileCoverage(raw_ostream &OS) const;
427 const GCOVOptions &Options;
428 StringMap<LineData> LineInfo;
430 uint32_t ProgramCount;
432 typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList;
433 typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
435 FileCoverageList FileCoverages;
436 FuncCoverageMap FuncCoverages;