summaryrefslogtreecommitdiff
path: root/tools/llvm-cov/GCOVReader.h
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvm-cov/GCOVReader.h')
-rw-r--r--tools/llvm-cov/GCOVReader.h225
1 files changed, 225 insertions, 0 deletions
diff --git a/tools/llvm-cov/GCOVReader.h b/tools/llvm-cov/GCOVReader.h
new file mode 100644
index 0000000000..5dfc75f152
--- /dev/null
+++ b/tools/llvm-cov/GCOVReader.h
@@ -0,0 +1,225 @@
+//===-- tools/cov/GCOVReader.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 coverage files that use 'gcov'
+// format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GCOVREADER_H
+#define GCOVREADER_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;
+
+enum GCOVFormat {
+ InvalidGCOV,
+ GCNO_402,
+ GCNO_404,
+ GCDA_402,
+ GCDA_404
+};
+
+/// GCOVBuffer - A wrapper around MemoryBuffer to provid GCOV specific
+/// read operations.
+class GCOVBuffer {
+public:
+ GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
+
+ /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
+ enum GCOVFormat readGCOVFormat() {
+ StringRef Magic = Buffer->getBuffer().slice(0, 12);
+ Cursor = 12;
+ if (Magic == "oncg*404MVLL")
+ return GCNO_404;
+ else if (Magic == "oncg*204MVLL")
+ return GCNO_402;
+ else if (Magic == "adcg*404MVLL")
+ return GCDA_404;
+ else if (Magic == "adcg*204MVLL")
+ return GCDA_402;
+
+ Cursor = 0;
+ return 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 = *(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 file information.
+class GCOVFile {
+public:
+ GCOVFile() : Format(InvalidGCOV) {}
+ ~GCOVFile();
+ bool read(GCOVBuffer &Buffer);
+ void dump();
+ void collectLineCounts(FileInfo &FI);
+private:
+ enum GCOVFormat Format;
+ SmallVector<GCOVFunction *, 16> Functions;
+};
+
+/// GCOVFunction - Collects function information.
+class GCOVFunction {
+public:
+ GCOVFunction() : Ident(0), LineNumber(0) {}
+ ~GCOVFunction();
+ bool read(GCOVBuffer &Buffer, 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