- //===- GCOV.h - LLVM coverage tool ------------------------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This header provides the interface to read and write coverage files that 
- // use 'gcov' format. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_PROFILEDATA_GCOV_H 
- #define LLVM_PROFILEDATA_GCOV_H 
-   
- #include "llvm/ADT/DenseSet.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/DataExtractor.h" 
- #include "llvm/Support/MemoryBuffer.h" 
- #include "llvm/Support/raw_ostream.h" 
- #include <algorithm> 
- #include <cstddef> 
- #include <cstdint> 
- #include <map> 
- #include <memory> 
- #include <string> 
- #include <utility> 
-   
- namespace llvm { 
-   
- class GCOVFunction; 
- class GCOVBlock; 
-   
- namespace GCOV { 
-   
- enum GCOVVersion { V304, V407, V408, V800, V900, V1200 }; 
-   
- /// A struct for passing gcov options between functions. 
- struct Options { 
-   Options(bool A, bool B, bool C, bool F, bool P, bool U, bool I, bool L, 
-           bool M, bool N, bool R, bool T, bool X, std::string SourcePrefix) 
-       : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), 
-         PreservePaths(P), UncondBranch(U), Intermediate(I), LongFileNames(L), 
-         Demangle(M), NoOutput(N), RelativeOnly(R), UseStdout(T), 
-         HashFilenames(X), SourcePrefix(std::move(SourcePrefix)) {} 
-   
-   bool AllBlocks; 
-   bool BranchInfo; 
-   bool BranchCount; 
-   bool FuncCoverage; 
-   bool PreservePaths; 
-   bool UncondBranch; 
-   bool Intermediate; 
-   bool LongFileNames; 
-   bool Demangle; 
-   bool NoOutput; 
-   bool RelativeOnly; 
-   bool UseStdout; 
-   bool HashFilenames; 
-   std::string SourcePrefix; 
- }; 
-   
- } // end namespace GCOV 
-   
- /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific 
- /// read operations. 
- class GCOVBuffer { 
- public: 
-   GCOVBuffer(MemoryBuffer *B) : Buffer(B) {} 
-   ~GCOVBuffer() { consumeError(cursor.takeError()); } 
-   
-   /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. 
-   bool readGCNOFormat() { 
-     StringRef buf = Buffer->getBuffer(); 
-     StringRef magic = buf.substr(0, 4); 
-     if (magic == "gcno") { 
-       de = DataExtractor(buf.substr(4), false, 0); 
-     } else if (magic == "oncg") { 
-       de = DataExtractor(buf.substr(4), true, 0); 
-     } else { 
-       errs() << "unexpected magic: " << magic << "\n"; 
-       return false; 
-     } 
-     return true; 
-   } 
-   
-   /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer. 
-   bool readGCDAFormat() { 
-     StringRef buf = Buffer->getBuffer(); 
-     StringRef magic = buf.substr(0, 4); 
-     if (magic == "gcda") { 
-       de = DataExtractor(buf.substr(4), false, 0); 
-     } else if (magic == "adcg") { 
-       de = DataExtractor(buf.substr(4), true, 0); 
-     } else { 
-       return false; 
-     } 
-     return true; 
-   } 
-   
-   /// readGCOVVersion - Read GCOV version. 
-   bool readGCOVVersion(GCOV::GCOVVersion &version) { 
-     std::string str(de.getBytes(cursor, 4)); 
-     if (str.size() != 4) 
-       return false; 
-     if (de.isLittleEndian()) 
-       std::reverse(str.begin(), str.end()); 
-     int ver = str[0] >= 'A' 
-                   ? (str[0] - 'A') * 100 + (str[1] - '0') * 10 + str[2] - '0' 
-                   : (str[0] - '0') * 10 + str[2] - '0'; 
-     if (ver >= 120) { 
-       this->version = version = GCOV::V1200; 
-       return true; 
-     } else if (ver >= 90) { 
-       // PR gcov-profile/84846, r269678 
-       this->version = version = GCOV::V900; 
-       return true; 
-     } else if (ver >= 80) { 
-       // PR gcov-profile/48463 
-       this->version = version = GCOV::V800; 
-       return true; 
-     } else if (ver >= 48) { 
-       // r189778: the exit block moved from the last to the second. 
-       this->version = version = GCOV::V408; 
-       return true; 
-     } else if (ver >= 47) { 
-       // r173147: split checksum into cfg checksum and line checksum. 
-       this->version = version = GCOV::V407; 
-       return true; 
-     } else if (ver >= 34) { 
-       this->version = version = GCOV::V304; 
-       return true; 
-     } 
-     errs() << "unexpected version: " << str << "\n"; 
-     return false; 
-   } 
-   
-   uint32_t getWord() { return de.getU32(cursor); } 
-   StringRef getString() { 
-     uint32_t len; 
-     if (!readInt(len) || len == 0) 
-       return {}; 
-     return de.getBytes(cursor, len * 4).split('\0').first; 
-   } 
-   
-   bool readInt(uint32_t &Val) { 
-     if (cursor.tell() + 4 > de.size()) { 
-       Val = 0; 
-       errs() << "unexpected end of memory buffer: " << cursor.tell() << "\n"; 
-       return false; 
-     } 
-     Val = de.getU32(cursor); 
-     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; 
-     if (!readInt(len) || len == 0) 
-       return false; 
-     if (version >= GCOV::V1200) 
-       str = de.getBytes(cursor, len).drop_back(); 
-     else 
-       str = de.getBytes(cursor, len * 4).split('\0').first; 
-     return bool(cursor); 
-   } 
-   
-   DataExtractor de{ArrayRef<uint8_t>{}, false, 0}; 
-   DataExtractor::Cursor cursor{0}; 
-   
- private: 
-   MemoryBuffer *Buffer; 
-   GCOV::GCOVVersion version{}; 
- }; 
-   
- /// 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); 
-   GCOV::GCOVVersion getVersion() const { return version; } 
-   void print(raw_ostream &OS) const; 
-   void dump() const; 
-   
-   std::vector<std::string> filenames; 
-   StringMap<unsigned> filenameToIdx; 
-   
- public: 
-   bool GCNOInitialized = false; 
-   GCOV::GCOVVersion version{}; 
-   uint32_t checksum = 0; 
-   StringRef cwd; 
-   SmallVector<std::unique_ptr<GCOVFunction>, 16> functions; 
-   std::map<uint32_t, GCOVFunction *> identToFunction; 
-   uint32_t runCount = 0; 
-   uint32_t programCount = 0; 
-   
-   using iterator = pointee_iterator< 
-       SmallVectorImpl<std::unique_ptr<GCOVFunction>>::const_iterator>; 
-   iterator begin() const { return iterator(functions.begin()); } 
-   iterator end() const { return iterator(functions.end()); } 
- }; 
-   
- struct GCOVArc { 
-   GCOVArc(GCOVBlock &src, GCOVBlock &dst, uint32_t flags) 
-       : src(src), dst(dst), flags(flags) {} 
-   bool onTree() const; 
-   
-   GCOVBlock &src; 
-   GCOVBlock &dst; 
-   uint32_t flags; 
-   uint64_t count = 0; 
-   uint64_t cycleCount = 0; 
- }; 
-   
- /// GCOVFunction - Collects function information. 
- class GCOVFunction { 
- public: 
-   using BlockIterator = pointee_iterator< 
-       SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator>; 
-   
-   GCOVFunction(GCOVFile &file) : file(file) {} 
-   
-   StringRef getName(bool demangle) const; 
-   StringRef getFilename() const; 
-   uint64_t getEntryCount() const; 
-   GCOVBlock &getExitBlock() const; 
-   
-   iterator_range<BlockIterator> blocksRange() const { 
-     return make_range(blocks.begin(), blocks.end()); 
-   } 
-   
-   uint64_t propagateCounts(const GCOVBlock &v, GCOVArc *pred); 
-   void print(raw_ostream &OS) const; 
-   void dump() const; 
-   
-   GCOVFile &file; 
-   uint32_t ident = 0; 
-   uint32_t linenoChecksum; 
-   uint32_t cfgChecksum = 0; 
-   uint32_t startLine = 0; 
-   uint32_t startColumn = 0; 
-   uint32_t endLine = 0; 
-   uint32_t endColumn = 0; 
-   uint8_t artificial = 0; 
-   StringRef Name; 
-   mutable SmallString<0> demangled; 
-   unsigned srcIdx; 
-   SmallVector<std::unique_ptr<GCOVBlock>, 0> blocks; 
-   SmallVector<std::unique_ptr<GCOVArc>, 0> arcs, treeArcs; 
-   DenseSet<const GCOVBlock *> visited; 
- }; 
-   
- /// GCOVBlock - Collects block information. 
- class GCOVBlock { 
- public: 
-   using EdgeIterator = SmallVectorImpl<GCOVArc *>::const_iterator; 
-   using BlockVector = SmallVector<const GCOVBlock *, 1>; 
-   using BlockVectorLists = SmallVector<BlockVector, 4>; 
-   using Edges = SmallVector<GCOVArc *, 4>; 
-   
-   GCOVBlock(uint32_t N) : number(N) {} 
-   
-   void addLine(uint32_t N) { lines.push_back(N); } 
-   uint32_t getLastLine() const { return lines.back(); } 
-   uint64_t getCount() const { return count; } 
-   
-   void addSrcEdge(GCOVArc *Edge) { pred.push_back(Edge); } 
-   
-   void addDstEdge(GCOVArc *Edge) { succ.push_back(Edge); } 
-   
-   iterator_range<EdgeIterator> srcs() const { 
-     return make_range(pred.begin(), pred.end()); 
-   } 
-   
-   iterator_range<EdgeIterator> dsts() const { 
-     return make_range(succ.begin(), succ.end()); 
-   } 
-   
-   void print(raw_ostream &OS) const; 
-   void dump() const; 
-   
-   static uint64_t 
-   augmentOneCycle(GCOVBlock *src, 
-                   std::vector<std::pair<GCOVBlock *, size_t>> &stack); 
-   static uint64_t getCyclesCount(const BlockVector &blocks); 
-   static uint64_t getLineCount(const BlockVector &Blocks); 
-   
- public: 
-   uint32_t number; 
-   uint64_t count = 0; 
-   SmallVector<GCOVArc *, 2> pred; 
-   SmallVector<GCOVArc *, 2> succ; 
-   SmallVector<uint32_t, 4> lines; 
-   bool traversable = false; 
-   GCOVArc *incoming = nullptr; 
- }; 
-   
- void gcovOneInput(const GCOV::Options &options, StringRef filename, 
-                   StringRef gcno, StringRef gcda, GCOVFile &file); 
-   
- } // end namespace llvm 
-   
- #endif // LLVM_PROFILEDATA_GCOV_H 
-