LLVM API Documentation
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