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: GCOVBuffer(MemoryBuffer * B)42 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} 43 44 /// readGCOVFormat - Read GCOV signature at the beginning of buffer. readGCOVFormat()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. readFunctionTag()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. readBlockTag()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. readEdgeTag()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. readLineTag()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. readArcTag()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 readInt()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 readInt64()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 readString()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 getCursor()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: GCOVFile()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: GCOVFunction()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: GCOVBlock(uint32_t N)187 GCOVBlock(uint32_t N) : Number(N), Counter(0) {} 188 ~GCOVBlock(); addEdge(uint32_t N)189 void addEdge(uint32_t N) { Edges.push_back(N); } 190 void addLine(StringRef Filename, uint32_t LineNo); addCount(uint64_t N)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: ~GCOVLines()204 ~GCOVLines() { Lines.clear(); } add(uint32_t N)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