|
|
//===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header provides the interface to read and write coverage files that
// use 'gcov' format.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_GCOV_H
#define LLVM_SUPPORT_GCOV_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
class GCOVFunction; class GCOVBlock; class GCOVLines; class FileInfo;
namespace GCOV { enum GCOVFormat { InvalidGCOV, GCNO_402, GCNO_404, GCDA_402, GCDA_404 }; } // end GCOV namespace
/// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
/// read operations.
class GCOVBuffer { public: GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
GCOV::GCOVFormat readGCOVFormat() { StringRef Magic = Buffer->getBuffer().slice(0, 12); Cursor = 12; if (Magic == "oncg*404MVLL") return GCOV::GCNO_404; else if (Magic == "oncg*204MVLL") return GCOV::GCNO_402; else if (Magic == "adcg*404MVLL") return GCOV::GCDA_404; else if (Magic == "adcg*204MVLL") return GCOV::GCDA_402; Cursor = 0; return GCOV::InvalidGCOV; }
/// readFunctionTag - If cursor points to a function tag then increment the
/// cursor and return true otherwise return false.
bool readFunctionTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || Tag[3] != '\1') { return false; } Cursor += 4; return true; }
/// readBlockTag - If cursor points to a block tag then increment the
/// cursor and return true otherwise return false.
bool readBlockTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' || Tag[3] != '\x01') { return false; } Cursor += 4; return true; }
/// readEdgeTag - If cursor points to an edge tag then increment the
/// cursor and return true otherwise return false.
bool readEdgeTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' || Tag[3] != '\x01') { return false; } Cursor += 4; return true; }
/// readLineTag - If cursor points to a line tag then increment the
/// cursor and return true otherwise return false.
bool readLineTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' || Tag[3] != '\x01') { return false; } Cursor += 4; return true; }
/// readArcTag - If cursor points to an gcda arc tag then increment the
/// cursor and return true otherwise return false.
bool readArcTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' || Tag[3] != '\1') { return false; } Cursor += 4; return true; }
uint32_t readInt() { uint32_t Result; StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4); assert (Str.empty() == false && "Unexpected memory buffer end!"); Cursor += 4; Result = *(const uint32_t *)(Str.data()); return Result; }
uint64_t readInt64() { uint64_t Lo = readInt(); uint64_t Hi = readInt(); uint64_t Result = Lo | (Hi << 32); return Result; }
StringRef readString() { uint32_t Len = readInt() * 4; StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len); Cursor += Len; return Str; }
uint64_t getCursor() const { return Cursor; } private: MemoryBuffer *Buffer; uint64_t Cursor; };
/// GCOVFile - Collects coverage information for one pair of coverage file
/// (.gcno and .gcda).
class GCOVFile { public: GCOVFile() {} ~GCOVFile(); bool read(GCOVBuffer &Buffer); void dump(); void collectLineCounts(FileInfo &FI); private: SmallVector<GCOVFunction *, 16> Functions; };
/// GCOVFunction - Collects function information.
class GCOVFunction { public: GCOVFunction() : Ident(0), LineNumber(0) {} ~GCOVFunction(); bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format); void dump(); void collectLineCounts(FileInfo &FI); private: uint32_t Ident; uint32_t LineNumber; StringRef Name; StringRef Filename; SmallVector<GCOVBlock *, 16> Blocks; };
/// GCOVBlock - Collects block information.
class GCOVBlock { public: GCOVBlock(uint32_t N) : Number(N), Counter(0) {} ~GCOVBlock(); void addEdge(uint32_t N) { Edges.push_back(N); } void addLine(StringRef Filename, uint32_t LineNo); void addCount(uint64_t N) { Counter = N; } void dump(); void collectLineCounts(FileInfo &FI); private: uint32_t Number; uint64_t Counter; SmallVector<uint32_t, 16> Edges; StringMap<GCOVLines *> Lines; };
/// GCOVLines - A wrapper around a vector of int to keep track of line nos.
class GCOVLines { public: ~GCOVLines() { Lines.clear(); } void add(uint32_t N) { Lines.push_back(N); } void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count); void dump();
private: SmallVector<uint32_t, 4> Lines; };
typedef SmallVector<uint32_t, 16> LineCounts; class FileInfo { public: void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count); void print(); private: StringMap<LineCounts> LineInfo; };
}
#endif
|