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 30namespace 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. 42class GCOVBuffer { 43public: 44 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} 45 46 /// readGCOVFormat - Read GCOV signature at the beginning of buffer. 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. 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. 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. 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. 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. 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 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 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 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 151 uint64_t getCursor() const { return Cursor; } 152private: 153 MemoryBuffer *Buffer; 154 uint64_t Cursor; 155}; 156 157/// GCOVFile - Collects coverage information for one pair of coverage file 158/// (.gcno and .gcda). 159class GCOVFile { 160public: 161 GCOVFile() {} 162 ~GCOVFile(); 163 bool read(GCOVBuffer &Buffer); 164 void dump(); 165 void collectLineCounts(FileInfo &FI); 166private: 167 SmallVector<GCOVFunction *, 16> Functions; 168}; 169 170/// GCOVFunction - Collects function information. 171class GCOVFunction { 172public: 173 GCOVFunction() : Ident(0), LineNumber(0) {} 174 ~GCOVFunction(); 175 bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format); 176 void dump(); 177 void collectLineCounts(FileInfo &FI); 178private: 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. 187class GCOVBlock { 188public: 189 GCOVBlock(uint32_t N) : Number(N), Counter(0) {} 190 ~GCOVBlock(); 191 void addEdge(uint32_t N) { Edges.push_back(N); } 192 void addLine(StringRef Filename, uint32_t LineNo); 193 void addCount(uint64_t N) { Counter = N; } 194 void dump(); 195 void collectLineCounts(FileInfo &FI); 196private: 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. 204class GCOVLines { 205public: 206 ~GCOVLines() { Lines.clear(); } 207 void add(uint32_t N) { Lines.push_back(N); } 208 void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count); 209 void dump(); 210 211private: 212 SmallVector<uint32_t, 4> Lines; 213}; 214 215typedef SmallVector<uint32_t, 16> LineCounts; 216class FileInfo { 217public: 218 void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count); 219 void print(); 220private: 221 StringMap<LineCounts> LineInfo; 222}; 223 224} 225 226#endif 227