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, V704 };
35 /// \brief A struct for passing gcov options between functions.
37 Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
38 : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
39 PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {}
50 } // end GCOV namespace
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 if (VersionStr == "*704") {
98 errs() << "Unexpected version: " << VersionStr << ".\n";
102 /// readFunctionTag - If cursor points to a function tag then increment the
103 /// cursor and return true otherwise return false.
104 bool readFunctionTag() {
105 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
106 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
114 /// readBlockTag - If cursor points to a block tag then increment the
115 /// cursor and return true otherwise return false.
116 bool readBlockTag() {
117 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
118 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
126 /// readEdgeTag - If cursor points to an edge tag then increment the
127 /// cursor and return true otherwise return false.
129 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
130 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
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);
142 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
150 /// readArcTag - If cursor points to an gcda arc tag then increment the
151 /// cursor and return true otherwise return false.
153 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
154 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
162 /// readObjectTag - If cursor points to an object summary tag then increment
163 /// the cursor and return true otherwise return false.
164 bool readObjectTag() {
165 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
166 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
174 /// readProgramTag - If cursor points to a program summary tag then increment
175 /// the cursor and return true otherwise return false.
176 bool readProgramTag() {
177 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
178 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
186 bool readInt(uint32_t &Val) {
187 if (Buffer->getBuffer().size() < Cursor + 4) {
188 errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
191 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
193 Val = *(const uint32_t *)(Str.data());
197 bool readInt64(uint64_t &Val) {
199 if (!readInt(Lo) || !readInt(Hi))
201 Val = ((uint64_t)Hi << 32) | Lo;
205 bool readString(StringRef &Str) {
207 // Keep reading until we find a non-zero length. This emulates gcov's
208 // behaviour, which appears to do the same.
213 if (Buffer->getBuffer().size() < Cursor + Len) {
214 errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
217 Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
222 uint64_t getCursor() const { return Cursor; }
223 void advanceCursor(uint32_t n) { Cursor += n * 4; }
226 MemoryBuffer *Buffer;
230 /// GCOVFile - Collects coverage information for one pair of coverage file
231 /// (.gcno and .gcda).
235 : 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);
244 bool GCNOInitialized;
245 GCOV::GCOVVersion Version;
247 SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions;
249 uint32_t ProgramCount;
252 /// GCOVEdge - Collects edge information.
254 GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {}
261 /// GCOVFunction - Collects function information.
264 typedef pointee_iterator<SmallVectorImpl<
265 std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator;
267 GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
268 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
269 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
270 StringRef getName() const { return Name; }
271 StringRef getFilename() const { return Filename; }
272 size_t getNumBlocks() const { return Blocks.size(); }
273 uint64_t getEntryCount() const;
274 uint64_t getExitCount() const;
276 BlockIterator block_begin() const { return Blocks.begin(); }
277 BlockIterator block_end() const { return Blocks.end(); }
278 iterator_range<BlockIterator> blocks() const {
279 return make_range(block_begin(), block_end());
283 void collectLineCounts(FileInfo &FI);
292 SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks;
293 SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges;
296 /// GCOVBlock - Collects block information.
299 EdgeWeight(GCOVBlock *D) : Dst(D), Count(0) {}
305 struct SortDstEdgesFunctor {
306 bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
307 return E1->Dst.Number < E2->Dst.Number;
312 typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
314 GCOVBlock(GCOVFunction &P, uint32_t N)
315 : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(),
316 DstEdges(), Lines() {}
318 const GCOVFunction &getParent() const { return Parent; }
319 void addLine(uint32_t N) { Lines.push_back(N); }
320 uint32_t getLastLine() const { return Lines.back(); }
321 void addCount(size_t DstEdgeNo, uint64_t N);
322 uint64_t getCount() const { return Counter; }
324 void addSrcEdge(GCOVEdge *Edge) {
325 assert(&Edge->Dst == this); // up to caller to ensure edge is valid
326 SrcEdges.push_back(Edge);
328 void addDstEdge(GCOVEdge *Edge) {
329 assert(&Edge->Src == this); // up to caller to ensure edge is valid
330 // Check if adding this edge causes list to become unsorted.
331 if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
332 DstEdgesAreSorted = false;
333 DstEdges.push_back(Edge);
335 size_t getNumSrcEdges() const { return SrcEdges.size(); }
336 size_t getNumDstEdges() const { return DstEdges.size(); }
339 EdgeIterator src_begin() const { return SrcEdges.begin(); }
340 EdgeIterator src_end() const { return SrcEdges.end(); }
341 iterator_range<EdgeIterator> srcs() const {
342 return make_range(src_begin(), src_end());
345 EdgeIterator dst_begin() const { return DstEdges.begin(); }
346 EdgeIterator dst_end() const { return DstEdges.end(); }
347 iterator_range<EdgeIterator> dsts() const {
348 return make_range(dst_begin(), dst_end());
352 void collectLineCounts(FileInfo &FI);
355 GCOVFunction &Parent;
358 bool DstEdgesAreSorted;
359 SmallVector<GCOVEdge *, 16> SrcEdges;
360 SmallVector<GCOVEdge *, 16> DstEdges;
361 SmallVector<uint32_t, 16> Lines;
365 // It is unlikely--but possible--for multiple functions to be on the same
367 // Therefore this typedef allows LineData.Functions to store multiple
369 // per instance. This is rare, however, so optimize for the common case.
370 typedef SmallVector<const GCOVFunction *, 1> FunctionVector;
371 typedef DenseMap<uint32_t, FunctionVector> FunctionLines;
372 typedef SmallVector<const GCOVBlock *, 4> BlockVector;
373 typedef DenseMap<uint32_t, BlockVector> BlockLines;
376 LineData() : LastLine(0) {}
378 FunctionLines Functions;
382 struct GCOVCoverage {
383 GCOVCoverage(StringRef Name)
384 : Name(Name), LogicalLines(0), LinesExec(0), Branches(0),
385 BranchesExec(0), BranchesTaken(0) {}
389 uint32_t LogicalLines;
393 uint32_t BranchesExec;
394 uint32_t BranchesTaken;
398 FileInfo(const GCOV::Options &Options)
399 : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
401 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
402 if (Line > LineInfo[Filename].LastLine)
403 LineInfo[Filename].LastLine = Line;
404 LineInfo[Filename].Blocks[Line - 1].push_back(Block);
406 void addFunctionLine(StringRef Filename, uint32_t Line,
407 const GCOVFunction *Function) {
408 if (Line > LineInfo[Filename].LastLine)
409 LineInfo[Filename].LastLine = Line;
410 LineInfo[Filename].Functions[Line - 1].push_back(Function);
412 void setRunCount(uint32_t Runs) { RunCount = Runs; }
413 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
414 void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
418 std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
419 std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
420 void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
421 void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
422 uint32_t LineIndex, uint32_t &BlockNo) const;
423 void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
424 GCOVCoverage &Coverage, uint32_t &EdgeNo);
425 void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
426 uint64_t Count) const;
428 void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
429 void printFuncCoverage(raw_ostream &OS) const;
430 void printFileCoverage(raw_ostream &OS) const;
432 const GCOV::Options &Options;
433 StringMap<LineData> LineInfo;
435 uint32_t ProgramCount;
437 typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList;
438 typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
440 FileCoverageList FileCoverages;
441 FuncCoverageMap FuncCoverages;