LLVM API Documentation

GCOV.h
Go to the documentation of this file.
00001 //===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This header provides the interface to read and write coverage files that 
00011 // use 'gcov' format.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_SUPPORT_GCOV_H
00016 #define LLVM_SUPPORT_GCOV_H
00017 
00018 #include "llvm/ADT/SmallVector.h"
00019 #include "llvm/ADT/StringMap.h"
00020 #include "llvm/Support/MemoryBuffer.h"
00021 #include "llvm/Support/raw_ostream.h"
00022 
00023 namespace llvm {
00024 
00025 class GCOVFunction;
00026 class GCOVBlock;
00027 class GCOVLines;
00028 class FileInfo;
00029 
00030 namespace GCOV {
00031   enum GCOVFormat {
00032     InvalidGCOV,
00033     GCNO_402,
00034     GCNO_404,
00035     GCDA_402,
00036     GCDA_404
00037   };
00038 } // end GCOV namespace
00039 
00040 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
00041 /// read operations.
00042 class GCOVBuffer {
00043 public:
00044   GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
00045   
00046   /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
00047   GCOV::GCOVFormat readGCOVFormat() {
00048     StringRef Magic = Buffer->getBuffer().slice(0, 12);
00049     Cursor = 12;
00050     if (Magic == "oncg*404MVLL")
00051       return GCOV::GCNO_404;
00052     else if (Magic == "oncg*204MVLL")
00053       return GCOV::GCNO_402;
00054     else if (Magic == "adcg*404MVLL")
00055       return GCOV::GCDA_404;
00056     else if (Magic == "adcg*204MVLL")
00057       return GCOV::GCDA_402;
00058     
00059     Cursor = 0;
00060     return GCOV::InvalidGCOV;
00061   }
00062 
00063   /// readFunctionTag - If cursor points to a function tag then increment the
00064   /// cursor and return true otherwise return false.
00065   bool readFunctionTag() {
00066     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
00067     if (Tag.empty() || 
00068         Tag[0] != '\0' || Tag[1] != '\0' ||
00069         Tag[2] != '\0' || Tag[3] != '\1') {
00070       return false;
00071     }
00072     Cursor += 4;
00073     return true;
00074   }
00075 
00076   /// readBlockTag - If cursor points to a block tag then increment the
00077   /// cursor and return true otherwise return false.
00078   bool readBlockTag() {
00079     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
00080     if (Tag.empty() || 
00081         Tag[0] != '\0' || Tag[1] != '\0' ||
00082         Tag[2] != '\x41' || Tag[3] != '\x01') {
00083       return false;
00084     }
00085     Cursor += 4;
00086     return true;
00087   }
00088 
00089   /// readEdgeTag - If cursor points to an edge tag then increment the
00090   /// cursor and return true otherwise return false.
00091   bool readEdgeTag() {
00092     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
00093     if (Tag.empty() || 
00094         Tag[0] != '\0' || Tag[1] != '\0' ||
00095         Tag[2] != '\x43' || Tag[3] != '\x01') {
00096       return false;
00097     }
00098     Cursor += 4;
00099     return true;
00100   }
00101 
00102   /// readLineTag - If cursor points to a line tag then increment the
00103   /// cursor and return true otherwise return false.
00104   bool readLineTag() {
00105     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
00106     if (Tag.empty() || 
00107         Tag[0] != '\0' || Tag[1] != '\0' ||
00108         Tag[2] != '\x45' || Tag[3] != '\x01') {
00109       return false;
00110     }
00111     Cursor += 4;
00112     return true;
00113   }
00114 
00115   /// readArcTag - If cursor points to an gcda arc tag then increment the
00116   /// cursor and return true otherwise return false.
00117   bool readArcTag() {
00118     StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
00119     if (Tag.empty() || 
00120         Tag[0] != '\0' || Tag[1] != '\0' ||
00121         Tag[2] != '\xa1' || Tag[3] != '\1') {
00122       return false;
00123     }
00124     Cursor += 4;
00125     return true;
00126   }
00127 
00128   uint32_t readInt() {
00129     uint32_t Result;
00130     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
00131     assert (Str.empty() == false && "Unexpected memory buffer end!");
00132     Cursor += 4;
00133     Result = *(const uint32_t *)(Str.data());
00134     return Result;
00135   }
00136 
00137   uint64_t readInt64() {
00138     uint64_t Lo = readInt();
00139     uint64_t Hi = readInt();
00140     uint64_t Result = Lo | (Hi << 32);
00141     return Result;
00142   }
00143 
00144   StringRef readString() {
00145     uint32_t Len = readInt() * 4;
00146     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
00147     Cursor += Len;
00148     return Str;
00149   }
00150 
00151   uint64_t getCursor() const { return Cursor; }
00152 private:
00153   MemoryBuffer *Buffer;
00154   uint64_t Cursor;
00155 };
00156 
00157 /// GCOVFile - Collects coverage information for one pair of coverage file
00158 /// (.gcno and .gcda).
00159 class GCOVFile {
00160 public:
00161   GCOVFile() {}
00162   ~GCOVFile();
00163   bool read(GCOVBuffer &Buffer);
00164   void dump();
00165   void collectLineCounts(FileInfo &FI);
00166 private:
00167   SmallVector<GCOVFunction *, 16> Functions;
00168 };
00169 
00170 /// GCOVFunction - Collects function information.
00171 class GCOVFunction {
00172 public:
00173   GCOVFunction() : Ident(0), LineNumber(0) {}
00174   ~GCOVFunction();
00175   bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format);
00176   void dump();
00177   void collectLineCounts(FileInfo &FI);
00178 private:
00179   uint32_t Ident;
00180   uint32_t LineNumber;
00181   StringRef Name;
00182   StringRef Filename;
00183   SmallVector<GCOVBlock *, 16> Blocks;
00184 };
00185 
00186 /// GCOVBlock - Collects block information.
00187 class GCOVBlock {
00188 public:
00189   GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
00190   ~GCOVBlock();
00191   void addEdge(uint32_t N) { Edges.push_back(N); }
00192   void addLine(StringRef Filename, uint32_t LineNo);
00193   void addCount(uint64_t N) { Counter = N; }
00194   void dump();
00195   void collectLineCounts(FileInfo &FI);
00196 private:
00197   uint32_t Number;
00198   uint64_t Counter;
00199   SmallVector<uint32_t, 16> Edges;
00200   StringMap<GCOVLines *> Lines;
00201 };
00202 
00203 /// GCOVLines - A wrapper around a vector of int to keep track of line nos.
00204 class GCOVLines {
00205 public:
00206   ~GCOVLines() { Lines.clear(); }
00207   void add(uint32_t N) { Lines.push_back(N); }
00208   void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count);
00209   void dump();
00210 
00211 private:
00212   SmallVector<uint32_t, 4> Lines;
00213 };
00214 
00215 typedef SmallVector<uint32_t, 16> LineCounts;
00216 class FileInfo {
00217 public:
00218   void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
00219   void print();
00220 private:
00221   StringMap<LineCounts> LineInfo;
00222 };
00223 
00224 }
00225 
00226 #endif