1226584Sdim//===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===// 2226584Sdim// 3226584Sdim// The LLVM Compiler Infrastructure 4226584Sdim// 5226584Sdim// This file is distributed under the University of Illinois Open Source 6226584Sdim// License. See LICENSE.TXT for details. 7226584Sdim// 8226584Sdim//===----------------------------------------------------------------------===// 9226584Sdim// 10226584Sdim// This header provides the interface to read and write coverage files that 11226584Sdim// use 'gcov' format. 12226584Sdim// 13226584Sdim//===----------------------------------------------------------------------===// 14226584Sdim 15249423Sdim#ifndef LLVM_SUPPORT_GCOV_H 16249423Sdim#define LLVM_SUPPORT_GCOV_H 17226584Sdim 18226584Sdim#include "llvm/ADT/SmallVector.h" 19226584Sdim#include "llvm/ADT/StringMap.h" 20226584Sdim#include "llvm/Support/MemoryBuffer.h" 21226584Sdim#include "llvm/Support/raw_ostream.h" 22226584Sdim 23226584Sdimnamespace llvm { 24226584Sdim 25226584Sdimclass GCOVFunction; 26226584Sdimclass GCOVBlock; 27226584Sdimclass GCOVLines; 28226584Sdimclass FileInfo; 29226584Sdim 30243830Sdimnamespace GCOV { 31243830Sdim enum GCOVFormat { 32243830Sdim InvalidGCOV, 33243830Sdim GCNO_402, 34243830Sdim GCNO_404, 35243830Sdim GCDA_402, 36243830Sdim GCDA_404 37243830Sdim }; 38243830Sdim} // end GCOV namespace 39226584Sdim 40226584Sdim/// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific 41226584Sdim/// read operations. 42226584Sdimclass GCOVBuffer { 43226584Sdimpublic: 44226584Sdim GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} 45226584Sdim 46226584Sdim /// readGCOVFormat - Read GCOV signature at the beginning of buffer. 47243830Sdim GCOV::GCOVFormat readGCOVFormat() { 48226584Sdim StringRef Magic = Buffer->getBuffer().slice(0, 12); 49226584Sdim Cursor = 12; 50226584Sdim if (Magic == "oncg*404MVLL") 51243830Sdim return GCOV::GCNO_404; 52226584Sdim else if (Magic == "oncg*204MVLL") 53243830Sdim return GCOV::GCNO_402; 54226584Sdim else if (Magic == "adcg*404MVLL") 55243830Sdim return GCOV::GCDA_404; 56226584Sdim else if (Magic == "adcg*204MVLL") 57243830Sdim return GCOV::GCDA_402; 58226584Sdim 59226584Sdim Cursor = 0; 60243830Sdim return GCOV::InvalidGCOV; 61226584Sdim } 62226584Sdim 63226584Sdim /// readFunctionTag - If cursor points to a function tag then increment the 64226584Sdim /// cursor and return true otherwise return false. 65226584Sdim bool readFunctionTag() { 66226584Sdim StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 67226584Sdim if (Tag.empty() || 68239462Sdim Tag[0] != '\0' || Tag[1] != '\0' || 69239462Sdim Tag[2] != '\0' || Tag[3] != '\1') { 70226584Sdim return false; 71226584Sdim } 72226584Sdim Cursor += 4; 73226584Sdim return true; 74226584Sdim } 75226584Sdim 76226584Sdim /// readBlockTag - If cursor points to a block tag then increment the 77226584Sdim /// cursor and return true otherwise return false. 78226584Sdim bool readBlockTag() { 79226584Sdim StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 80226584Sdim if (Tag.empty() || 81239462Sdim Tag[0] != '\0' || Tag[1] != '\0' || 82239462Sdim Tag[2] != '\x41' || Tag[3] != '\x01') { 83226584Sdim return false; 84226584Sdim } 85226584Sdim Cursor += 4; 86226584Sdim return true; 87226584Sdim } 88226584Sdim 89226584Sdim /// readEdgeTag - If cursor points to an edge tag then increment the 90226584Sdim /// cursor and return true otherwise return false. 91226584Sdim bool readEdgeTag() { 92226584Sdim StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 93226584Sdim if (Tag.empty() || 94239462Sdim Tag[0] != '\0' || Tag[1] != '\0' || 95239462Sdim Tag[2] != '\x43' || Tag[3] != '\x01') { 96226584Sdim return false; 97226584Sdim } 98226584Sdim Cursor += 4; 99226584Sdim return true; 100226584Sdim } 101226584Sdim 102226584Sdim /// readLineTag - If cursor points to a line tag then increment the 103226584Sdim /// cursor and return true otherwise return false. 104226584Sdim bool readLineTag() { 105226584Sdim StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 106226584Sdim if (Tag.empty() || 107239462Sdim Tag[0] != '\0' || Tag[1] != '\0' || 108239462Sdim Tag[2] != '\x45' || Tag[3] != '\x01') { 109226584Sdim return false; 110226584Sdim } 111226584Sdim Cursor += 4; 112226584Sdim return true; 113226584Sdim } 114226584Sdim 115226584Sdim /// readArcTag - If cursor points to an gcda arc tag then increment the 116226584Sdim /// cursor and return true otherwise return false. 117226584Sdim bool readArcTag() { 118226584Sdim StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 119226584Sdim if (Tag.empty() || 120239462Sdim Tag[0] != '\0' || Tag[1] != '\0' || 121239462Sdim Tag[2] != '\xa1' || Tag[3] != '\1') { 122226584Sdim return false; 123226584Sdim } 124226584Sdim Cursor += 4; 125226584Sdim return true; 126226584Sdim } 127226584Sdim 128226584Sdim uint32_t readInt() { 129226584Sdim uint32_t Result; 130226584Sdim StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4); 131226584Sdim assert (Str.empty() == false && "Unexpected memory buffer end!"); 132226584Sdim Cursor += 4; 133243830Sdim Result = *(const uint32_t *)(Str.data()); 134226584Sdim return Result; 135226584Sdim } 136226584Sdim 137226584Sdim uint64_t readInt64() { 138226584Sdim uint64_t Lo = readInt(); 139226584Sdim uint64_t Hi = readInt(); 140226584Sdim uint64_t Result = Lo | (Hi << 32); 141226584Sdim return Result; 142226584Sdim } 143226584Sdim 144226584Sdim StringRef readString() { 145226584Sdim uint32_t Len = readInt() * 4; 146226584Sdim StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len); 147226584Sdim Cursor += Len; 148226584Sdim return Str; 149226584Sdim } 150226584Sdim 151226584Sdim uint64_t getCursor() const { return Cursor; } 152226584Sdimprivate: 153226584Sdim MemoryBuffer *Buffer; 154226584Sdim uint64_t Cursor; 155226584Sdim}; 156226584Sdim 157226584Sdim/// GCOVFile - Collects coverage information for one pair of coverage file 158226584Sdim/// (.gcno and .gcda). 159226584Sdimclass GCOVFile { 160226584Sdimpublic: 161226584Sdim GCOVFile() {} 162226584Sdim ~GCOVFile(); 163226584Sdim bool read(GCOVBuffer &Buffer); 164226584Sdim void dump(); 165226584Sdim void collectLineCounts(FileInfo &FI); 166226584Sdimprivate: 167226584Sdim SmallVector<GCOVFunction *, 16> Functions; 168226584Sdim}; 169226584Sdim 170226584Sdim/// GCOVFunction - Collects function information. 171226584Sdimclass GCOVFunction { 172226584Sdimpublic: 173226584Sdim GCOVFunction() : Ident(0), LineNumber(0) {} 174226584Sdim ~GCOVFunction(); 175243830Sdim bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format); 176226584Sdim void dump(); 177226584Sdim void collectLineCounts(FileInfo &FI); 178226584Sdimprivate: 179226584Sdim uint32_t Ident; 180226584Sdim uint32_t LineNumber; 181226584Sdim StringRef Name; 182226584Sdim StringRef Filename; 183226584Sdim SmallVector<GCOVBlock *, 16> Blocks; 184226584Sdim}; 185226584Sdim 186226584Sdim/// GCOVBlock - Collects block information. 187226584Sdimclass GCOVBlock { 188226584Sdimpublic: 189226584Sdim GCOVBlock(uint32_t N) : Number(N), Counter(0) {} 190226584Sdim ~GCOVBlock(); 191226584Sdim void addEdge(uint32_t N) { Edges.push_back(N); } 192226584Sdim void addLine(StringRef Filename, uint32_t LineNo); 193226584Sdim void addCount(uint64_t N) { Counter = N; } 194226584Sdim void dump(); 195226584Sdim void collectLineCounts(FileInfo &FI); 196226584Sdimprivate: 197226584Sdim uint32_t Number; 198226584Sdim uint64_t Counter; 199226584Sdim SmallVector<uint32_t, 16> Edges; 200226584Sdim StringMap<GCOVLines *> Lines; 201226584Sdim}; 202226584Sdim 203226584Sdim/// GCOVLines - A wrapper around a vector of int to keep track of line nos. 204226584Sdimclass GCOVLines { 205226584Sdimpublic: 206226584Sdim ~GCOVLines() { Lines.clear(); } 207226584Sdim void add(uint32_t N) { Lines.push_back(N); } 208226584Sdim void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count); 209226584Sdim void dump(); 210226584Sdim 211226584Sdimprivate: 212226584Sdim SmallVector<uint32_t, 4> Lines; 213226584Sdim}; 214226584Sdim 215226584Sdimtypedef SmallVector<uint32_t, 16> LineCounts; 216226584Sdimclass FileInfo { 217226584Sdimpublic: 218226584Sdim void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count); 219226584Sdim void print(); 220226584Sdimprivate: 221226584Sdim StringMap<LineCounts> LineInfo; 222226584Sdim}; 223226584Sdim 224226584Sdim} 225226584Sdim 226226584Sdim#endif 227