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