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 23namespace llvm { 24 25class GCOVFunction; 26class GCOVBlock; 27class GCOVLines; 28class FileInfo; 29 30enum 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. 40class GCOVBuffer { 41public: 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; } 150private: 151 MemoryBuffer *Buffer; 152 uint64_t Cursor; 153}; 154 155/// GCOVFile - Collects coverage information for one pair of coverage file 156/// (.gcno and .gcda). 157class GCOVFile { 158public: 159 GCOVFile() {} 160 ~GCOVFile(); 161 bool read(GCOVBuffer &Buffer); 162 void dump(); 163 void collectLineCounts(FileInfo &FI); 164private: 165 SmallVector<GCOVFunction *, 16> Functions; 166}; 167 168/// GCOVFunction - Collects function information. 169class GCOVFunction { 170public: 171 GCOVFunction() : Ident(0), LineNumber(0) {} 172 ~GCOVFunction(); 173 bool read(GCOVBuffer &Buffer, GCOVFormat Format); 174 void dump(); 175 void collectLineCounts(FileInfo &FI); 176private: 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. 185class GCOVBlock { 186public: 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); 194private: 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. 202class GCOVLines { 203public: 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 209private: 210 SmallVector<uint32_t, 4> Lines; 211}; 212 213typedef SmallVector<uint32_t, 16> LineCounts; 214class FileInfo { 215public: 216 void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count); 217 void print(); 218private: 219 StringMap<LineCounts> LineInfo; 220}; 221 222} 223 224#endif 225