Home | History | Annotate | Download | only in Support
      1 //===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This header provides the interface to read and write coverage files that
     11 // use 'gcov' format.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_GCOV_H
     16 #define LLVM_GCOV_H
     17 
     18 #include "llvm/ADT/SmallVector.h"
     19 #include "llvm/ADT/StringMap.h"
     20 #include "llvm/Support/MemoryBuffer.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 
     23 namespace llvm {
     24 
     25 class GCOVFunction;
     26 class GCOVBlock;
     27 class GCOVLines;
     28 class FileInfo;
     29 
     30 enum GCOVFormat {
     31   InvalidGCOV,
     32   GCNO_402,
     33   GCNO_404,
     34   GCDA_402,
     35   GCDA_404
     36 };
     37 
     38 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
     39 /// read operations.
     40 class GCOVBuffer {
     41 public:
     42   GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
     43 
     44   /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
     45   enum GCOVFormat readGCOVFormat() {
     46     StringRef Magic = Buffer->getBuffer().slice(0, 12);
     47     Cursor = 12;
     48     if (Magic == "oncg*404MVLL")
     49       return GCNO_404;
     50     else if (Magic == "oncg*204MVLL")
     51       return GCNO_402;
     52     else if (Magic == "adcg*404MVLL")
     53       return GCDA_404;
     54     else if (Magic == "adcg*204MVLL")
     55       return GCDA_402;
     56 
     57     Cursor = 0;
     58     return InvalidGCOV;
     59   }
     60 
     61   /// readFunctionTag - If cursor points to a function tag then increment the
     62   /// cursor and return true otherwise return false.
     63   bool readFunctionTag() {
     64     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
     65     if (Tag.empty() ||
     66 	Tag[0] != '\0' || Tag[1] != '\0' ||
     67 	Tag[2] != '\0' || Tag[3] != '\1') {
     68       return false;
     69     }
     70     Cursor += 4;
     71     return true;
     72   }
     73 
     74   /// readBlockTag - If cursor points to a block tag then increment the
     75   /// cursor and return true otherwise return false.
     76   bool readBlockTag() {
     77     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
     78     if (Tag.empty() ||
     79 	Tag[0] != '\0' || Tag[1] != '\0' ||
     80 	Tag[2] != '\x41' || Tag[3] != '\x01') {
     81       return false;
     82     }
     83     Cursor += 4;
     84     return true;
     85   }
     86 
     87   /// readEdgeTag - If cursor points to an edge tag then increment the
     88   /// cursor and return true otherwise return false.
     89   bool readEdgeTag() {
     90     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
     91     if (Tag.empty() ||
     92 	Tag[0] != '\0' || Tag[1] != '\0' ||
     93 	Tag[2] != '\x43' || Tag[3] != '\x01') {
     94       return false;
     95     }
     96     Cursor += 4;
     97     return true;
     98   }
     99 
    100   /// readLineTag - If cursor points to a line tag then increment the
    101   /// cursor and return true otherwise return false.
    102   bool readLineTag() {
    103     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
    104     if (Tag.empty() ||
    105 	Tag[0] != '\0' || Tag[1] != '\0' ||
    106 	Tag[2] != '\x45' || Tag[3] != '\x01') {
    107       return false;
    108     }
    109     Cursor += 4;
    110     return true;
    111   }
    112 
    113   /// readArcTag - If cursor points to an gcda arc tag then increment the
    114   /// cursor and return true otherwise return false.
    115   bool readArcTag() {
    116     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
    117     if (Tag.empty() ||
    118 	Tag[0] != '\0' || Tag[1] != '\0' ||
    119 	Tag[2] != '\xa1' || Tag[3] != '\1') {
    120       return false;
    121     }
    122     Cursor += 4;
    123     return true;
    124   }
    125 
    126   uint32_t readInt() {
    127     uint32_t Result;
    128     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
    129     assert (Str.empty() == false && "Unexpected memory buffer end!");
    130     Cursor += 4;
    131     Result = *(uint32_t *)(Str.data());
    132     return Result;
    133   }
    134 
    135   uint64_t readInt64() {
    136     uint64_t Lo = readInt();
    137     uint64_t Hi = readInt();
    138     uint64_t Result = Lo | (Hi << 32);
    139     return Result;
    140   }
    141 
    142   StringRef readString() {
    143     uint32_t Len = readInt() * 4;
    144     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
    145     Cursor += Len;
    146     return Str;
    147   }
    148 
    149   uint64_t getCursor() const { return Cursor; }
    150 private:
    151   MemoryBuffer *Buffer;
    152   uint64_t Cursor;
    153 };
    154 
    155 /// GCOVFile - Collects coverage information for one pair of coverage file
    156 /// (.gcno and .gcda).
    157 class GCOVFile {
    158 public:
    159   GCOVFile() {}
    160   ~GCOVFile();
    161   bool read(GCOVBuffer &Buffer);
    162   void dump();
    163   void collectLineCounts(FileInfo &FI);
    164 private:
    165   SmallVector<GCOVFunction *, 16> Functions;
    166 };
    167 
    168 /// GCOVFunction - Collects function information.
    169 class GCOVFunction {
    170 public:
    171   GCOVFunction() : Ident(0), LineNumber(0) {}
    172   ~GCOVFunction();
    173   bool read(GCOVBuffer &Buffer, GCOVFormat Format);
    174   void dump();
    175   void collectLineCounts(FileInfo &FI);
    176 private:
    177   uint32_t Ident;
    178   uint32_t LineNumber;
    179   StringRef Name;
    180   StringRef Filename;
    181   SmallVector<GCOVBlock *, 16> Blocks;
    182 };
    183 
    184 /// GCOVBlock - Collects block information.
    185 class GCOVBlock {
    186 public:
    187   GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
    188   ~GCOVBlock();
    189   void addEdge(uint32_t N) { Edges.push_back(N); }
    190   void addLine(StringRef Filename, uint32_t LineNo);
    191   void addCount(uint64_t N) { Counter = N; }
    192   void dump();
    193   void collectLineCounts(FileInfo &FI);
    194 private:
    195   uint32_t Number;
    196   uint64_t Counter;
    197   SmallVector<uint32_t, 16> Edges;
    198   StringMap<GCOVLines *> Lines;
    199 };
    200 
    201 /// GCOVLines - A wrapper around a vector of int to keep track of line nos.
    202 class GCOVLines {
    203 public:
    204   ~GCOVLines() { Lines.clear(); }
    205   void add(uint32_t N) { Lines.push_back(N); }
    206   void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count);
    207   void dump();
    208 
    209 private:
    210   SmallVector<uint32_t, 4> Lines;
    211 };
    212 
    213 typedef SmallVector<uint32_t, 16> LineCounts;
    214 class FileInfo {
    215 public:
    216   void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
    217   void print();
    218 private:
    219   StringMap<LineCounts> LineInfo;
    220 };
    221 
    222 }
    223 
    224 #endif
    225