llvm.org GIT mirror llvm / 58c6200
Put GCOVFile and other related interface in a common header so that llvm-cov tool can share it with GCOV writer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141095 91177308-0d34-0410-b5e6-96231b3b80d8 Devang Patel 8 years ago
5 changed file(s) with 506 addition(s) and 506 deletion(s). Raw diff Collapse all Expand all
0 //===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This header provides the interface to read and write coverage files that
10 // use 'gcov' format.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_GCOV_H
15 #define LLVM_GCOV_H
16
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/Support/MemoryBuffer.h"
20 #include "llvm/Support/raw_ostream.h"
21
22 namespace llvm {
23
24 class GCOVFunction;
25 class GCOVBlock;
26 class GCOVLines;
27 class FileInfo;
28
29 enum GCOVFormat {
30 InvalidGCOV,
31 GCNO_402,
32 GCNO_404,
33 GCDA_402,
34 GCDA_404
35 };
36
37 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
38 /// read operations.
39 class GCOVBuffer {
40 public:
41 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
42
43 /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
44 enum GCOVFormat readGCOVFormat() {
45 StringRef Magic = Buffer->getBuffer().slice(0, 12);
46 Cursor = 12;
47 if (Magic == "oncg*404MVLL")
48 return GCNO_404;
49 else if (Magic == "oncg*204MVLL")
50 return GCNO_402;
51 else if (Magic == "adcg*404MVLL")
52 return GCDA_404;
53 else if (Magic == "adcg*204MVLL")
54 return GCDA_402;
55
56 Cursor = 0;
57 return InvalidGCOV;
58 }
59
60 /// readFunctionTag - If cursor points to a function tag then increment the
61 /// cursor and return true otherwise return false.
62 bool readFunctionTag() {
63 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
64 if (Tag.empty() ||
65 Tag[0] != '\0' || Tag[1] != '\0' ||
66 Tag[2] != '\0' || Tag[3] != '\1') {
67 return false;
68 }
69 Cursor += 4;
70 return true;
71 }
72
73 /// readBlockTag - If cursor points to a block tag then increment the
74 /// cursor and return true otherwise return false.
75 bool readBlockTag() {
76 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
77 if (Tag.empty() ||
78 Tag[0] != '\0' || Tag[1] != '\0' ||
79 Tag[2] != '\x41' || Tag[3] != '\x01') {
80 return false;
81 }
82 Cursor += 4;
83 return true;
84 }
85
86 /// readEdgeTag - If cursor points to an edge tag then increment the
87 /// cursor and return true otherwise return false.
88 bool readEdgeTag() {
89 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
90 if (Tag.empty() ||
91 Tag[0] != '\0' || Tag[1] != '\0' ||
92 Tag[2] != '\x43' || Tag[3] != '\x01') {
93 return false;
94 }
95 Cursor += 4;
96 return true;
97 }
98
99 /// readLineTag - If cursor points to a line tag then increment the
100 /// cursor and return true otherwise return false.
101 bool readLineTag() {
102 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
103 if (Tag.empty() ||
104 Tag[0] != '\0' || Tag[1] != '\0' ||
105 Tag[2] != '\x45' || Tag[3] != '\x01') {
106 return false;
107 }
108 Cursor += 4;
109 return true;
110 }
111
112 /// readArcTag - If cursor points to an gcda arc tag then increment the
113 /// cursor and return true otherwise return false.
114 bool readArcTag() {
115 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
116 if (Tag.empty() ||
117 Tag[0] != '\0' || Tag[1] != '\0' ||
118 Tag[2] != '\xa1' || Tag[3] != '\1') {
119 return false;
120 }
121 Cursor += 4;
122 return true;
123 }
124
125 uint32_t readInt() {
126 uint32_t Result;
127 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
128 assert (Str.empty() == false && "Unexpected memory buffer end!");
129 Cursor += 4;
130 Result = *(uint32_t *)(Str.data());
131 return Result;
132 }
133
134 uint64_t readInt64() {
135 uint64_t Lo = readInt();
136 uint64_t Hi = readInt();
137 uint64_t Result = Lo | (Hi << 32);
138 return Result;
139 }
140
141 StringRef readString() {
142 uint32_t Len = readInt() * 4;
143 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
144 Cursor += Len;
145 return Str;
146 }
147
148 uint64_t getCursor() const { return Cursor; }
149 private:
150 MemoryBuffer *Buffer;
151 uint64_t Cursor;
152 };
153
154 /// GCOVFile - Collects coverage information for one pair of coverage file
155 /// (.gcno and .gcda).
156 class GCOVFile {
157 public:
158 GCOVFile() {}
159 ~GCOVFile();
160 bool read(GCOVBuffer &Buffer);
161 void dump();
162 void collectLineCounts(FileInfo &FI);
163 private:
164 SmallVector Functions;
165 };
166
167 /// GCOVFunction - Collects function information.
168 class GCOVFunction {
169 public:
170 GCOVFunction() : Ident(0), LineNumber(0) {}
171 ~GCOVFunction();
172 bool read(GCOVBuffer &Buffer, GCOVFormat Format);
173 void dump();
174 void collectLineCounts(FileInfo &FI);
175 private:
176 uint32_t Ident;
177 uint32_t LineNumber;
178 StringRef Name;
179 StringRef Filename;
180 SmallVector Blocks;
181 };
182
183 /// GCOVBlock - Collects block information.
184 class GCOVBlock {
185 public:
186 GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
187 ~GCOVBlock();
188 void addEdge(uint32_t N) { Edges.push_back(N); }
189 void addLine(StringRef Filename, uint32_t LineNo);
190 void addCount(uint64_t N) { Counter = N; }
191 void dump();
192 void collectLineCounts(FileInfo &FI);
193 private:
194 uint32_t Number;
195 uint64_t Counter;
196 SmallVector Edges;
197 StringMap Lines;
198 };
199
200 /// GCOVLines - A wrapper around a vector of int to keep track of line nos.
201 class GCOVLines {
202 public:
203 ~GCOVLines() { Lines.clear(); }
204 void add(uint32_t N) { Lines.push_back(N); }
205 void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count);
206 void dump();
207
208 private:
209 SmallVector Lines;
210 };
211
212 typedef SmallVector LineCounts;
213 class FileInfo {
214 public:
215 void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
216 void print();
217 private:
218 StringMap LineInfo;
219 };
220
221 }
222
223 #endif
0 //===- GCOVr.cpp - LLVM coverage tool -------------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // GCOV implements the interface to read and write coverage files that use
10 // 'gcov' format.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/GCOV.h"
15 #include "llvm/ADT/OwningPtr.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/Support/MemoryObject.h"
18 #include "llvm/Support/system_error.h"
19 using namespace llvm;
20
21 //===----------------------------------------------------------------------===//
22 // GCOVFile implementation.
23
24 /// ~GCOVFile - Delete GCOVFile and its content.
25 GCOVFile::~GCOVFile() {
26 DeleteContainerPointers(Functions);
27 }
28
29 /// isGCDAFile - Return true if Format identifies a .gcda file.
30 static bool isGCDAFile(GCOVFormat Format) {
31 return Format == GCDA_402 || Format == GCDA_404;
32 }
33
34 /// isGCNOFile - Return true if Format identifies a .gcno file.
35 static bool isGCNOFile(GCOVFormat Format) {
36 return Format == GCNO_402 || Format == GCNO_404;
37 }
38
39 /// read - Read GCOV buffer.
40 bool GCOVFile::read(GCOVBuffer &Buffer) {
41 GCOVFormat Format = Buffer.readGCOVFormat();
42 if (Format == InvalidGCOV)
43 return false;
44
45 unsigned i = 0;
46 while (1) {
47 GCOVFunction *GFun = NULL;
48 if (isGCDAFile(Format)) {
49 // Use existing function while reading .gcda file.
50 assert (i < Functions.size() && ".gcda data does not match .gcno data");
51 GFun = Functions[i];
52 } else if (isGCNOFile(Format)){
53 GFun = new GCOVFunction();
54 Functions.push_back(GFun);
55 }
56 if (!GFun || !GFun->read(Buffer, Format))
57 break;
58 ++i;
59 }
60 return true;
61 }
62
63 /// dump - Dump GCOVFile content on standard out for debugging purposes.
64 void GCOVFile::dump() {
65 for (SmallVector::iterator I = Functions.begin(),
66 E = Functions.end(); I != E; ++I)
67 (*I)->dump();
68 }
69
70 /// collectLineCounts - Collect line counts. This must be used after
71 /// reading .gcno and .gcda files.
72 void GCOVFile::collectLineCounts(FileInfo &FI) {
73 for (SmallVector::iterator I = Functions.begin(),
74 E = Functions.end(); I != E; ++I)
75 (*I)->collectLineCounts(FI);
76 FI.print();
77 }
78
79 //===----------------------------------------------------------------------===//
80 // GCOVFunction implementation.
81
82 /// ~GCOVFunction - Delete GCOVFunction and its content.
83 GCOVFunction::~GCOVFunction() {
84 DeleteContainerPointers(Blocks);
85 }
86
87 /// read - Read a aunction from the buffer. Return false if buffer cursor
88 /// does not point to a function tag.
89 bool GCOVFunction::read(GCOVBuffer &Buff, GCOVFormat Format) {
90 if (!Buff.readFunctionTag())
91 return false;
92
93 Buff.readInt(); // Function header length
94 Ident = Buff.readInt();
95 Buff.readInt(); // Checksum #1
96 if (Format != GCNO_402)
97 Buff.readInt(); // Checksum #2
98
99 Name = Buff.readString();
100 if (Format == GCNO_402 || Format == GCNO_404)
101 Filename = Buff.readString();
102
103 if (Format == GCDA_402 || Format == GCDA_404) {
104 Buff.readArcTag();
105 uint32_t Count = Buff.readInt() / 2;
106 for (unsigned i = 0, e = Count; i != e; ++i) {
107 Blocks[i]->addCount(Buff.readInt64());
108 }
109 return true;;
110 }
111
112 LineNumber = Buff.readInt();
113
114 // read blocks.
115 assert (Buff.readBlockTag() && "Block Tag not found!");
116 uint32_t BlockCount = Buff.readInt();
117 for (int i = 0, e = BlockCount; i != e; ++i) {
118 Buff.readInt(); // Block flags;
119 Blocks.push_back(new GCOVBlock(i));
120 }
121
122 // read edges.
123 while (Buff.readEdgeTag()) {
124 uint32_t EdgeCount = (Buff.readInt() - 1) / 2;
125 uint32_t BlockNo = Buff.readInt();
126 assert (BlockNo < BlockCount && "Unexpected Block number!");
127 for (int i = 0, e = EdgeCount; i != e; ++i) {
128 Blocks[BlockNo]->addEdge(Buff.readInt());
129 Buff.readInt(); // Edge flag
130 }
131 }
132
133 // read line table.
134 while (Buff.readLineTag()) {
135 uint32_t LineTableLength = Buff.readInt();
136 uint32_t Size = Buff.getCursor() + LineTableLength*4;
137 uint32_t BlockNo = Buff.readInt();
138 assert (BlockNo < BlockCount && "Unexpected Block number!");
139 GCOVBlock *Block = Blocks[BlockNo];
140 Buff.readInt(); // flag
141 while (Buff.getCursor() != (Size - 4)) {
142 StringRef Filename = Buff.readString();
143 if (Buff.getCursor() == (Size - 4)) break;
144 while (uint32_t L = Buff.readInt())
145 Block->addLine(Filename, L);
146 }
147 Buff.readInt(); // flag
148 }
149 return true;
150 }
151
152 /// dump - Dump GCOVFunction content on standard out for debugging purposes.
153 void GCOVFunction::dump() {
154 outs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
155 for (SmallVector::iterator I = Blocks.begin(),
156 E = Blocks.end(); I != E; ++I)
157 (*I)->dump();
158 }
159
160 /// collectLineCounts - Collect line counts. This must be used after
161 /// reading .gcno and .gcda files.
162 void GCOVFunction::collectLineCounts(FileInfo &FI) {
163 for (SmallVector::iterator I = Blocks.begin(),
164 E = Blocks.end(); I != E; ++I)
165 (*I)->collectLineCounts(FI);
166 }
167
168 //===----------------------------------------------------------------------===//
169 // GCOVBlock implementation.
170
171 /// ~GCOVBlock - Delete GCOVBlock and its content.
172 GCOVBlock::~GCOVBlock() {
173 Edges.clear();
174 DeleteContainerSeconds(Lines);
175 }
176
177 void GCOVBlock::addLine(StringRef Filename, uint32_t LineNo) {
178 GCOVLines *&LinesForFile = Lines[Filename];
179 if (!LinesForFile)
180 LinesForFile = new GCOVLines();
181 LinesForFile->add(LineNo);
182 }
183
184 /// collectLineCounts - Collect line counts. This must be used after
185 /// reading .gcno and .gcda files.
186 void GCOVBlock::collectLineCounts(FileInfo &FI) {
187 for (StringMap::iterator I = Lines.begin(),
188 E = Lines.end(); I != E; ++I)
189 I->second->collectLineCounts(FI, I->first(), Counter);
190 }
191
192 /// dump - Dump GCOVBlock content on standard out for debugging purposes.
193 void GCOVBlock::dump() {
194 outs() << "Block : " << Number << " Counter : " << Counter << "\n";
195 if (!Edges.empty()) {
196 outs() << "\tEdges : ";
197 for (SmallVector::iterator I = Edges.begin(), E = Edges.end();
198 I != E; ++I)
199 outs() << (*I) << ",";
200 outs() << "\n";
201 }
202 if (!Lines.empty()) {
203 outs() << "\tLines : ";
204 for (StringMap::iterator LI = Lines.begin(),
205 LE = Lines.end(); LI != LE; ++LI) {
206 outs() << LI->first() << " -> ";
207 LI->second->dump();
208 outs() << "\n";
209 }
210 }
211 }
212
213 //===----------------------------------------------------------------------===//
214 // GCOVLines implementation.
215
216 /// collectLineCounts - Collect line counts. This must be used after
217 /// reading .gcno and .gcda files.
218 void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename,
219 uint32_t Count) {
220 for (SmallVector::iterator I = Lines.begin(),
221 E = Lines.end(); I != E; ++I)
222 FI.addLineCount(Filename, *I, Count);
223 }
224
225 /// dump - Dump GCOVLines content on standard out for debugging purposes.
226 void GCOVLines::dump() {
227 for (SmallVector::iterator I = Lines.begin(),
228 E = Lines.end(); I != E; ++I)
229 outs() << (*I) << ",";
230 }
231
232 //===----------------------------------------------------------------------===//
233 // FileInfo implementation.
234
235 /// addLineCount - Add line count for the given line number in a file.
236 void FileInfo::addLineCount(StringRef Filename, uint32_t Line, uint32_t Count) {
237 if (LineInfo.find(Filename) == LineInfo.end()) {
238 OwningPtr Buff;
239 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
240 errs() << Filename << ": " << ec.message() << "\n";
241 return;
242 }
243 StringRef AllLines = Buff.take()->getBuffer();
244 LineCounts L(AllLines.count('\n')+2);
245 L[Line-1] = Count;
246 LineInfo[Filename] = L;
247 return;
248 }
249 LineCounts &L = LineInfo[Filename];
250 L[Line-1] = Count;
251 }
252
253 /// print - Print source files with collected line count information.
254 void FileInfo::print() {
255 for (StringMap::iterator I = LineInfo.begin(), E = LineInfo.end();
256 I != E; ++I) {
257 StringRef Filename = I->first();
258 outs() << Filename << "\n";
259 LineCounts &L = LineInfo[Filename];
260 OwningPtr Buff;
261 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
262 errs() << Filename << ": " << ec.message() << "\n";
263 return;
264 }
265 StringRef AllLines = Buff.take()->getBuffer();
266 for (unsigned i = 0, e = L.size(); i != e; ++i) {
267 if (L[i])
268 outs() << L[i] << ":\t";
269 else
270 outs() << " :\t";
271 std::pair P = AllLines.split('\n');
272 if (AllLines != P.first)
273 outs() << P.first;
274 outs() << "\n";
275 AllLines = P.second;
276 }
277 }
278 }
279
280
+0
-281
tools/llvm-cov/GCOVReader.cpp less more
None //===- tools/llvm-cov/GCOVReader.cpp - LLVM coverage tool -----------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // GCOVReader implements the interface to read coverage files that use 'gcov'
10 // format.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "GCOVReader.h"
15 #include "llvm/ADT/OwningPtr.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/Support/MemoryObject.h"
18 #include "llvm/Support/system_error.h"
19 using namespace llvm;
20
21 //===----------------------------------------------------------------------===//
22 // GCOVFile implementation.
23
24 /// ~GCOVFile - Delete GCOVFile and its content.
25 GCOVFile::~GCOVFile() {
26 DeleteContainerPointers(Functions);
27 }
28
29 /// isGCDAFile - Return true if Format identifies a .gcda file.
30 static bool isGCDAFile(GCOVFormat Format) {
31 return Format == GCDA_402 || Format == GCDA_404;
32 }
33
34 /// isGCNOFile - Return true if Format identifies a .gcno file.
35 static bool isGCNOFile(GCOVFormat Format) {
36 return Format == GCNO_402 || Format == GCNO_404;
37 }
38
39 /// read - Read GCOV buffer.
40 bool GCOVFile::read(GCOVBuffer &Buffer) {
41 GCOVFormat Format = Buffer.readGCOVFormat();
42 if (Format == InvalidGCOV)
43 return false;
44
45 unsigned i = 0;
46 while (1) {
47 GCOVFunction *GFun = NULL;
48 if (isGCDAFile(Format)) {
49 // Use existing function while reading .gcda file.
50 assert (i < Functions.size() && ".gcda data does not match .gcno data");
51 GFun = Functions[i];
52 } else if (isGCNOFile(Format)){
53 GFun = new GCOVFunction();
54 Functions.push_back(GFun);
55 }
56 if (!GFun || !GFun->read(Buffer, Format))
57 break;
58 ++i;
59 }
60 return true;
61 }
62
63 /// dump - Dump GCOVFile content on standard out for debugging purposes.
64 void GCOVFile::dump() {
65 for (SmallVector::iterator I = Functions.begin(),
66 E = Functions.end(); I != E; ++I)
67 (*I)->dump();
68 }
69
70 /// collectLineCounts - Collect line counts. This must be used after
71 /// reading .gcno and .gcda files.
72 void GCOVFile::collectLineCounts(FileInfo &FI) {
73 for (SmallVector::iterator I = Functions.begin(),
74 E = Functions.end(); I != E; ++I)
75 (*I)->collectLineCounts(FI);
76 FI.print();
77 }
78
79 //===----------------------------------------------------------------------===//
80 // GCOVFunction implementation.
81
82 /// ~GCOVFunction - Delete GCOVFunction and its content.
83 GCOVFunction::~GCOVFunction() {
84 DeleteContainerPointers(Blocks);
85 }
86
87 /// read - Read a aunction from the buffer. Return false if buffer cursor
88 /// does not point to a function tag.
89 bool GCOVFunction::read(GCOVBuffer &Buff, GCOVFormat Format) {
90 if (!Buff.readFunctionTag())
91 return false;
92
93 Buff.readInt(); // Function header length
94 Ident = Buff.readInt();
95 Buff.readInt(); // Checksum #1
96 if (Format != GCNO_402)
97 Buff.readInt(); // Checksum #2
98
99 Name = Buff.readString();
100 if (Format == GCNO_402 || Format == GCNO_404)
101 Filename = Buff.readString();
102
103 if (Format == GCDA_402 || Format == GCDA_404) {
104 Buff.readArcTag();
105 uint32_t Count = Buff.readInt() / 2;
106 for (unsigned i = 0, e = Count; i != e; ++i) {
107 Blocks[i]->addCount(Buff.readInt64());
108 }
109 return true;;
110 }
111
112 LineNumber = Buff.readInt();
113
114 // read blocks.
115 assert (Buff.readBlockTag() && "Block Tag not found!");
116 uint32_t BlockCount = Buff.readInt();
117 for (int i = 0, e = BlockCount; i != e; ++i) {
118 Buff.readInt(); // Block flags;
119 Blocks.push_back(new GCOVBlock(i));
120 }
121
122 // read edges.
123 while (Buff.readEdgeTag()) {
124 uint32_t EdgeCount = (Buff.readInt() - 1) / 2;
125 uint32_t BlockNo = Buff.readInt();
126 assert (BlockNo < BlockCount && "Unexpected Block number!");
127 for (int i = 0, e = EdgeCount; i != e; ++i) {
128 Blocks[BlockNo]->addEdge(Buff.readInt());
129 Buff.readInt(); // Edge flag
130 }
131 }
132
133 // read line table.
134 while (Buff.readLineTag()) {
135 uint32_t LineTableLength = Buff.readInt();
136 uint32_t Size = Buff.getCursor() + LineTableLength*4;
137 uint32_t BlockNo = Buff.readInt();
138 assert (BlockNo < BlockCount && "Unexpected Block number!");
139 GCOVBlock *Block = Blocks[BlockNo];
140 Buff.readInt(); // flag
141 while (Buff.getCursor() != (Size - 4)) {
142 StringRef Filename = Buff.readString();
143 if (Buff.getCursor() == (Size - 4)) break;
144 while (uint32_t L = Buff.readInt())
145 Block->addLine(Filename, L);
146 }
147 Buff.readInt(); // flag
148 }
149 return true;
150 }
151
152 /// dump - Dump GCOVFunction content on standard out for debugging purposes.
153 void GCOVFunction::dump() {
154 outs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
155 for (SmallVector::iterator I = Blocks.begin(),
156 E = Blocks.end(); I != E; ++I)
157 (*I)->dump();
158 }
159
160 /// collectLineCounts - Collect line counts. This must be used after
161 /// reading .gcno and .gcda files.
162 void GCOVFunction::collectLineCounts(FileInfo &FI) {
163 for (SmallVector::iterator I = Blocks.begin(),
164 E = Blocks.end(); I != E; ++I)
165 (*I)->collectLineCounts(FI);
166 }
167
168 //===----------------------------------------------------------------------===//
169 // GCOVBlock implementation.
170
171 /// ~GCOVBlock - Delete GCOVBlock and its content.
172 GCOVBlock::~GCOVBlock() {
173 Edges.clear();
174 DeleteContainerSeconds(Lines);
175 }
176
177 void GCOVBlock::addLine(StringRef Filename, uint32_t LineNo) {
178 GCOVLines *&LinesForFile = Lines[Filename];
179 if (!LinesForFile)
180 LinesForFile = new GCOVLines();
181 LinesForFile->add(LineNo);
182 }
183
184 /// collectLineCounts - Collect line counts. This must be used after
185 /// reading .gcno and .gcda files.
186 void GCOVBlock::collectLineCounts(FileInfo &FI) {
187 for (StringMap::iterator I = Lines.begin(),
188 E = Lines.end(); I != E; ++I)
189 I->second->collectLineCounts(FI, I->first(), Counter);
190 }
191
192 /// dump - Dump GCOVBlock content on standard out for debugging purposes.
193 void GCOVBlock::dump() {
194 outs() << "Block : " << Number << " Counter : " << Counter << "\n";
195 if (!Edges.empty()) {
196 outs() << "\tEdges : ";
197 for (SmallVector::iterator I = Edges.begin(), E = Edges.end();
198 I != E; ++I)
199 outs() << (*I) << ",";
200 outs() << "\n";
201 }
202 if (!Lines.empty()) {
203 outs() << "\tLines : ";
204 for (StringMap::iterator LI = Lines.begin(),
205 LE = Lines.end(); LI != LE; ++LI) {
206 outs() << LI->first() << " -> ";
207 LI->second->dump();
208 outs() << "\n";
209 }
210 }
211 }
212
213 //===----------------------------------------------------------------------===//
214 // GCOVLines implementation.
215
216 /// collectLineCounts - Collect line counts. This must be used after
217 /// reading .gcno and .gcda files.
218 void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename,
219 uint32_t Count) {
220 for (SmallVector::iterator I = Lines.begin(),
221 E = Lines.end(); I != E; ++I)
222 FI.addLineCount(Filename, *I, Count);
223 }
224
225 /// dump - Dump GCOVLines content on standard out for debugging purposes.
226 void GCOVLines::dump() {
227 for (SmallVector::iterator I = Lines.begin(),
228 E = Lines.end(); I != E; ++I)
229 outs() << (*I) << ",";
230 }
231
232 //===----------------------------------------------------------------------===//
233 // FileInfo implementation.
234
235 /// addLineCount - Add line count for the given line number in a file.
236 void FileInfo::addLineCount(StringRef Filename, uint32_t Line, uint32_t Count) {
237 if (LineInfo.find(Filename) == LineInfo.end()) {
238 OwningPtr Buff;
239 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
240 errs() << Filename << ": " << ec.message() << "\n";
241 return;
242 }
243 StringRef AllLines = Buff.take()->getBuffer();
244 LineCounts L(AllLines.count('\n')+2);
245 L[Line-1] = Count;
246 LineInfo[Filename] = L;
247 return;
248 }
249 LineCounts &L = LineInfo[Filename];
250 L[Line-1] = Count;
251 }
252
253 /// print - Print source files with collected line count information.
254 void FileInfo::print() {
255 for (StringMap::iterator I = LineInfo.begin(), E = LineInfo.end();
256 I != E; ++I) {
257 StringRef Filename = I->first();
258 outs() << Filename << "\n";
259 LineCounts &L = LineInfo[Filename];
260 OwningPtr Buff;
261 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
262 errs() << Filename << ": " << ec.message() << "\n";
263 return;
264 }
265 StringRef AllLines = Buff.take()->getBuffer();
266 for (unsigned i = 0, e = L.size(); i != e; ++i) {
267 if (L[i])
268 outs() << L[i] << ":\t";
269 else
270 outs() << " :\t";
271 std::pair P = AllLines.split('\n');
272 if (AllLines != P.first)
273 outs() << P.first;
274 outs() << "\n";
275 AllLines = P.second;
276 }
277 }
278 }
279
280
+0
-224
tools/llvm-cov/GCOVReader.h less more
None //===-- tools/llvm-cov/GCOVReader.h - LLVM coverage tool --------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This header provides the interface to read coverage files that use 'gcov'
10 // format.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef GCOVREADER_H
15 #define GCOVREADER_H
16
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/Support/MemoryBuffer.h"
20 #include "llvm/Support/raw_ostream.h"
21
22 namespace llvm {
23
24 class GCOVFunction;
25 class GCOVBlock;
26 class GCOVLines;
27 class FileInfo;
28
29 enum GCOVFormat {
30 InvalidGCOV,
31 GCNO_402,
32 GCNO_404,
33 GCDA_402,
34 GCDA_404
35 };
36
37 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
38 /// read operations.
39 class GCOVBuffer {
40 public:
41 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
42
43 /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
44 enum GCOVFormat readGCOVFormat() {
45 StringRef Magic = Buffer->getBuffer().slice(0, 12);
46 Cursor = 12;
47 if (Magic == "oncg*404MVLL")
48 return GCNO_404;
49 else if (Magic == "oncg*204MVLL")
50 return GCNO_402;
51 else if (Magic == "adcg*404MVLL")
52 return GCDA_404;
53 else if (Magic == "adcg*204MVLL")
54 return GCDA_402;
55
56 Cursor = 0;
57 return InvalidGCOV;
58 }
59
60 /// readFunctionTag - If cursor points to a function tag then increment the
61 /// cursor and return true otherwise return false.
62 bool readFunctionTag() {
63 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
64 if (Tag.empty() ||
65 Tag[0] != '\0' || Tag[1] != '\0' ||
66 Tag[2] != '\0' || Tag[3] != '\1') {
67 return false;
68 }
69 Cursor += 4;
70 return true;
71 }
72
73 /// readBlockTag - If cursor points to a block tag then increment the
74 /// cursor and return true otherwise return false.
75 bool readBlockTag() {
76 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
77 if (Tag.empty() ||
78 Tag[0] != '\0' || Tag[1] != '\0' ||
79 Tag[2] != '\x41' || Tag[3] != '\x01') {
80 return false;
81 }
82 Cursor += 4;
83 return true;
84 }
85
86 /// readEdgeTag - If cursor points to an edge tag then increment the
87 /// cursor and return true otherwise return false.
88 bool readEdgeTag() {
89 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
90 if (Tag.empty() ||
91 Tag[0] != '\0' || Tag[1] != '\0' ||
92 Tag[2] != '\x43' || Tag[3] != '\x01') {
93 return false;
94 }
95 Cursor += 4;
96 return true;
97 }
98
99 /// readLineTag - If cursor points to a line tag then increment the
100 /// cursor and return true otherwise return false.
101 bool readLineTag() {
102 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
103 if (Tag.empty() ||
104 Tag[0] != '\0' || Tag[1] != '\0' ||
105 Tag[2] != '\x45' || Tag[3] != '\x01') {
106 return false;
107 }
108 Cursor += 4;
109 return true;
110 }
111
112 /// readArcTag - If cursor points to an gcda arc tag then increment the
113 /// cursor and return true otherwise return false.
114 bool readArcTag() {
115 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
116 if (Tag.empty() ||
117 Tag[0] != '\0' || Tag[1] != '\0' ||
118 Tag[2] != '\xa1' || Tag[3] != '\1') {
119 return false;
120 }
121 Cursor += 4;
122 return true;
123 }
124
125 uint32_t readInt() {
126 uint32_t Result;
127 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
128 assert (Str.empty() == false && "Unexpected memory buffer end!");
129 Cursor += 4;
130 Result = *(uint32_t *)(Str.data());
131 return Result;
132 }
133
134 uint64_t readInt64() {
135 uint64_t Lo = readInt();
136 uint64_t Hi = readInt();
137 uint64_t Result = Lo | (Hi << 32);
138 return Result;
139 }
140
141 StringRef readString() {
142 uint32_t Len = readInt() * 4;
143 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
144 Cursor += Len;
145 return Str;
146 }
147
148 uint64_t getCursor() const { return Cursor; }
149 private:
150 MemoryBuffer *Buffer;
151 uint64_t Cursor;
152 };
153
154 /// GCOVFile - Collects coverage information for one pair of coverage file
155 /// (.gcno and .gcda).
156 class GCOVFile {
157 public:
158 GCOVFile() {}
159 ~GCOVFile();
160 bool read(GCOVBuffer &Buffer);
161 void dump();
162 void collectLineCounts(FileInfo &FI);
163 private:
164 SmallVector Functions;
165 };
166
167 /// GCOVFunction - Collects function information.
168 class GCOVFunction {
169 public:
170 GCOVFunction() : Ident(0), LineNumber(0) {}
171 ~GCOVFunction();
172 bool read(GCOVBuffer &Buffer, GCOVFormat Format);
173 void dump();
174 void collectLineCounts(FileInfo &FI);
175 private:
176 uint32_t Ident;
177 uint32_t LineNumber;
178 StringRef Name;
179 StringRef Filename;
180 SmallVector Blocks;
181 };
182
183 /// GCOVBlock - Collects block information.
184 class GCOVBlock {
185 public:
186 GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
187 ~GCOVBlock();
188 void addEdge(uint32_t N) { Edges.push_back(N); }
189 void addLine(StringRef Filename, uint32_t LineNo);
190 void addCount(uint64_t N) { Counter = N; }
191 void dump();
192 void collectLineCounts(FileInfo &FI);
193 private:
194 uint32_t Number;
195 uint64_t Counter;
196 SmallVector Edges;
197 StringMap Lines;
198 };
199
200 /// GCOVLines - A wrapper around a vector of int to keep track of line nos.
201 class GCOVLines {
202 public:
203 ~GCOVLines() { Lines.clear(); }
204 void add(uint32_t N) { Lines.push_back(N); }
205 void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count);
206 void dump();
207
208 private:
209 SmallVector Lines;
210 };
211
212 typedef SmallVector LineCounts;
213 class FileInfo {
214 public:
215 void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
216 void print();
217 private:
218 StringMap LineInfo;
219 };
220
221 }
222
223 #endif
1010 //
1111 //===----------------------------------------------------------------------===//
1212
13 #include "GCOVReader.h"
1413 #include "llvm/ADT/OwningPtr.h"
1514 #include "llvm/Support/CommandLine.h"
15 #include "llvm/Support/GCOV.h"
1616 #include "llvm/Support/ManagedStatic.h"
1717 #include "llvm/Support/MemoryObject.h"
1818 #include "llvm/Support/PrettyStackTrace.h"