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