diff options
author | David L. Jones <dlj@google.com> | 2017-11-15 01:40:05 +0000 |
---|---|---|
committer | David L. Jones <dlj@google.com> | 2017-11-15 01:40:05 +0000 |
commit | d5c2cca72463233df77a065f201db31b140eb44d (patch) | |
tree | 3f9a978131033302a58b7db7db1ecf2a4622bad2 /include/llvm/Support/GCOV.h | |
parent | ce7676b8db6bac096dad4c4ad62e9e6bb8aa1064 (diff) | |
parent | dcf64df89bc6d775e266ebd6b0134d135f47a35b (diff) | |
download | llvm-testing.tar.gz |
Creating branches/google/testing and tags/google/testing/2017-11-14 from r317716testing
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/testing@318248 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Support/GCOV.h')
-rw-r--r-- | include/llvm/Support/GCOV.h | 460 |
1 files changed, 0 insertions, 460 deletions
diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h deleted file mode 100644 index 02016e7dbd62..000000000000 --- a/include/llvm/Support/GCOV.h +++ /dev/null @@ -1,460 +0,0 @@ -//===- GCOV.h - LLVM coverage tool ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header provides the interface to read and write coverage files that -// use 'gcov' format. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_GCOV_H -#define LLVM_SUPPORT_GCOV_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <memory> -#include <string> -#include <utility> - -namespace llvm { - -class GCOVFunction; -class GCOVBlock; -class FileInfo; - -namespace GCOV { - -enum GCOVVersion { V402, V404, V704 }; - -/// \brief A struct for passing gcov options between functions. -struct Options { - Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N) - : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), - PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {} - - bool AllBlocks; - bool BranchInfo; - bool BranchCount; - bool FuncCoverage; - bool PreservePaths; - bool UncondBranch; - bool LongFileNames; - bool NoOutput; -}; - -} // end namespace GCOV - -/// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific -/// read operations. -class GCOVBuffer { -public: - GCOVBuffer(MemoryBuffer *B) : Buffer(B) {} - - /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. - bool readGCNOFormat() { - StringRef File = Buffer->getBuffer().slice(0, 4); - if (File != "oncg") { - errs() << "Unexpected file type: " << File << ".\n"; - return false; - } - Cursor = 4; - return true; - } - - /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer. - bool readGCDAFormat() { - StringRef File = Buffer->getBuffer().slice(0, 4); - if (File != "adcg") { - errs() << "Unexpected file type: " << File << ".\n"; - return false; - } - Cursor = 4; - return true; - } - - /// readGCOVVersion - Read GCOV version. - bool readGCOVVersion(GCOV::GCOVVersion &Version) { - StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (VersionStr == "*204") { - Cursor += 4; - Version = GCOV::V402; - return true; - } - if (VersionStr == "*404") { - Cursor += 4; - Version = GCOV::V404; - return true; - } - if (VersionStr == "*704") { - Cursor += 4; - Version = GCOV::V704; - return true; - } - errs() << "Unexpected version: " << VersionStr << ".\n"; - return false; - } - - /// readFunctionTag - If cursor points to a function tag then increment the - /// cursor and return true otherwise return false. - bool readFunctionTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || - Tag[3] != '\1') { - return false; - } - Cursor += 4; - return true; - } - - /// readBlockTag - If cursor points to a block tag then increment the - /// cursor and return true otherwise return false. - bool readBlockTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' || - Tag[3] != '\x01') { - return false; - } - Cursor += 4; - return true; - } - - /// readEdgeTag - If cursor points to an edge tag then increment the - /// cursor and return true otherwise return false. - bool readEdgeTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' || - Tag[3] != '\x01') { - return false; - } - Cursor += 4; - return true; - } - - /// readLineTag - If cursor points to a line tag then increment the - /// cursor and return true otherwise return false. - bool readLineTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' || - Tag[3] != '\x01') { - return false; - } - Cursor += 4; - return true; - } - - /// readArcTag - If cursor points to an gcda arc tag then increment the - /// cursor and return true otherwise return false. - bool readArcTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' || - Tag[3] != '\1') { - return false; - } - Cursor += 4; - return true; - } - - /// readObjectTag - If cursor points to an object summary tag then increment - /// the cursor and return true otherwise return false. - bool readObjectTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || - Tag[3] != '\xa1') { - return false; - } - Cursor += 4; - return true; - } - - /// readProgramTag - If cursor points to a program summary tag then increment - /// the cursor and return true otherwise return false. - bool readProgramTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || - Tag[3] != '\xa3') { - return false; - } - Cursor += 4; - return true; - } - - bool readInt(uint32_t &Val) { - if (Buffer->getBuffer().size() < Cursor + 4) { - errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n"; - return false; - } - StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4); - Cursor += 4; - Val = *(const uint32_t *)(Str.data()); - return true; - } - - bool readInt64(uint64_t &Val) { - uint32_t Lo, Hi; - if (!readInt(Lo) || !readInt(Hi)) - return false; - Val = ((uint64_t)Hi << 32) | Lo; - return true; - } - - bool readString(StringRef &Str) { - uint32_t Len = 0; - // Keep reading until we find a non-zero length. This emulates gcov's - // behaviour, which appears to do the same. - while (Len == 0) - if (!readInt(Len)) - return false; - Len *= 4; - if (Buffer->getBuffer().size() < Cursor + Len) { - errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n"; - return false; - } - Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first; - Cursor += Len; - return true; - } - - uint64_t getCursor() const { return Cursor; } - void advanceCursor(uint32_t n) { Cursor += n * 4; } - -private: - MemoryBuffer *Buffer; - uint64_t Cursor = 0; -}; - -/// GCOVFile - Collects coverage information for one pair of coverage file -/// (.gcno and .gcda). -class GCOVFile { -public: - GCOVFile() = default; - - bool readGCNO(GCOVBuffer &Buffer); - bool readGCDA(GCOVBuffer &Buffer); - uint32_t getChecksum() const { return Checksum; } - void print(raw_ostream &OS) const; - void dump() const; - void collectLineCounts(FileInfo &FI); - -private: - bool GCNOInitialized = false; - GCOV::GCOVVersion Version; - uint32_t Checksum = 0; - SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions; - uint32_t RunCount = 0; - uint32_t ProgramCount = 0; -}; - -/// GCOVEdge - Collects edge information. -struct GCOVEdge { - GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D) {} - - GCOVBlock &Src; - GCOVBlock &Dst; - uint64_t Count = 0; -}; - -/// GCOVFunction - Collects function information. -class GCOVFunction { -public: - using BlockIterator = pointee_iterator<SmallVectorImpl< - std::unique_ptr<GCOVBlock>>::const_iterator>; - - GCOVFunction(GCOVFile &P) : Parent(P) {} - - bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); - bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); - StringRef getName() const { return Name; } - StringRef getFilename() const { return Filename; } - size_t getNumBlocks() const { return Blocks.size(); } - uint64_t getEntryCount() const; - uint64_t getExitCount() const; - - BlockIterator block_begin() const { return Blocks.begin(); } - BlockIterator block_end() const { return Blocks.end(); } - iterator_range<BlockIterator> blocks() const { - return make_range(block_begin(), block_end()); - } - - void print(raw_ostream &OS) const; - void dump() const; - void collectLineCounts(FileInfo &FI); - -private: - GCOVFile &Parent; - uint32_t Ident = 0; - uint32_t Checksum; - uint32_t LineNumber = 0; - StringRef Name; - StringRef Filename; - SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks; - SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges; -}; - -/// GCOVBlock - Collects block information. -class GCOVBlock { - struct EdgeWeight { - EdgeWeight(GCOVBlock *D) : Dst(D) {} - - GCOVBlock *Dst; - uint64_t Count = 0; - }; - - struct SortDstEdgesFunctor { - bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) { - return E1->Dst.Number < E2->Dst.Number; - } - }; - -public: - using EdgeIterator = SmallVectorImpl<GCOVEdge *>::const_iterator; - - GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N) {} - ~GCOVBlock(); - - const GCOVFunction &getParent() const { return Parent; } - void addLine(uint32_t N) { Lines.push_back(N); } - uint32_t getLastLine() const { return Lines.back(); } - void addCount(size_t DstEdgeNo, uint64_t N); - uint64_t getCount() const { return Counter; } - - void addSrcEdge(GCOVEdge *Edge) { - assert(&Edge->Dst == this); // up to caller to ensure edge is valid - SrcEdges.push_back(Edge); - } - - void addDstEdge(GCOVEdge *Edge) { - assert(&Edge->Src == this); // up to caller to ensure edge is valid - // Check if adding this edge causes list to become unsorted. - if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number) - DstEdgesAreSorted = false; - DstEdges.push_back(Edge); - } - - size_t getNumSrcEdges() const { return SrcEdges.size(); } - size_t getNumDstEdges() const { return DstEdges.size(); } - void sortDstEdges(); - - EdgeIterator src_begin() const { return SrcEdges.begin(); } - EdgeIterator src_end() const { return SrcEdges.end(); } - iterator_range<EdgeIterator> srcs() const { - return make_range(src_begin(), src_end()); - } - - EdgeIterator dst_begin() const { return DstEdges.begin(); } - EdgeIterator dst_end() const { return DstEdges.end(); } - iterator_range<EdgeIterator> dsts() const { - return make_range(dst_begin(), dst_end()); - } - - void print(raw_ostream &OS) const; - void dump() const; - void collectLineCounts(FileInfo &FI); - -private: - GCOVFunction &Parent; - uint32_t Number; - uint64_t Counter = 0; - bool DstEdgesAreSorted = true; - SmallVector<GCOVEdge *, 16> SrcEdges; - SmallVector<GCOVEdge *, 16> DstEdges; - SmallVector<uint32_t, 16> Lines; -}; - -class FileInfo { - // It is unlikely--but possible--for multiple functions to be on the same - // line. - // Therefore this typedef allows LineData.Functions to store multiple - // functions - // per instance. This is rare, however, so optimize for the common case. - using FunctionVector = SmallVector<const GCOVFunction *, 1>; - using FunctionLines = DenseMap<uint32_t, FunctionVector>; - using BlockVector = SmallVector<const GCOVBlock *, 4>; - using BlockLines = DenseMap<uint32_t, BlockVector>; - - struct LineData { - LineData() = default; - - BlockLines Blocks; - FunctionLines Functions; - uint32_t LastLine = 0; - }; - - struct GCOVCoverage { - GCOVCoverage(StringRef Name) : Name(Name) {} - - StringRef Name; - - uint32_t LogicalLines = 0; - uint32_t LinesExec = 0; - - uint32_t Branches = 0; - uint32_t BranchesExec = 0; - uint32_t BranchesTaken = 0; - }; - -public: - FileInfo(const GCOV::Options &Options) : Options(Options) {} - - void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) { - if (Line > LineInfo[Filename].LastLine) - LineInfo[Filename].LastLine = Line; - LineInfo[Filename].Blocks[Line - 1].push_back(Block); - } - - void addFunctionLine(StringRef Filename, uint32_t Line, - const GCOVFunction *Function) { - if (Line > LineInfo[Filename].LastLine) - LineInfo[Filename].LastLine = Line; - LineInfo[Filename].Functions[Line - 1].push_back(Function); - } - - void setRunCount(uint32_t Runs) { RunCount = Runs; } - void setProgramCount(uint32_t Programs) { ProgramCount = Programs; } - void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile, - StringRef GCDAFile); - -private: - std::string getCoveragePath(StringRef Filename, StringRef MainFilename); - std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath); - void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const; - void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, - uint32_t LineIndex, uint32_t &BlockNo) const; - void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, - GCOVCoverage &Coverage, uint32_t &EdgeNo); - void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, - uint64_t Count) const; - - void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const; - void printFuncCoverage(raw_ostream &OS) const; - void printFileCoverage(raw_ostream &OS) const; - - const GCOV::Options &Options; - StringMap<LineData> LineInfo; - uint32_t RunCount = 0; - uint32_t ProgramCount = 0; - - using FileCoverageList = SmallVector<std::pair<std::string, GCOVCoverage>, 4>; - using FuncCoverageMap = MapVector<const GCOVFunction *, GCOVCoverage>; - - FileCoverageList FileCoverages; - FuncCoverageMap FuncCoverages; -}; - -} // end namespace llvm - -#endif // LLVM_SUPPORT_GCOV_H |