llvm.org GIT mirror llvm / 7711c31
GCOV: Move GCOV from IR & Support into ProfileData to fix layering This class was split between libIR and libSupport, which breaks under modular code generation. Move it into the one library that uses it, ProfileData, to resolve this issue. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317366 91177308-0d34-0410-b5e6-96231b3b80d8 David Blaikie 1 year, 11 months ago
8 changed file(s) with 1284 addition(s) and 1284 deletion(s). Raw diff Collapse all Expand all
0 //===- 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_PROFILEDATA_GCOV_H
15 #define LLVM_PROFILEDATA_GCOV_H
16
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/MapVector.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/iterator.h"
23 #include "llvm/ADT/iterator_range.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include
27 #include
28 #include
29 #include
30 #include
31 #include
32
33 namespace llvm {
34
35 class GCOVFunction;
36 class GCOVBlock;
37 class FileInfo;
38
39 namespace GCOV {
40
41 enum GCOVVersion { V402, V404, V704 };
42
43 /// \brief A struct for passing gcov options between functions.
44 struct Options {
45 Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
46 : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
47 PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {}
48
49 bool AllBlocks;
50 bool BranchInfo;
51 bool BranchCount;
52 bool FuncCoverage;
53 bool PreservePaths;
54 bool UncondBranch;
55 bool LongFileNames;
56 bool NoOutput;
57 };
58
59 } // end namespace GCOV
60
61 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
62 /// read operations.
63 class GCOVBuffer {
64 public:
65 GCOVBuffer(MemoryBuffer *B) : Buffer(B) {}
66
67 /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
68 bool readGCNOFormat() {
69 StringRef File = Buffer->getBuffer().slice(0, 4);
70 if (File != "oncg") {
71 errs() << "Unexpected file type: " << File << ".\n";
72 return false;
73 }
74 Cursor = 4;
75 return true;
76 }
77
78 /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
79 bool readGCDAFormat() {
80 StringRef File = Buffer->getBuffer().slice(0, 4);
81 if (File != "adcg") {
82 errs() << "Unexpected file type: " << File << ".\n";
83 return false;
84 }
85 Cursor = 4;
86 return true;
87 }
88
89 /// readGCOVVersion - Read GCOV version.
90 bool readGCOVVersion(GCOV::GCOVVersion &Version) {
91 StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4);
92 if (VersionStr == "*204") {
93 Cursor += 4;
94 Version = GCOV::V402;
95 return true;
96 }
97 if (VersionStr == "*404") {
98 Cursor += 4;
99 Version = GCOV::V404;
100 return true;
101 }
102 if (VersionStr == "*704") {
103 Cursor += 4;
104 Version = GCOV::V704;
105 return true;
106 }
107 errs() << "Unexpected version: " << VersionStr << ".\n";
108 return false;
109 }
110
111 /// readFunctionTag - If cursor points to a function tag then increment the
112 /// cursor and return true otherwise return false.
113 bool readFunctionTag() {
114 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
115 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
116 Tag[3] != '\1') {
117 return false;
118 }
119 Cursor += 4;
120 return true;
121 }
122
123 /// readBlockTag - If cursor points to a block tag then increment the
124 /// cursor and return true otherwise return false.
125 bool readBlockTag() {
126 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
127 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
128 Tag[3] != '\x01') {
129 return false;
130 }
131 Cursor += 4;
132 return true;
133 }
134
135 /// readEdgeTag - If cursor points to an edge tag then increment the
136 /// cursor and return true otherwise return false.
137 bool readEdgeTag() {
138 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
139 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
140 Tag[3] != '\x01') {
141 return false;
142 }
143 Cursor += 4;
144 return true;
145 }
146
147 /// readLineTag - If cursor points to a line tag then increment the
148 /// cursor and return true otherwise return false.
149 bool readLineTag() {
150 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
151 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
152 Tag[3] != '\x01') {
153 return false;
154 }
155 Cursor += 4;
156 return true;
157 }
158
159 /// readArcTag - If cursor points to an gcda arc tag then increment the
160 /// cursor and return true otherwise return false.
161 bool readArcTag() {
162 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
163 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
164 Tag[3] != '\1') {
165 return false;
166 }
167 Cursor += 4;
168 return true;
169 }
170
171 /// readObjectTag - If cursor points to an object summary tag then increment
172 /// the cursor and return true otherwise return false.
173 bool readObjectTag() {
174 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
175 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
176 Tag[3] != '\xa1') {
177 return false;
178 }
179 Cursor += 4;
180 return true;
181 }
182
183 /// readProgramTag - If cursor points to a program summary tag then increment
184 /// the cursor and return true otherwise return false.
185 bool readProgramTag() {
186 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
187 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
188 Tag[3] != '\xa3') {
189 return false;
190 }
191 Cursor += 4;
192 return true;
193 }
194
195 bool readInt(uint32_t &Val) {
196 if (Buffer->getBuffer().size() < Cursor + 4) {
197 errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
198 return false;
199 }
200 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
201 Cursor += 4;
202 Val = *(const uint32_t *)(Str.data());
203 return true;
204 }
205
206 bool readInt64(uint64_t &Val) {
207 uint32_t Lo, Hi;
208 if (!readInt(Lo) || !readInt(Hi))
209 return false;
210 Val = ((uint64_t)Hi << 32) | Lo;
211 return true;
212 }
213
214 bool readString(StringRef &Str) {
215 uint32_t Len = 0;
216 // Keep reading until we find a non-zero length. This emulates gcov's
217 // behaviour, which appears to do the same.
218 while (Len == 0)
219 if (!readInt(Len))
220 return false;
221 Len *= 4;
222 if (Buffer->getBuffer().size() < Cursor + Len) {
223 errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
224 return false;
225 }
226 Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
227 Cursor += Len;
228 return true;
229 }
230
231 uint64_t getCursor() const { return Cursor; }
232 void advanceCursor(uint32_t n) { Cursor += n * 4; }
233
234 private:
235 MemoryBuffer *Buffer;
236 uint64_t Cursor = 0;
237 };
238
239 /// GCOVFile - Collects coverage information for one pair of coverage file
240 /// (.gcno and .gcda).
241 class GCOVFile {
242 public:
243 GCOVFile() = default;
244
245 bool readGCNO(GCOVBuffer &Buffer);
246 bool readGCDA(GCOVBuffer &Buffer);
247 uint32_t getChecksum() const { return Checksum; }
248 void print(raw_ostream &OS) const;
249 void dump() const;
250 void collectLineCounts(FileInfo &FI);
251
252 private:
253 bool GCNOInitialized = false;
254 GCOV::GCOVVersion Version;
255 uint32_t Checksum = 0;
256 SmallVector, 16> Functions;
257 uint32_t RunCount = 0;
258 uint32_t ProgramCount = 0;
259 };
260
261 /// GCOVEdge - Collects edge information.
262 struct GCOVEdge {
263 GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D) {}
264
265 GCOVBlock &Src;
266 GCOVBlock &Dst;
267 uint64_t Count = 0;
268 };
269
270 /// GCOVFunction - Collects function information.
271 class GCOVFunction {
272 public:
273 using BlockIterator = pointee_iterator
274 std::unique_ptr>::const_iterator>;
275
276 GCOVFunction(GCOVFile &P) : Parent(P) {}
277
278 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
279 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
280 StringRef getName() const { return Name; }
281 StringRef getFilename() const { return Filename; }
282 size_t getNumBlocks() const { return Blocks.size(); }
283 uint64_t getEntryCount() const;
284 uint64_t getExitCount() const;
285
286 BlockIterator block_begin() const { return Blocks.begin(); }
287 BlockIterator block_end() const { return Blocks.end(); }
288 iterator_range blocks() const {
289 return make_range(block_begin(), block_end());
290 }
291
292 void print(raw_ostream &OS) const;
293 void dump() const;
294 void collectLineCounts(FileInfo &FI);
295
296 private:
297 GCOVFile &Parent;
298 uint32_t Ident = 0;
299 uint32_t Checksum;
300 uint32_t LineNumber = 0;
301 StringRef Name;
302 StringRef Filename;
303 SmallVector, 16> Blocks;
304 SmallVector, 16> Edges;
305 };
306
307 /// GCOVBlock - Collects block information.
308 class GCOVBlock {
309 struct EdgeWeight {
310 EdgeWeight(GCOVBlock *D) : Dst(D) {}
311
312 GCOVBlock *Dst;
313 uint64_t Count = 0;
314 };
315
316 struct SortDstEdgesFunctor {
317 bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
318 return E1->Dst.Number < E2->Dst.Number;
319 }
320 };
321
322 public:
323 using EdgeIterator = SmallVectorImpl::const_iterator;
324
325 GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N) {}
326 ~GCOVBlock();
327
328 const GCOVFunction &getParent() const { return Parent; }
329 void addLine(uint32_t N) { Lines.push_back(N); }
330 uint32_t getLastLine() const { return Lines.back(); }
331 void addCount(size_t DstEdgeNo, uint64_t N);
332 uint64_t getCount() const { return Counter; }
333
334 void addSrcEdge(GCOVEdge *Edge) {
335 assert(&Edge->Dst == this); // up to caller to ensure edge is valid
336 SrcEdges.push_back(Edge);
337 }
338
339 void addDstEdge(GCOVEdge *Edge) {
340 assert(&Edge->Src == this); // up to caller to ensure edge is valid
341 // Check if adding this edge causes list to become unsorted.
342 if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
343 DstEdgesAreSorted = false;
344 DstEdges.push_back(Edge);
345 }
346
347 size_t getNumSrcEdges() const { return SrcEdges.size(); }
348 size_t getNumDstEdges() const { return DstEdges.size(); }
349 void sortDstEdges();
350
351 EdgeIterator src_begin() const { return SrcEdges.begin(); }
352 EdgeIterator src_end() const { return SrcEdges.end(); }
353 iterator_range srcs() const {
354 return make_range(src_begin(), src_end());
355 }
356
357 EdgeIterator dst_begin() const { return DstEdges.begin(); }
358 EdgeIterator dst_end() const { return DstEdges.end(); }
359 iterator_range dsts() const {
360 return make_range(dst_begin(), dst_end());
361 }
362
363 void print(raw_ostream &OS) const;
364 void dump() const;
365 void collectLineCounts(FileInfo &FI);
366
367 private:
368 GCOVFunction &Parent;
369 uint32_t Number;
370 uint64_t Counter = 0;
371 bool DstEdgesAreSorted = true;
372 SmallVector SrcEdges;
373 SmallVector DstEdges;
374 SmallVector Lines;
375 };
376
377 class FileInfo {
378 // It is unlikely--but possible--for multiple functions to be on the same
379 // line.
380 // Therefore this typedef allows LineData.Functions to store multiple
381 // functions
382 // per instance. This is rare, however, so optimize for the common case.
383 using FunctionVector = SmallVector;
384 using FunctionLines = DenseMap;
385 using BlockVector = SmallVector;
386 using BlockLines = DenseMap;
387
388 struct LineData {
389 LineData() = default;
390
391 BlockLines Blocks;
392 FunctionLines Functions;
393 uint32_t LastLine = 0;
394 };
395
396 struct GCOVCoverage {
397 GCOVCoverage(StringRef Name) : Name(Name) {}
398
399 StringRef Name;
400
401 uint32_t LogicalLines = 0;
402 uint32_t LinesExec = 0;
403
404 uint32_t Branches = 0;
405 uint32_t BranchesExec = 0;
406 uint32_t BranchesTaken = 0;
407 };
408
409 public:
410 FileInfo(const GCOV::Options &Options) : Options(Options) {}
411
412 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
413 if (Line > LineInfo[Filename].LastLine)
414 LineInfo[Filename].LastLine = Line;
415 LineInfo[Filename].Blocks[Line - 1].push_back(Block);
416 }
417
418 void addFunctionLine(StringRef Filename, uint32_t Line,
419 const GCOVFunction *Function) {
420 if (Line > LineInfo[Filename].LastLine)
421 LineInfo[Filename].LastLine = Line;
422 LineInfo[Filename].Functions[Line - 1].push_back(Function);
423 }
424
425 void setRunCount(uint32_t Runs) { RunCount = Runs; }
426 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
427 void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
428 StringRef GCDAFile);
429
430 private:
431 std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
432 std::unique_ptr openCoveragePath(StringRef CoveragePath);
433 void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
434 void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
435 uint32_t LineIndex, uint32_t &BlockNo) const;
436 void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
437 GCOVCoverage &Coverage, uint32_t &EdgeNo);
438 void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
439 uint64_t Count) const;
440
441 void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
442 void printFuncCoverage(raw_ostream &OS) const;
443 void printFileCoverage(raw_ostream &OS) const;
444
445 const GCOV::Options &Options;
446 StringMap LineInfo;
447 uint32_t RunCount = 0;
448 uint32_t ProgramCount = 0;
449
450 using FileCoverageList = SmallVector, 4>;
451 using FuncCoverageMap = MapVector;
452
453 FileCoverageList FileCoverages;
454 FuncCoverageMap FuncCoverages;
455 };
456
457 } // end namespace llvm
458
459 #endif // LLVM_SUPPORT_GCOV_H
216216 #include "llvm/IR/Function.h"
217217 #include "llvm/IR/LLVMContext.h"
218218 #include "llvm/IR/ProfileSummary.h"
219 #include "llvm/ProfileData/GCOV.h"
219220 #include "llvm/ProfileData/SampleProf.h"
220221 #include "llvm/Support/Debug.h"
221222 #include "llvm/Support/ErrorOr.h"
222 #include "llvm/Support/GCOV.h"
223223 #include "llvm/Support/MemoryBuffer.h"
224224 #include
225225 #include
+0
-460
include/llvm/Support/GCOV.h less more
None //===- 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_SUPPORT_GCOV_H
15 #define LLVM_SUPPORT_GCOV_H
16
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/MapVector.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/iterator.h"
23 #include "llvm/ADT/iterator_range.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include
27 #include
28 #include
29 #include
30 #include
31 #include
32
33 namespace llvm {
34
35 class GCOVFunction;
36 class GCOVBlock;
37 class FileInfo;
38
39 namespace GCOV {
40
41 enum GCOVVersion { V402, V404, V704 };
42
43 /// \brief A struct for passing gcov options between functions.
44 struct Options {
45 Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
46 : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
47 PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {}
48
49 bool AllBlocks;
50 bool BranchInfo;
51 bool BranchCount;
52 bool FuncCoverage;
53 bool PreservePaths;
54 bool UncondBranch;
55 bool LongFileNames;
56 bool NoOutput;
57 };
58
59 } // end namespace GCOV
60
61 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
62 /// read operations.
63 class GCOVBuffer {
64 public:
65 GCOVBuffer(MemoryBuffer *B) : Buffer(B) {}
66
67 /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
68 bool readGCNOFormat() {
69 StringRef File = Buffer->getBuffer().slice(0, 4);
70 if (File != "oncg") {
71 errs() << "Unexpected file type: " << File << ".\n";
72 return false;
73 }
74 Cursor = 4;
75 return true;
76 }
77
78 /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
79 bool readGCDAFormat() {
80 StringRef File = Buffer->getBuffer().slice(0, 4);
81 if (File != "adcg") {
82 errs() << "Unexpected file type: " << File << ".\n";
83 return false;
84 }
85 Cursor = 4;
86 return true;
87 }
88
89 /// readGCOVVersion - Read GCOV version.
90 bool readGCOVVersion(GCOV::GCOVVersion &Version) {
91 StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4);
92 if (VersionStr == "*204") {
93 Cursor += 4;
94 Version = GCOV::V402;
95 return true;
96 }
97 if (VersionStr == "*404") {
98 Cursor += 4;
99 Version = GCOV::V404;
100 return true;
101 }
102 if (VersionStr == "*704") {
103 Cursor += 4;
104 Version = GCOV::V704;
105 return true;
106 }
107 errs() << "Unexpected version: " << VersionStr << ".\n";
108 return false;
109 }
110
111 /// readFunctionTag - If cursor points to a function tag then increment the
112 /// cursor and return true otherwise return false.
113 bool readFunctionTag() {
114 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
115 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
116 Tag[3] != '\1') {
117 return false;
118 }
119 Cursor += 4;
120 return true;
121 }
122
123 /// readBlockTag - If cursor points to a block tag then increment the
124 /// cursor and return true otherwise return false.
125 bool readBlockTag() {
126 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
127 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
128 Tag[3] != '\x01') {
129 return false;
130 }
131 Cursor += 4;
132 return true;
133 }
134
135 /// readEdgeTag - If cursor points to an edge tag then increment the
136 /// cursor and return true otherwise return false.
137 bool readEdgeTag() {
138 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
139 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
140 Tag[3] != '\x01') {
141 return false;
142 }
143 Cursor += 4;
144 return true;
145 }
146
147 /// readLineTag - If cursor points to a line tag then increment the
148 /// cursor and return true otherwise return false.
149 bool readLineTag() {
150 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
151 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
152 Tag[3] != '\x01') {
153 return false;
154 }
155 Cursor += 4;
156 return true;
157 }
158
159 /// readArcTag - If cursor points to an gcda arc tag then increment the
160 /// cursor and return true otherwise return false.
161 bool readArcTag() {
162 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
163 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
164 Tag[3] != '\1') {
165 return false;
166 }
167 Cursor += 4;
168 return true;
169 }
170
171 /// readObjectTag - If cursor points to an object summary tag then increment
172 /// the cursor and return true otherwise return false.
173 bool readObjectTag() {
174 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
175 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
176 Tag[3] != '\xa1') {
177 return false;
178 }
179 Cursor += 4;
180 return true;
181 }
182
183 /// readProgramTag - If cursor points to a program summary tag then increment
184 /// the cursor and return true otherwise return false.
185 bool readProgramTag() {
186 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
187 if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
188 Tag[3] != '\xa3') {
189 return false;
190 }
191 Cursor += 4;
192 return true;
193 }
194
195 bool readInt(uint32_t &Val) {
196 if (Buffer->getBuffer().size() < Cursor + 4) {
197 errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
198 return false;
199 }
200 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
201 Cursor += 4;
202 Val = *(const uint32_t *)(Str.data());
203 return true;
204 }
205
206 bool readInt64(uint64_t &Val) {
207 uint32_t Lo, Hi;
208 if (!readInt(Lo) || !readInt(Hi))
209 return false;
210 Val = ((uint64_t)Hi << 32) | Lo;
211 return true;
212 }
213
214 bool readString(StringRef &Str) {
215 uint32_t Len = 0;
216 // Keep reading until we find a non-zero length. This emulates gcov's
217 // behaviour, which appears to do the same.
218 while (Len == 0)
219 if (!readInt(Len))
220 return false;
221 Len *= 4;
222 if (Buffer->getBuffer().size() < Cursor + Len) {
223 errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
224 return false;
225 }
226 Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
227 Cursor += Len;
228 return true;
229 }
230
231 uint64_t getCursor() const { return Cursor; }
232 void advanceCursor(uint32_t n) { Cursor += n * 4; }
233
234 private:
235 MemoryBuffer *Buffer;
236 uint64_t Cursor = 0;
237 };
238
239 /// GCOVFile - Collects coverage information for one pair of coverage file
240 /// (.gcno and .gcda).
241 class GCOVFile {
242 public:
243 GCOVFile() = default;
244
245 bool readGCNO(GCOVBuffer &Buffer);
246 bool readGCDA(GCOVBuffer &Buffer);
247 uint32_t getChecksum() const { return Checksum; }
248 void print(raw_ostream &OS) const;
249 void dump() const;
250 void collectLineCounts(FileInfo &FI);
251
252 private:
253 bool GCNOInitialized = false;
254 GCOV::GCOVVersion Version;
255 uint32_t Checksum = 0;
256 SmallVector, 16> Functions;
257 uint32_t RunCount = 0;
258 uint32_t ProgramCount = 0;
259 };
260
261 /// GCOVEdge - Collects edge information.
262 struct GCOVEdge {
263 GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D) {}
264
265 GCOVBlock &Src;
266 GCOVBlock &Dst;
267 uint64_t Count = 0;
268 };
269
270 /// GCOVFunction - Collects function information.
271 class GCOVFunction {
272 public:
273 using BlockIterator = pointee_iterator
274 std::unique_ptr>::const_iterator>;
275
276 GCOVFunction(GCOVFile &P) : Parent(P) {}
277
278 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
279 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
280 StringRef getName() const { return Name; }
281 StringRef getFilename() const { return Filename; }
282 size_t getNumBlocks() const { return Blocks.size(); }
283 uint64_t getEntryCount() const;
284 uint64_t getExitCount() const;
285
286 BlockIterator block_begin() const { return Blocks.begin(); }
287 BlockIterator block_end() const { return Blocks.end(); }
288 iterator_range blocks() const {
289 return make_range(block_begin(), block_end());
290 }
291
292 void print(raw_ostream &OS) const;
293 void dump() const;
294 void collectLineCounts(FileInfo &FI);
295
296 private:
297 GCOVFile &Parent;
298 uint32_t Ident = 0;
299 uint32_t Checksum;
300 uint32_t LineNumber = 0;
301 StringRef Name;
302 StringRef Filename;
303 SmallVector, 16> Blocks;
304 SmallVector, 16> Edges;
305 };
306
307 /// GCOVBlock - Collects block information.
308 class GCOVBlock {
309 struct EdgeWeight {
310 EdgeWeight(GCOVBlock *D) : Dst(D) {}
311
312 GCOVBlock *Dst;
313 uint64_t Count = 0;
314 };
315
316 struct SortDstEdgesFunctor {
317 bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
318 return E1->Dst.Number < E2->Dst.Number;
319 }
320 };
321
322 public:
323 using EdgeIterator = SmallVectorImpl::const_iterator;
324
325 GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N) {}
326 ~GCOVBlock();
327
328 const GCOVFunction &getParent() const { return Parent; }
329 void addLine(uint32_t N) { Lines.push_back(N); }
330 uint32_t getLastLine() const { return Lines.back(); }
331 void addCount(size_t DstEdgeNo, uint64_t N);
332 uint64_t getCount() const { return Counter; }
333
334 void addSrcEdge(GCOVEdge *Edge) {
335 assert(&Edge->Dst == this); // up to caller to ensure edge is valid
336 SrcEdges.push_back(Edge);
337 }
338
339 void addDstEdge(GCOVEdge *Edge) {
340 assert(&Edge->Src == this); // up to caller to ensure edge is valid
341 // Check if adding this edge causes list to become unsorted.
342 if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
343 DstEdgesAreSorted = false;
344 DstEdges.push_back(Edge);
345 }
346
347 size_t getNumSrcEdges() const { return SrcEdges.size(); }
348 size_t getNumDstEdges() const { return DstEdges.size(); }
349 void sortDstEdges();
350
351 EdgeIterator src_begin() const { return SrcEdges.begin(); }
352 EdgeIterator src_end() const { return SrcEdges.end(); }
353 iterator_range srcs() const {
354 return make_range(src_begin(), src_end());
355 }
356
357 EdgeIterator dst_begin() const { return DstEdges.begin(); }
358 EdgeIterator dst_end() const { return DstEdges.end(); }
359 iterator_range dsts() const {
360 return make_range(dst_begin(), dst_end());
361 }
362
363 void print(raw_ostream &OS) const;
364 void dump() const;
365 void collectLineCounts(FileInfo &FI);
366
367 private:
368 GCOVFunction &Parent;
369 uint32_t Number;
370 uint64_t Counter = 0;
371 bool DstEdgesAreSorted = true;
372 SmallVector SrcEdges;
373 SmallVector DstEdges;
374 SmallVector Lines;
375 };
376
377 class FileInfo {
378 // It is unlikely--but possible--for multiple functions to be on the same
379 // line.
380 // Therefore this typedef allows LineData.Functions to store multiple
381 // functions
382 // per instance. This is rare, however, so optimize for the common case.
383 using FunctionVector = SmallVector;
384 using FunctionLines = DenseMap;
385 using BlockVector = SmallVector;
386 using BlockLines = DenseMap;
387
388 struct LineData {
389 LineData() = default;
390
391 BlockLines Blocks;
392 FunctionLines Functions;
393 uint32_t LastLine = 0;
394 };
395
396 struct GCOVCoverage {
397 GCOVCoverage(StringRef Name) : Name(Name) {}
398
399 StringRef Name;
400
401 uint32_t LogicalLines = 0;
402 uint32_t LinesExec = 0;
403
404 uint32_t Branches = 0;
405 uint32_t BranchesExec = 0;
406 uint32_t BranchesTaken = 0;
407 };
408
409 public:
410 FileInfo(const GCOV::Options &Options) : Options(Options) {}
411
412 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
413 if (Line > LineInfo[Filename].LastLine)
414 LineInfo[Filename].LastLine = Line;
415 LineInfo[Filename].Blocks[Line - 1].push_back(Block);
416 }
417
418 void addFunctionLine(StringRef Filename, uint32_t Line,
419 const GCOVFunction *Function) {
420 if (Line > LineInfo[Filename].LastLine)
421 LineInfo[Filename].LastLine = Line;
422 LineInfo[Filename].Functions[Line - 1].push_back(Function);
423 }
424
425 void setRunCount(uint32_t Runs) { RunCount = Runs; }
426 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
427 void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
428 StringRef GCDAFile);
429
430 private:
431 std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
432 std::unique_ptr openCoveragePath(StringRef CoveragePath);
433 void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
434 void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
435 uint32_t LineIndex, uint32_t &BlockNo) const;
436 void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
437 GCOVCoverage &Coverage, uint32_t &EdgeNo);
438 void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
439 uint64_t Count) const;
440
441 void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
442 void printFuncCoverage(raw_ostream &OS) const;
443 void printFileCoverage(raw_ostream &OS) const;
444
445 const GCOV::Options &Options;
446 StringMap LineInfo;
447 uint32_t RunCount = 0;
448 uint32_t ProgramCount = 0;
449
450 using FileCoverageList = SmallVector, 4>;
451 using FuncCoverageMap = MapVector;
452
453 FileCoverageList FileCoverages;
454 FuncCoverageMap FuncCoverages;
455 };
456
457 } // end namespace llvm
458
459 #endif // LLVM_SUPPORT_GCOV_H
2121 DiagnosticPrinter.cpp
2222 Dominators.cpp
2323 Function.cpp
24 GCOV.cpp
2524 GVMaterializer.cpp
2625 Globals.cpp
2726 IRBuilder.cpp
+0
-821
lib/IR/GCOV.cpp less more
None //===- GCOV.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/STLExtras.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/FileSystem.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include
22 #include
23
24 using namespace llvm;
25
26 //===----------------------------------------------------------------------===//
27 // GCOVFile implementation.
28
29 /// readGCNO - Read GCNO buffer.
30 bool GCOVFile::readGCNO(GCOVBuffer &Buffer) {
31 if (!Buffer.readGCNOFormat())
32 return false;
33 if (!Buffer.readGCOVVersion(Version))
34 return false;
35
36 if (!Buffer.readInt(Checksum))
37 return false;
38 while (true) {
39 if (!Buffer.readFunctionTag())
40 break;
41 auto GFun = make_unique(*this);
42 if (!GFun->readGCNO(Buffer, Version))
43 return false;
44 Functions.push_back(std::move(GFun));
45 }
46
47 GCNOInitialized = true;
48 return true;
49 }
50
51 /// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
52 /// called after readGCNO().
53 bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
54 assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
55 if (!Buffer.readGCDAFormat())
56 return false;
57 GCOV::GCOVVersion GCDAVersion;
58 if (!Buffer.readGCOVVersion(GCDAVersion))
59 return false;
60 if (Version != GCDAVersion) {
61 errs() << "GCOV versions do not match.\n";
62 return false;
63 }
64
65 uint32_t GCDAChecksum;
66 if (!Buffer.readInt(GCDAChecksum))
67 return false;
68 if (Checksum != GCDAChecksum) {
69 errs() << "File checksums do not match: " << Checksum
70 << " != " << GCDAChecksum << ".\n";
71 return false;
72 }
73 for (size_t i = 0, e = Functions.size(); i < e; ++i) {
74 if (!Buffer.readFunctionTag()) {
75 errs() << "Unexpected number of functions.\n";
76 return false;
77 }
78 if (!Functions[i]->readGCDA(Buffer, Version))
79 return false;
80 }
81 if (Buffer.readObjectTag()) {
82 uint32_t Length;
83 uint32_t Dummy;
84 if (!Buffer.readInt(Length))
85 return false;
86 if (!Buffer.readInt(Dummy))
87 return false; // checksum
88 if (!Buffer.readInt(Dummy))
89 return false; // num
90 if (!Buffer.readInt(RunCount))
91 return false;
92 Buffer.advanceCursor(Length - 3);
93 }
94 while (Buffer.readProgramTag()) {
95 uint32_t Length;
96 if (!Buffer.readInt(Length))
97 return false;
98 Buffer.advanceCursor(Length);
99 ++ProgramCount;
100 }
101
102 return true;
103 }
104
105 void GCOVFile::print(raw_ostream &OS) const {
106 for (const auto &FPtr : Functions)
107 FPtr->print(OS);
108 }
109
110 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
111 /// dump - Dump GCOVFile content to dbgs() for debugging purposes.
112 LLVM_DUMP_METHOD void GCOVFile::dump() const {
113 print(dbgs());
114 }
115 #endif
116
117 /// collectLineCounts - Collect line counts. This must be used after
118 /// reading .gcno and .gcda files.
119 void GCOVFile::collectLineCounts(FileInfo &FI) {
120 for (const auto &FPtr : Functions)
121 FPtr->collectLineCounts(FI);
122 FI.setRunCount(RunCount);
123 FI.setProgramCount(ProgramCount);
124 }
125
126 //===----------------------------------------------------------------------===//
127 // GCOVFunction implementation.
128
129 /// readGCNO - Read a function from the GCNO buffer. Return false if an error
130 /// occurs.
131 bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
132 uint32_t Dummy;
133 if (!Buff.readInt(Dummy))
134 return false; // Function header length
135 if (!Buff.readInt(Ident))
136 return false;
137 if (!Buff.readInt(Checksum))
138 return false;
139 if (Version != GCOV::V402) {
140 uint32_t CfgChecksum;
141 if (!Buff.readInt(CfgChecksum))
142 return false;
143 if (Parent.getChecksum() != CfgChecksum) {
144 errs() << "File checksums do not match: " << Parent.getChecksum()
145 << " != " << CfgChecksum << " in (" << Name << ").\n";
146 return false;
147 }
148 }
149 if (!Buff.readString(Name))
150 return false;
151 if (!Buff.readString(Filename))
152 return false;
153 if (!Buff.readInt(LineNumber))
154 return false;
155
156 // read blocks.
157 if (!Buff.readBlockTag()) {
158 errs() << "Block tag not found.\n";
159 return false;
160 }
161 uint32_t BlockCount;
162 if (!Buff.readInt(BlockCount))
163 return false;
164 for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
165 if (!Buff.readInt(Dummy))
166 return false; // Block flags;
167 Blocks.push_back(make_unique(*this, i));
168 }
169
170 // read edges.
171 while (Buff.readEdgeTag()) {
172 uint32_t EdgeCount;
173 if (!Buff.readInt(EdgeCount))
174 return false;
175 EdgeCount = (EdgeCount - 1) / 2;
176 uint32_t BlockNo;
177 if (!Buff.readInt(BlockNo))
178 return false;
179 if (BlockNo >= BlockCount) {
180 errs() << "Unexpected block number: " << BlockNo << " (in " << Name
181 << ").\n";
182 return false;
183 }
184 for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
185 uint32_t Dst;
186 if (!Buff.readInt(Dst))
187 return false;
188 Edges.push_back(make_unique(*Blocks[BlockNo], *Blocks[Dst]));
189 GCOVEdge *Edge = Edges.back().get();
190 Blocks[BlockNo]->addDstEdge(Edge);
191 Blocks[Dst]->addSrcEdge(Edge);
192 if (!Buff.readInt(Dummy))
193 return false; // Edge flag
194 }
195 }
196
197 // read line table.
198 while (Buff.readLineTag()) {
199 uint32_t LineTableLength;
200 // Read the length of this line table.
201 if (!Buff.readInt(LineTableLength))
202 return false;
203 uint32_t EndPos = Buff.getCursor() + LineTableLength * 4;
204 uint32_t BlockNo;
205 // Read the block number this table is associated with.
206 if (!Buff.readInt(BlockNo))
207 return false;
208 if (BlockNo >= BlockCount) {
209 errs() << "Unexpected block number: " << BlockNo << " (in " << Name
210 << ").\n";
211 return false;
212 }
213 GCOVBlock &Block = *Blocks[BlockNo];
214 // Read the word that pads the beginning of the line table. This may be a
215 // flag of some sort, but seems to always be zero.
216 if (!Buff.readInt(Dummy))
217 return false;
218
219 // Line information starts here and continues up until the last word.
220 if (Buff.getCursor() != (EndPos - sizeof(uint32_t))) {
221 StringRef F;
222 // Read the source file name.
223 if (!Buff.readString(F))
224 return false;
225 if (Filename != F) {
226 errs() << "Multiple sources for a single basic block: " << Filename
227 << " != " << F << " (in " << Name << ").\n";
228 return false;
229 }
230 // Read lines up to, but not including, the null terminator.
231 while (Buff.getCursor() < (EndPos - 2 * sizeof(uint32_t))) {
232 uint32_t Line;
233 if (!Buff.readInt(Line))
234 return false;
235 // Line 0 means this instruction was injected by the compiler. Skip it.
236 if (!Line)
237 continue;
238 Block.addLine(Line);
239 }
240 // Read the null terminator.
241 if (!Buff.readInt(Dummy))
242 return false;
243 }
244 // The last word is either a flag or padding, it isn't clear which. Skip
245 // over it.
246 if (!Buff.readInt(Dummy))
247 return false;
248 }
249 return true;
250 }
251
252 /// readGCDA - Read a function from the GCDA buffer. Return false if an error
253 /// occurs.
254 bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
255 uint32_t HeaderLength;
256 if (!Buff.readInt(HeaderLength))
257 return false; // Function header length
258
259 uint64_t EndPos = Buff.getCursor() + HeaderLength * sizeof(uint32_t);
260
261 uint32_t GCDAIdent;
262 if (!Buff.readInt(GCDAIdent))
263 return false;
264 if (Ident != GCDAIdent) {
265 errs() << "Function identifiers do not match: " << Ident
266 << " != " << GCDAIdent << " (in " << Name << ").\n";
267 return false;
268 }
269
270 uint32_t GCDAChecksum;
271 if (!Buff.readInt(GCDAChecksum))
272 return false;
273 if (Checksum != GCDAChecksum) {
274 errs() << "Function checksums do not match: " << Checksum
275 << " != " << GCDAChecksum << " (in " << Name << ").\n";
276 return false;
277 }
278
279 uint32_t CfgChecksum;
280 if (Version != GCOV::V402) {
281 if (!Buff.readInt(CfgChecksum))
282 return false;
283 if (Parent.getChecksum() != CfgChecksum) {
284 errs() << "File checksums do not match: " << Parent.getChecksum()
285 << " != " << CfgChecksum << " (in " << Name << ").\n";
286 return false;
287 }
288 }
289
290 if (Buff.getCursor() < EndPos) {
291 StringRef GCDAName;
292 if (!Buff.readString(GCDAName))
293 return false;
294 if (Name != GCDAName) {
295 errs() << "Function names do not match: " << Name << " != " << GCDAName
296 << ".\n";
297 return false;
298 }
299 }
300
301 if (!Buff.readArcTag()) {
302 errs() << "Arc tag not found (in " << Name << ").\n";
303 return false;
304 }
305
306 uint32_t Count;
307 if (!Buff.readInt(Count))
308 return false;
309 Count /= 2;
310
311 // This for loop adds the counts for each block. A second nested loop is
312 // required to combine the edge counts that are contained in the GCDA file.
313 for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) {
314 // The last block is always reserved for exit block
315 if (BlockNo >= Blocks.size()) {
316 errs() << "Unexpected number of edges (in " << Name << ").\n";
317 return false;
318 }
319 if (BlockNo == Blocks.size() - 1)
320 errs() << "(" << Name << ") has arcs from exit block.\n";
321 GCOVBlock &Block = *Blocks[BlockNo];
322 for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
323 ++EdgeNo) {
324 if (Count == 0) {
325 errs() << "Unexpected number of edges (in " << Name << ").\n";
326 return false;
327 }
328 uint64_t ArcCount;
329 if (!Buff.readInt64(ArcCount))
330 return false;
331 Block.addCount(EdgeNo, ArcCount);
332 --Count;
333 }
334 Block.sortDstEdges();
335 }
336 return true;
337 }
338
339 /// getEntryCount - Get the number of times the function was called by
340 /// retrieving the entry block's count.
341 uint64_t GCOVFunction::getEntryCount() const {
342 return Blocks.front()->getCount();
343 }
344
345 /// getExitCount - Get the number of times the function returned by retrieving
346 /// the exit block's count.
347 uint64_t GCOVFunction::getExitCount() const {
348 return Blocks.back()->getCount();
349 }
350
351 void GCOVFunction::print(raw_ostream &OS) const {
352 OS << "===== " << Name << " (" << Ident << ") @ " << Filename << ":"
353 << LineNumber << "\n";
354 for (const auto &Block : Blocks)
355 Block->print(OS);
356 }
357
358 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
359 /// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
360 LLVM_DUMP_METHOD void GCOVFunction::dump() const {
361 print(dbgs());
362 }
363 #endif
364
365 /// collectLineCounts - Collect line counts. This must be used after
366 /// reading .gcno and .gcda files.
367 void GCOVFunction::collectLineCounts(FileInfo &FI) {
368 // If the line number is zero, this is a function that doesn't actually appear
369 // in the source file, so there isn't anything we can do with it.
370 if (LineNumber == 0)
371 return;
372
373 for (const auto &Block : Blocks)
374 Block->collectLineCounts(FI);
375 FI.addFunctionLine(Filename, LineNumber, this);
376 }
377
378 //===----------------------------------------------------------------------===//
379 // GCOVBlock implementation.
380
381 /// ~GCOVBlock - Delete GCOVBlock and its content.
382 GCOVBlock::~GCOVBlock() {
383 SrcEdges.clear();
384 DstEdges.clear();
385 Lines.clear();
386 }
387
388 /// addCount - Add to block counter while storing the edge count. If the
389 /// destination has no outgoing edges, also update that block's count too.
390 void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
391 assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
392 DstEdges[DstEdgeNo]->Count = N;
393 Counter += N;
394 if (!DstEdges[DstEdgeNo]->Dst.getNumDstEdges())
395 DstEdges[DstEdgeNo]->Dst.Counter += N;
396 }
397
398 /// sortDstEdges - Sort destination edges by block number, nop if already
399 /// sorted. This is required for printing branch info in the correct order.
400 void GCOVBlock::sortDstEdges() {
401 if (!DstEdgesAreSorted) {
402 SortDstEdgesFunctor SortEdges;
403 std::stable_sort(DstEdges.begin(), DstEdges.end(), SortEdges);
404 }
405 }
406
407 /// collectLineCounts - Collect line counts. This must be used after
408 /// reading .gcno and .gcda files.
409 void GCOVBlock::collectLineCounts(FileInfo &FI) {
410 for (uint32_t N : Lines)
411 FI.addBlockLine(Parent.getFilename(), N, this);
412 }
413
414 void GCOVBlock::print(raw_ostream &OS) const {
415 OS << "Block : " << Number << " Counter : " << Counter << "\n";
416 if (!SrcEdges.empty()) {
417 OS << "\tSource Edges : ";
418 for (const GCOVEdge *Edge : SrcEdges)
419 OS << Edge->Src.Number << " (" << Edge->Count << "), ";
420 OS << "\n";
421 }
422 if (!DstEdges.empty()) {
423 OS << "\tDestination Edges : ";
424 for (const GCOVEdge *Edge : DstEdges)
425 OS << Edge->Dst.Number << " (" << Edge->Count << "), ";
426 OS << "\n";
427 }
428 if (!Lines.empty()) {
429 OS << "\tLines : ";
430 for (uint32_t N : Lines)
431 OS << (N) << ",";
432 OS << "\n";
433 }
434 }
435
436 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
437 /// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
438 LLVM_DUMP_METHOD void GCOVBlock::dump() const {
439 print(dbgs());
440 }
441 #endif
442
443 //===----------------------------------------------------------------------===//
444 // FileInfo implementation.
445
446 // Safe integer division, returns 0 if numerator is 0.
447 static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) {
448 if (!Numerator)
449 return 0;
450 return Numerator / Divisor;
451 }
452
453 // This custom division function mimics gcov's branch ouputs:
454 // - Round to closest whole number
455 // - Only output 0% or 100% if it's exactly that value
456 static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) {
457 if (!Numerator)
458 return 0;
459 if (Numerator == Divisor)
460 return 100;
461
462 uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor;
463 if (Res == 0)
464 return 1;
465 if (Res == 100)
466 return 99;
467 return Res;
468 }
469
470 namespace {
471 struct formatBranchInfo {
472 formatBranchInfo(const GCOV::Options &Options, uint64_t Count, uint64_t Total)
473 : Options(Options), Count(Count), Total(Total) {}
474
475 void print(raw_ostream &OS) const {
476 if (!Total)
477 OS << "never executed";
478 else if (Options.BranchCount)
479 OS << "taken " << Count;
480 else
481 OS << "taken " << branchDiv(Count, Total) << "%";
482 }
483
484 const GCOV::Options &Options;
485 uint64_t Count;
486 uint64_t Total;
487 };
488
489 static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
490 FBI.print(OS);
491 return OS;
492 }
493
494 class LineConsumer {
495 std::unique_ptr Buffer;
496 StringRef Remaining;
497
498 public:
499 LineConsumer(StringRef Filename) {
500 ErrorOr> BufferOrErr =
501 MemoryBuffer::getFileOrSTDIN(Filename);
502 if (std::error_code EC = BufferOrErr.getError()) {
503 errs() << Filename << ": " << EC.message() << "\n";
504 Remaining = "";
505 } else {
506 Buffer = std::move(BufferOrErr.get());
507 Remaining = Buffer->getBuffer();
508 }
509 }
510 bool empty() { return Remaining.empty(); }
511 void printNext(raw_ostream &OS, uint32_t LineNum) {
512 StringRef Line;
513 if (empty())
514 Line = "/*EOF*/";
515 else
516 std::tie(Line, Remaining) = Remaining.split("\n");
517 OS << format("%5u:", LineNum) << Line << "\n";
518 }
519 };
520 } // end anonymous namespace
521
522 /// Convert a path to a gcov filename. If PreservePaths is true, this
523 /// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
524 static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
525 if (!PreservePaths)
526 return sys::path::filename(Filename).str();
527
528 // This behaviour is defined by gcov in terms of text replacements, so it's
529 // not likely to do anything useful on filesystems with different textual
530 // conventions.
531 llvm::SmallString<256> Result("");
532 StringRef::iterator I, S, E;
533 for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) {
534 if (*I != '/')
535 continue;
536
537 if (I - S == 1 && *S == '.') {
538 // ".", the current directory, is skipped.
539 } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') {
540 // "..", the parent directory, is replaced with "^".
541 Result.append("^#");
542 } else {
543 if (S < I)
544 // Leave other components intact,
545 Result.append(S, I);
546 // And separate with "#".
547 Result.push_back('#');
548 }
549 S = I + 1;
550 }
551
552 if (S < I)
553 Result.append(S, I);
554 return Result.str();
555 }
556
557 std::string FileInfo::getCoveragePath(StringRef Filename,
558 StringRef MainFilename) {
559 if (Options.NoOutput)
560 // This is probably a bug in gcov, but when -n is specified, paths aren't
561 // mangled at all, and the -l and -p options are ignored. Here, we do the
562 // same.
563 return Filename;
564
565 std::string CoveragePath;
566 if (Options.LongFileNames && !Filename.equals(MainFilename))
567 CoveragePath =
568 mangleCoveragePath(MainFilename, Options.PreservePaths) + "##";
569 CoveragePath += mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov";
570 return CoveragePath;
571 }
572
573 std::unique_ptr
574 FileInfo::openCoveragePath(StringRef CoveragePath) {
575 if (Options.NoOutput)
576 return llvm::make_unique();
577
578 std::error_code EC;
579 auto OS = llvm::make_unique(CoveragePath, EC,
580 sys::fs::F_Text);
581 if (EC) {
582 errs() << EC.message() << "\n";
583 return llvm::make_unique();
584 }
585 return std::move(OS);
586 }
587
588 /// print - Print source files with collected line count information.
589 void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
590 StringRef GCNOFile, StringRef GCDAFile) {
591 SmallVector Filenames;
592 for (const auto &LI : LineInfo)
593 Filenames.push_back(LI.first());
594 std::sort(Filenames.begin(), Filenames.end());
595
596 for (StringRef Filename : Filenames) {
597 auto AllLines = LineConsumer(Filename);
598
599 std::string CoveragePath = getCoveragePath(Filename, MainFilename);
600 std::unique_ptr CovStream = openCoveragePath(CoveragePath);
601 raw_ostream &CovOS = *CovStream;
602
603 CovOS << " -: 0:Source:" << Filename << "\n";
604 CovOS << " -: 0:Graph:" << GCNOFile << "\n";
605 CovOS << " -: 0:Data:" << GCDAFile << "\n";
606 CovOS << " -: 0:Runs:" << RunCount << "\n";
607 CovOS << " -: 0:Programs:" << ProgramCount << "\n";
608
609 const LineData &Line = LineInfo[Filename];
610 GCOVCoverage FileCoverage(Filename);
611 for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || !AllLines.empty();
612 ++LineIndex) {
613 if (Options.BranchInfo) {
614 FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
615 if (FuncsIt != Line.Functions.end())
616 printFunctionSummary(CovOS, FuncsIt->second);
617 }
618
619 BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex);
620 if (BlocksIt == Line.Blocks.end()) {
621 // No basic blocks are on this line. Not an executable line of code.
622 CovOS << " -:";
623 AllLines.printNext(CovOS, LineIndex + 1);
624 } else {
625 const BlockVector &Blocks = BlocksIt->second;
626
627 // Add up the block counts to form line counts.
628 DenseMap LineExecs;
629 uint64_t LineCount = 0;
630 for (const GCOVBlock *Block : Blocks) {
631 if (Options.AllBlocks) {
632 // Only take the highest block count for that line.
633 uint64_t BlockCount = Block->getCount();
634 LineCount = LineCount > BlockCount ? LineCount : BlockCount;
635 } else {
636 // Sum up all of the block counts.
637 LineCount += Block->getCount();
638 }
639
640 if (Options.FuncCoverage) {
641 // This is a slightly convoluted way to most accurately gather line
642 // statistics for functions. Basically what is happening is that we
643 // don't want to count a single line with multiple blocks more than
644 // once. However, we also don't simply want to give the total line
645 // count to every function that starts on the line. Thus, what is
646 // happening here are two things:
647 // 1) Ensure that the number of logical lines is only incremented
648 // once per function.
649 // 2) If there are multiple blocks on the same line, ensure that the
650 // number of lines executed is incremented as long as at least
651 // one of the blocks are executed.
652 const GCOVFunction *Function = &Block->getParent();
653 if (FuncCoverages.find(Function) == FuncCoverages.end()) {
654 std::pair KeyValue(
655 Function, GCOVCoverage(Function->getName()));
656 FuncCoverages.insert(KeyValue);
657 }
658 GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
659
660 if (LineExecs.find(Function) == LineExecs.end()) {
661 if (Block->getCount()) {
662 ++FuncCoverage.LinesExec;
663 LineExecs[Function] = true;
664 } else {
665 LineExecs[Function] = false;
666 }
667 ++FuncCoverage.LogicalLines;
668 } else if (!LineExecs[Function] && Block->getCount()) {
669 ++FuncCoverage.LinesExec;
670 LineExecs[Function] = true;
671 }
672 }
673 }
674
675 if (LineCount == 0)
676 CovOS << " #####:";
677 else {
678 CovOS << format("%9" PRIu64 ":", LineCount);
679 ++FileCoverage.LinesExec;
680 }
681 ++FileCoverage.LogicalLines;
682
683 AllLines.printNext(CovOS, LineIndex + 1);
684
685 uint32_t BlockNo = 0;
686 uint32_t EdgeNo = 0;
687 for (const GCOVBlock *Block : Blocks) {
688 // Only print block and branch information at the end of the block.
689 if (Block->getLastLine() != LineIndex + 1)
690 continue;
691 if (Options.AllBlocks)
692 printBlockInfo(CovOS, *Block, LineIndex, BlockNo);
693 if (Options.BranchInfo) {
694 size_t NumEdges = Block->getNumDstEdges();
695 if (NumEdges > 1)
696 printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo);
697 else if (Options.UncondBranch && NumEdges == 1)
698 printUncondBranchInfo(CovOS, EdgeNo,
699 (*Block->dst_begin())->Count);
700 }
701 }
702 }
703 }
704 FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage));
705 }
706
707 // FIXME: There is no way to detect calls given current instrumentation.
708 if (Options.FuncCoverage)
709 printFuncCoverage(InfoOS);
710 printFileCoverage(InfoOS);
711 }
712
713 /// printFunctionSummary - Print function and block summary.
714 void FileInfo::printFunctionSummary(raw_ostream &OS,
715 const FunctionVector &Funcs) const {
716 for (const GCOVFunction *Func : Funcs) {
717 uint64_t EntryCount = Func->getEntryCount();
718 uint32_t BlocksExec = 0;
719 for (const GCOVBlock &Block : Func->blocks())
720 if (Block.getNumDstEdges() && Block.getCount())
721 ++BlocksExec;
722
723 OS << "function " << Func->getName() << " called " << EntryCount
724 << " returned " << safeDiv(Func->getExitCount() * 100, EntryCount)
725 << "% blocks executed "
726 << safeDiv(BlocksExec * 100, Func->getNumBlocks() - 1) << "%\n";
727 }
728 }
729
730 /// printBlockInfo - Output counts for each block.
731 void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
732 uint32_t LineIndex, uint32_t &BlockNo) const {
733 if (Block.getCount() == 0)
734 OS << " $$$$$:";
735 else
736 OS << format("%9" PRIu64 ":", Block.getCount());
737 OS << format("%5u-block %2u\n", LineIndex + 1, BlockNo++);
738 }
739
740 /// printBranchInfo - Print conditional branch probabilities.
741 void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
742 GCOVCoverage &Coverage, uint32_t &EdgeNo) {
743 SmallVector BranchCounts;
744 uint64_t TotalCounts = 0;
745 for (const GCOVEdge *Edge : Block.dsts()) {
746 BranchCounts.push_back(Edge->Count);
747 TotalCounts += Edge->Count;
748 if (Block.getCount())
749 ++Coverage.BranchesExec;
750 if (Edge->Count)
751 ++Coverage.BranchesTaken;
752 ++Coverage.Branches;
753
754 if (Options.FuncCoverage) {
755 const GCOVFunction *Function = &Block.getParent();
756 GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
757 if (Block.getCount())
758 ++FuncCoverage.BranchesExec;
759 if (Edge->Count)
760 ++FuncCoverage.BranchesTaken;
761 ++FuncCoverage.Branches;
762 }
763 }
764
765 for (uint64_t N : BranchCounts)
766 OS << format("branch %2u ", EdgeNo++)
767 << formatBranchInfo(Options, N, TotalCounts) << "\n";
768 }
769
770 /// printUncondBranchInfo - Print unconditional branch probabilities.
771 void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
772 uint64_t Count) const {
773 OS << format("unconditional %2u ", EdgeNo++)
774 << formatBranchInfo(Options, Count, Count) << "\n";
775 }
776
777 // printCoverage - Print generic coverage info used by both printFuncCoverage
778 // and printFileCoverage.
779 void FileInfo::printCoverage(raw_ostream &OS,
780 const GCOVCoverage &Coverage) const {
781 OS << format("Lines executed:%.2f%% of %u\n",
782 double(Coverage.LinesExec) * 100 / Coverage.LogicalLines,
783 Coverage.LogicalLines);
784 if (Options.BranchInfo) {
785 if (Coverage.Branches) {
786 OS << format("Branches executed:%.2f%% of %u\n",
787 double(Coverage.BranchesExec) * 100 / Coverage.Branches,
788 Coverage.Branches);
789 OS << format("Taken at least once:%.2f%% of %u\n",
790 double(Coverage.BranchesTaken) * 100 / Coverage.Branches,
791 Coverage.Branches);
792 } else {
793 OS << "No branches\n";
794 }
795 OS << "No calls\n"; // to be consistent with gcov
796 }
797 }
798
799 // printFuncCoverage - Print per-function coverage info.
800 void FileInfo::printFuncCoverage(raw_ostream &OS) const {
801 for (const auto &FC : FuncCoverages) {
802 const GCOVCoverage &Coverage = FC.second;
803 OS << "Function '" << Coverage.Name << "'\n";
804 printCoverage(OS, Coverage);
805 OS << "\n";
806 }
807 }
808
809 // printFileCoverage - Print per-file coverage info.
810 void FileInfo::printFileCoverage(raw_ostream &OS) const {
811 for (const auto &FC : FileCoverages) {
812 const std::string &Filename = FC.first;
813 const GCOVCoverage &Coverage = FC.second;
814 OS << "File '" << Coverage.Name << "'\n";
815 printCoverage(OS, Coverage);
816 if (!Options.NoOutput)
817 OS << Coverage.Name << ":creating '" << Filename << "'\n";
818 OS << "\n";
819 }
820 }
0 add_llvm_library(LLVMProfileData
1 GCOV.cpp
12 InstrProf.cpp
23 InstrProfReader.cpp
34 InstrProfWriter.cpp
0 //===- GCOV.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/ProfileData/GCOV.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/FileSystem.h"
18 #include "llvm/Support/Format.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include
22 #include
23
24 using namespace llvm;
25
26 //===----------------------------------------------------------------------===//
27 // GCOVFile implementation.
28
29 /// readGCNO - Read GCNO buffer.
30 bool GCOVFile::readGCNO(GCOVBuffer &Buffer) {
31 if (!Buffer.readGCNOFormat())
32 return false;
33 if (!Buffer.readGCOVVersion(Version))
34 return false;
35
36 if (!Buffer.readInt(Checksum))
37 return false;
38 while (true) {
39 if (!Buffer.readFunctionTag())
40 break;
41 auto GFun = make_unique(*this);
42 if (!GFun->readGCNO(Buffer, Version))
43 return false;
44 Functions.push_back(std::move(GFun));
45 }
46
47 GCNOInitialized = true;
48 return true;
49 }
50
51 /// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
52 /// called after readGCNO().
53 bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
54 assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
55 if (!Buffer.readGCDAFormat())
56 return false;
57 GCOV::GCOVVersion GCDAVersion;
58 if (!Buffer.readGCOVVersion(GCDAVersion))
59 return false;
60 if (Version != GCDAVersion) {
61 errs() << "GCOV versions do not match.\n";
62 return false;
63 }
64
65 uint32_t GCDAChecksum;
66 if (!Buffer.readInt(GCDAChecksum))
67 return false;
68 if (Checksum != GCDAChecksum) {
69 errs() << "File checksums do not match: " << Checksum
70 << " != " << GCDAChecksum << ".\n";
71 return false;
72 }
73 for (size_t i = 0, e = Functions.size(); i < e; ++i) {
74 if (!Buffer.readFunctionTag()) {
75 errs() << "Unexpected number of functions.\n";
76 return false;
77 }
78 if (!Functions[i]->readGCDA(Buffer, Version))
79 return false;
80 }
81 if (Buffer.readObjectTag()) {
82 uint32_t Length;
83 uint32_t Dummy;
84 if (!Buffer.readInt(Length))
85 return false;
86 if (!Buffer.readInt(Dummy))
87 return false; // checksum
88 if (!Buffer.readInt(Dummy))
89 return false; // num
90 if (!Buffer.readInt(RunCount))
91 return false;
92 Buffer.advanceCursor(Length - 3);
93 }
94 while (Buffer.readProgramTag()) {
95 uint32_t Length;
96 if (!Buffer.readInt(Length))
97 return false;
98 Buffer.advanceCursor(Length);
99 ++ProgramCount;
100 }
101
102 return true;
103 }
104
105 void GCOVFile::print(raw_ostream &OS) const {
106 for (const auto &FPtr : Functions)
107 FPtr->print(OS);
108 }
109
110 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
111 /// dump - Dump GCOVFile content to dbgs() for debugging purposes.
112 LLVM_DUMP_METHOD void GCOVFile::dump() const {
113 print(dbgs());
114 }
115 #endif
116
117 /// collectLineCounts - Collect line counts. This must be used after
118 /// reading .gcno and .gcda files.
119 void GCOVFile::collectLineCounts(FileInfo &FI) {
120 for (const auto &FPtr : Functions)
121 FPtr->collectLineCounts(FI);
122 FI.setRunCount(RunCount);
123 FI.setProgramCount(ProgramCount);
124 }
125
126 //===----------------------------------------------------------------------===//
127 // GCOVFunction implementation.
128
129 /// readGCNO - Read a function from the GCNO buffer. Return false if an error
130 /// occurs.
131 bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
132 uint32_t Dummy;
133 if (!Buff.readInt(Dummy))
134 return false; // Function header length
135 if (!Buff.readInt(Ident))
136 return false;
137 if (!Buff.readInt(Checksum))
138 return false;
139 if (Version != GCOV::V402) {
140 uint32_t CfgChecksum;
141 if (!Buff.readInt(CfgChecksum))
142 return false;
143 if (Parent.getChecksum() != CfgChecksum) {
144 errs() << "File checksums do not match: " << Parent.getChecksum()
145 << " != " << CfgChecksum << " in (" << Name << ").\n";
146 return false;
147 }
148 }
149 if (!Buff.readString(Name))
150 return false;
151 if (!Buff.readString(Filename))
152 return false;
153 if (!Buff.readInt(LineNumber))
154 return false;
155
156 // read blocks.
157 if (!Buff.readBlockTag()) {
158 errs() << "Block tag not found.\n";
159 return false;
160 }
161 uint32_t BlockCount;
162 if (!Buff.readInt(BlockCount))
163 return false;
164 for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
165 if (!Buff.readInt(Dummy))
166 return false; // Block flags;
167 Blocks.push_back(make_unique(*this, i));
168 }
169
170 // read edges.
171 while (Buff.readEdgeTag()) {
172 uint32_t EdgeCount;
173 if (!Buff.readInt(EdgeCount))
174 return false;
175 EdgeCount = (EdgeCount - 1) / 2;
176 uint32_t BlockNo;
177 if (!Buff.readInt(BlockNo))
178 return false;
179 if (BlockNo >= BlockCount) {
180 errs() << "Unexpected block number: " << BlockNo << " (in " << Name
181 << ").\n";
182 return false;
183 }
184 for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
185 uint32_t Dst;
186 if (!Buff.readInt(Dst))
187 return false;
188 Edges.push_back(make_unique(*Blocks[BlockNo], *Blocks[Dst]));
189 GCOVEdge *Edge = Edges.back().get();
190 Blocks[BlockNo]->addDstEdge(Edge);
191 Blocks[Dst]->addSrcEdge(Edge);
192 if (!Buff.readInt(Dummy))
193 return false; // Edge flag
194 }
195 }
196
197 // read line table.
198 while (Buff.readLineTag()) {
199 uint32_t LineTableLength;
200 // Read the length of this line table.
201 if (!Buff.readInt(LineTableLength))
202 return false;
203 uint32_t EndPos = Buff.getCursor() + LineTableLength * 4;
204 uint32_t BlockNo;
205 // Read the block number this table is associated with.
206 if (!Buff.readInt(BlockNo))
207 return false;
208 if (BlockNo >= BlockCount) {
209 errs() << "Unexpected block number: " << BlockNo << " (in " << Name
210 << ").\n";
211 return false;
212 }
213 GCOVBlock &Block = *Blocks[BlockNo];
214 // Read the word that pads the beginning of the line table. This may be a
215 // flag of some sort, but seems to always be zero.
216 if (!Buff.readInt(Dummy))
217 return false;
218
219 // Line information starts here and continues up until the last word.
220 if (Buff.getCursor() != (EndPos - sizeof(uint32_t))) {
221 StringRef F;
222 // Read the source file name.
223 if (!Buff.readString(F))
224 return false;
225 if (Filename != F) {
226 errs() << "Multiple sources for a single basic block: " << Filename
227 << " != " << F << " (in " << Name << ").\n";
228 return false;
229 }
230 // Read lines up to, but not including, the null terminator.
231 while (Buff.getCursor() < (EndPos - 2 * sizeof(uint32_t))) {
232 uint32_t Line;
233 if (!Buff.readInt(Line))
234 return false;
235 // Line 0 means this instruction was injected by the compiler. Skip it.
236 if (!Line)
237 continue;
238 Block.addLine(Line);
239 }
240 // Read the null terminator.
241 if (!Buff.readInt(Dummy))
242 return false;
243 }
244 // The last word is either a flag or padding, it isn't clear which. Skip
245 // over it.
246 if (!Buff.readInt(Dummy))
247 return false;
248 }
249 return true;
250 }
251
252 /// readGCDA - Read a function from the GCDA buffer. Return false if an error
253 /// occurs.
254 bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
255 uint32_t HeaderLength;
256 if (!Buff.readInt(HeaderLength))
257 return false; // Function header length
258
259 uint64_t EndPos = Buff.getCursor() + HeaderLength * sizeof(uint32_t);
260
261 uint32_t GCDAIdent;
262 if (!Buff.readInt(GCDAIdent))
263 return false;
264 if (Ident != GCDAIdent) {
265 errs() << "Function identifiers do not match: " << Ident
266 << " != " << GCDAIdent << " (in " << Name << ").\n";
267 return false;
268 }
269
270 uint32_t GCDAChecksum;
271 if (!Buff.readInt(GCDAChecksum))
272 return false;
273 if (Checksum != GCDAChecksum) {
274 errs() << "Function checksums do not match: " << Checksum
275 << " != " << GCDAChecksum << " (in " << Name << ").\n";
276 return false;
277 }
278
279 uint32_t CfgChecksum;
280 if (Version != GCOV::V402) {
281 if (!Buff.readInt(CfgChecksum))
282 return false;
283 if (Parent.getChecksum() != CfgChecksum) {
284 errs() << "File checksums do not match: " << Parent.getChecksum()
285 << " != " << CfgChecksum << " (in " << Name << ").\n";
286 return false;
287 }
288 }
289
290 if (Buff.getCursor() < EndPos) {
291 StringRef GCDAName;
292 if (!Buff.readString(GCDAName))
293 return false;
294 if (Name != GCDAName) {
295 errs() << "Function names do not match: " << Name << " != " << GCDAName
296 << ".\n";
297 return false;
298 }
299 }
300
301 if (!Buff.readArcTag()) {
302 errs() << "Arc tag not found (in " << Name << ").\n";
303 return false;
304 }
305
306 uint32_t Count;
307 if (!Buff.readInt(Count))
308 return false;
309 Count /= 2;
310
311 // This for loop adds the counts for each block. A second nested loop is
312 // required to combine the edge counts that are contained in the GCDA file.
313 for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) {
314 // The last block is always reserved for exit block
315 if (BlockNo >= Blocks.size()) {
316 errs() << "Unexpected number of edges (in " << Name << ").\n";
317 return false;
318 }
319 if (BlockNo == Blocks.size() - 1)
320 errs() << "(" << Name << ") has arcs from exit block.\n";
321 GCOVBlock &Block = *Blocks[BlockNo];
322 for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
323 ++EdgeNo) {
324 if (Count == 0) {
325 errs() << "Unexpected number of edges (in " << Name << ").\n";
326 return false;
327 }
328 uint64_t ArcCount;
329 if (!Buff.readInt64(ArcCount))
330 return false;
331 Block.addCount(EdgeNo, ArcCount);
332 --Count;
333 }
334 Block.sortDstEdges();
335 }
336 return true;
337 }
338
339 /// getEntryCount - Get the number of times the function was called by
340 /// retrieving the entry block's count.
341 uint64_t GCOVFunction::getEntryCount() const {
342 return Blocks.front()->getCount();
343 }
344
345 /// getExitCount - Get the number of times the function returned by retrieving
346 /// the exit block's count.
347 uint64_t GCOVFunction::getExitCount() const {
348 return Blocks.back()->getCount();
349 }
350
351 void GCOVFunction::print(raw_ostream &OS) const {
352 OS << "===== " << Name << " (" << Ident << ") @ " << Filename << ":"
353 << LineNumber << "\n";
354 for (const auto &Block : Blocks)
355 Block->print(OS);
356 }
357
358 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
359 /// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
360 LLVM_DUMP_METHOD void GCOVFunction::dump() const {
361 print(dbgs());
362 }
363 #endif
364
365 /// collectLineCounts - Collect line counts. This must be used after
366 /// reading .gcno and .gcda files.
367 void GCOVFunction::collectLineCounts(FileInfo &FI) {
368 // If the line number is zero, this is a function that doesn't actually appear
369 // in the source file, so there isn't anything we can do with it.
370 if (LineNumber == 0)
371 return;
372
373 for (const auto &Block : Blocks)
374 Block->collectLineCounts(FI);
375 FI.addFunctionLine(Filename, LineNumber, this);
376 }
377
378 //===----------------------------------------------------------------------===//
379 // GCOVBlock implementation.
380
381 /// ~GCOVBlock - Delete GCOVBlock and its content.
382 GCOVBlock::~GCOVBlock() {
383 SrcEdges.clear();
384 DstEdges.clear();
385 Lines.clear();
386 }
387
388 /// addCount - Add to block counter while storing the edge count. If the
389 /// destination has no outgoing edges, also update that block's count too.
390 void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
391 assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
392 DstEdges[DstEdgeNo]->Count = N;
393 Counter += N;
394 if (!DstEdges[DstEdgeNo]->Dst.getNumDstEdges())
395 DstEdges[DstEdgeNo]->Dst.Counter += N;
396 }
397
398 /// sortDstEdges - Sort destination edges by block number, nop if already
399 /// sorted. This is required for printing branch info in the correct order.
400 void GCOVBlock::sortDstEdges() {
401 if (!DstEdgesAreSorted) {
402 SortDstEdgesFunctor SortEdges;
403 std::stable_sort(DstEdges.begin(), DstEdges.end(), SortEdges);
404 }
405 }
406
407 /// collectLineCounts - Collect line counts. This must be used after
408 /// reading .gcno and .gcda files.
409 void GCOVBlock::collectLineCounts(FileInfo &FI) {
410 for (uint32_t N : Lines)
411 FI.addBlockLine(Parent.getFilename(), N, this);
412 }
413
414 void GCOVBlock::print(raw_ostream &OS) const {
415 OS << "Block : " << Number << " Counter : " << Counter << "\n";
416 if (!SrcEdges.empty()) {
417 OS << "\tSource Edges : ";
418 for (const GCOVEdge *Edge : SrcEdges)
419 OS << Edge->Src.Number << " (" << Edge->Count << "), ";
420 OS << "\n";
421 }
422 if (!DstEdges.empty()) {
423 OS << "\tDestination Edges : ";
424 for (const GCOVEdge *Edge : DstEdges)
425 OS << Edge->Dst.Number << " (" << Edge->Count << "), ";
426 OS << "\n";
427 }
428 if (!Lines.empty()) {
429 OS << "\tLines : ";
430 for (uint32_t N : Lines)
431 OS << (N) << ",";
432 OS << "\n";
433 }
434 }
435
436 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
437 /// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
438 LLVM_DUMP_METHOD void GCOVBlock::dump() const {
439 print(dbgs());
440 }
441 #endif
442
443 //===----------------------------------------------------------------------===//
444 // FileInfo implementation.
445
446 // Safe integer division, returns 0 if numerator is 0.
447 static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) {
448 if (!Numerator)
449 return 0;
450 return Numerator / Divisor;
451 }
452
453 // This custom division function mimics gcov's branch ouputs:
454 // - Round to closest whole number
455 // - Only output 0% or 100% if it's exactly that value
456 static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) {
457 if (!Numerator)
458 return 0;
459 if (Numerator == Divisor)
460 return 100;
461
462 uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor;
463 if (Res == 0)
464 return 1;
465 if (Res == 100)
466 return 99;
467 return Res;
468 }
469
470 namespace {
471 struct formatBranchInfo {
472 formatBranchInfo(const GCOV::Options &Options, uint64_t Count, uint64_t Total)
473 : Options(Options), Count(Count), Total(Total) {}
474
475 void print(raw_ostream &OS) const {
476 if (!Total)
477 OS << "never executed";
478 else if (Options.BranchCount)
479 OS << "taken " << Count;
480 else
481 OS << "taken " << branchDiv(Count, Total) << "%";
482 }
483
484 const GCOV::Options &Options;
485 uint64_t Count;
486 uint64_t Total;
487 };
488
489 static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
490 FBI.print(OS);
491 return OS;
492 }
493
494 class LineConsumer {
495 std::unique_ptr Buffer;
496 StringRef Remaining;
497
498 public:
499 LineConsumer(StringRef Filename) {
500 ErrorOr> BufferOrErr =
501 MemoryBuffer::getFileOrSTDIN(Filename);
502 if (std::error_code EC = BufferOrErr.getError()) {
503 errs() << Filename << ": " << EC.message() << "\n";
504 Remaining = "";
505 } else {
506 Buffer = std::move(BufferOrErr.get());
507 Remaining = Buffer->getBuffer();
508 }
509 }
510 bool empty() { return Remaining.empty(); }
511 void printNext(raw_ostream &OS, uint32_t LineNum) {
512 StringRef Line;
513 if (empty())
514 Line = "/*EOF*/";
515 else
516 std::tie(Line, Remaining) = Remaining.split("\n");
517 OS << format("%5u:", LineNum) << Line << "\n";
518 }
519 };
520 } // end anonymous namespace
521
522 /// Convert a path to a gcov filename. If PreservePaths is true, this
523 /// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
524 static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
525 if (!PreservePaths)
526 return sys::path::filename(Filename).str();
527
528 // This behaviour is defined by gcov in terms of text replacements, so it's
529 // not likely to do anything useful on filesystems with different textual
530 // conventions.
531 llvm::SmallString<256> Result("");
532 StringRef::iterator I, S, E;
533 for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) {
534 if (*I != '/')
535 continue;
536
537 if (I - S == 1 && *S == '.') {
538 // ".", the current directory, is skipped.
539 } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') {
540 // "..", the parent directory, is replaced with "^".
541 Result.append("^#");
542 } else {
543 if (S < I)
544 // Leave other components intact,
545 Result.append(S, I);
546 // And separate with "#".
547 Result.push_back('#');
548 }
549 S = I + 1;
550 }
551
552 if (S < I)
553 Result.append(S, I);
554 return Result.str();
555 }
556
557 std::string FileInfo::getCoveragePath(StringRef Filename,
558 StringRef MainFilename) {
559 if (Options.NoOutput)
560 // This is probably a bug in gcov, but when -n is specified, paths aren't
561 // mangled at all, and the -l and -p options are ignored. Here, we do the
562 // same.
563 return Filename;
564
565 std::string CoveragePath;
566 if (Options.LongFileNames && !Filename.equals(MainFilename))
567 CoveragePath =
568 mangleCoveragePath(MainFilename, Options.PreservePaths) + "##";
569 CoveragePath += mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov";
570 return CoveragePath;
571 }
572
573 std::unique_ptr
574 FileInfo::openCoveragePath(StringRef CoveragePath) {
575 if (Options.NoOutput)
576 return llvm::make_unique();
577
578 std::error_code EC;
579 auto OS = llvm::make_unique(CoveragePath, EC,
580 sys::fs::F_Text);
581 if (EC) {
582 errs() << EC.message() << "\n";
583 return llvm::make_unique();
584 }
585 return std::move(OS);
586 }
587
588 /// print - Print source files with collected line count information.
589 void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
590 StringRef GCNOFile, StringRef GCDAFile) {
591 SmallVector Filenames;
592 for (const auto &LI : LineInfo)
593 Filenames.push_back(LI.first());
594 std::sort(Filenames.begin(), Filenames.end());
595
596 for (StringRef Filename : Filenames) {
597 auto AllLines = LineConsumer(Filename);
598
599 std::string CoveragePath = getCoveragePath(Filename, MainFilename);
600 std::unique_ptr CovStream = openCoveragePath(CoveragePath);
601 raw_ostream &CovOS = *CovStream;
602
603 CovOS << " -: 0:Source:" << Filename << "\n";
604 CovOS << " -: 0:Graph:" << GCNOFile << "\n";
605 CovOS << " -: 0:Data:" << GCDAFile << "\n";
606 CovOS << " -: 0:Runs:" << RunCount << "\n";
607 CovOS << " -: 0:Programs:" << ProgramCount << "\n";
608
609 const LineData &Line = LineInfo[Filename];
610 GCOVCoverage FileCoverage(Filename);
611 for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || !AllLines.empty();
612 ++LineIndex) {
613 if (Options.BranchInfo) {
614 FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
615 if (FuncsIt != Line.Functions.end())
616 printFunctionSummary(CovOS, FuncsIt->second);
617 }
618
619 BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex);
620 if (BlocksIt == Line.Blocks.end()) {
621 // No basic blocks are on this line. Not an executable line of code.
622 CovOS << " -:";
623 AllLines.printNext(CovOS, LineIndex + 1);
624 } else {
625 const BlockVector &Blocks = BlocksIt->second;
626
627 // Add up the block counts to form line counts.
628 DenseMap LineExecs;
629 uint64_t LineCount = 0;
630 for (const GCOVBlock *Block : Blocks) {
631 if (Options.AllBlocks) {
632 // Only take the highest block count for that line.
633 uint64_t BlockCount = Block->getCount();
634 LineCount = LineCount > BlockCount ? LineCount : BlockCount;
635 } else {
636 // Sum up all of the block counts.
637 LineCount += Block->getCount();
638 }
639
640 if (Options.FuncCoverage) {
641 // This is a slightly convoluted way to most accurately gather line
642 // statistics for functions. Basically what is happening is that we
643 // don't want to count a single line with multiple blocks more than
644 // once. However, we also don't simply want to give the total line
645 // count to every function that starts on the line. Thus, what is
646 // happening here are two things:
647 // 1) Ensure that the number of logical lines is only incremented
648 // once per function.
649 // 2) If there are multiple blocks on the same line, ensure that the
650 // number of lines executed is incremented as long as at least
651 // one of the blocks are executed.
652 const GCOVFunction *Function = &Block->getParent();
653 if (FuncCoverages.find(Function) == FuncCoverages.end()) {
654 std::pair KeyValue(
655 Function, GCOVCoverage(Function->getName()));
656 FuncCoverages.insert(KeyValue);
657 }
658 GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
659
660 if (LineExecs.find(Function) == LineExecs.end()) {
661 if (Block->getCount()) {
662 ++FuncCoverage.LinesExec;
663 LineExecs[Function] = true;
664 } else {
665 LineExecs[Function] = false;
666 }
667 ++FuncCoverage.LogicalLines;
668 } else if (!LineExecs[Function] && Block->getCount()) {
669 ++FuncCoverage.LinesExec;
670 LineExecs[Function] = true;
671 }
672 }
673 }
674
675 if (LineCount == 0)
676 CovOS << " #####:";
677 else {
678 CovOS << format("%9" PRIu64 ":", LineCount);
679 ++FileCoverage.LinesExec;
680 }
681 ++FileCoverage.LogicalLines;
682
683 AllLines.printNext(CovOS, LineIndex + 1);
684
685 uint32_t BlockNo = 0;
686 uint32_t EdgeNo = 0;
687 for (const GCOVBlock *Block : Blocks) {
688 // Only print block and branch information at the end of the block.
689 if (Block->getLastLine() != LineIndex + 1)
690 continue;
691 if (Options.AllBlocks)
692 printBlockInfo(CovOS, *Block, LineIndex, BlockNo);
693 if (Options.BranchInfo) {
694 size_t NumEdges = Block->getNumDstEdges();
695 if (NumEdges > 1)
696 printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo);
697 else if (Options.UncondBranch && NumEdges == 1)
698 printUncondBranchInfo(CovOS, EdgeNo,
699 (*Block->dst_begin())->Count);
700 }
701 }
702 }
703 }
704 FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage));
705 }
706
707 // FIXME: There is no way to detect calls given current instrumentation.
708 if (Options.FuncCoverage)
709 printFuncCoverage(InfoOS);
710 printFileCoverage(InfoOS);
711 }
712
713 /// printFunctionSummary - Print function and block summary.
714 void FileInfo::printFunctionSummary(raw_ostream &OS,
715 const FunctionVector &Funcs) const {
716 for (const GCOVFunction *Func : Funcs) {
717 uint64_t EntryCount = Func->getEntryCount();
718 uint32_t BlocksExec = 0;
719 for (const GCOVBlock &Block : Func->blocks())
720 if (Block.getNumDstEdges() && Block.getCount())
721 ++BlocksExec;
722
723 OS << "function " << Func->getName() << " called " << EntryCount
724 << " returned " << safeDiv(Func->getExitCount() * 100, EntryCount)
725 << "% blocks executed "
726 << safeDiv(BlocksExec * 100, Func->getNumBlocks() - 1) << "%\n";
727 }
728 }
729
730 /// printBlockInfo - Output counts for each block.
731 void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
732 uint32_t LineIndex, uint32_t &BlockNo) const {
733 if (Block.getCount() == 0)
734 OS << " $$$$$:";
735 else
736 OS << format("%9" PRIu64 ":", Block.getCount());
737 OS << format("%5u-block %2u\n", LineIndex + 1, BlockNo++);
738 }
739
740 /// printBranchInfo - Print conditional branch probabilities.
741 void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
742 GCOVCoverage &Coverage, uint32_t &EdgeNo) {
743 SmallVector BranchCounts;
744 uint64_t TotalCounts = 0;
745 for (const GCOVEdge *Edge : Block.dsts()) {
746 BranchCounts.push_back(Edge->Count);
747 TotalCounts += Edge->Count;
748 if (Block.getCount())
749 ++Coverage.BranchesExec;
750 if (Edge->Count)
751 ++Coverage.BranchesTaken;
752 ++Coverage.Branches;
753
754 if (Options.FuncCoverage) {
755 const GCOVFunction *Function = &Block.getParent();
756 GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
757 if (Block.getCount())
758 ++FuncCoverage.BranchesExec;
759 if (Edge->Count)
760 ++FuncCoverage.BranchesTaken;
761 ++FuncCoverage.Branches;
762 }
763 }
764
765 for (uint64_t N : BranchCounts)
766 OS << format("branch %2u ", EdgeNo++)
767 << formatBranchInfo(Options, N, TotalCounts) << "\n";
768 }
769
770 /// printUncondBranchInfo - Print unconditional branch probabilities.
771 void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
772 uint64_t Count) const {
773 OS << format("unconditional %2u ", EdgeNo++)
774 << formatBranchInfo(Options, Count, Count) << "\n";
775 }
776
777 // printCoverage - Print generic coverage info used by both printFuncCoverage
778 // and printFileCoverage.
779 void FileInfo::printCoverage(raw_ostream &OS,
780 const GCOVCoverage &Coverage) const {
781 OS << format("Lines executed:%.2f%% of %u\n",
782 double(Coverage.LinesExec) * 100 / Coverage.LogicalLines,
783 Coverage.LogicalLines);
784 if (Options.BranchInfo) {
785 if (Coverage.Branches) {
786 OS << format("Branches executed:%.2f%% of %u\n",
787 double(Coverage.BranchesExec) * 100 / Coverage.Branches,
788 Coverage.Branches);
789 OS << format("Taken at least once:%.2f%% of %u\n",
790 double(Coverage.BranchesTaken) * 100 / Coverage.Branches,
791 Coverage.Branches);
792 } else {
793 OS << "No branches\n";
794 }
795 OS << "No calls\n"; // to be consistent with gcov
796 }
797 }
798
799 // printFuncCoverage - Print per-function coverage info.
800 void FileInfo::printFuncCoverage(raw_ostream &OS) const {
801 for (const auto &FC : FuncCoverages) {
802 const GCOVCoverage &Coverage = FC.second;
803 OS << "Function '" << Coverage.Name << "'\n";
804 printCoverage(OS, Coverage);
805 OS << "\n";
806 }
807 }
808
809 // printFileCoverage - Print per-file coverage info.
810 void FileInfo::printFileCoverage(raw_ostream &OS) const {
811 for (const auto &FC : FileCoverages) {
812 const std::string &Filename = FC.first;
813 const GCOVCoverage &Coverage = FC.second;
814 OS << "File '" << Coverage.Name << "'\n";
815 printCoverage(OS, Coverage);
816 if (!Options.NoOutput)
817 OS << Coverage.Name << ":creating '" << Filename << "'\n";
818 OS << "\n";
819 }
820 }
1010 //
1111 //===----------------------------------------------------------------------===//
1212
13 #include "llvm/ProfileData/GCOV.h"
1314 #include "llvm/ADT/SmallString.h"
1415 #include "llvm/Support/CommandLine.h"
1516 #include "llvm/Support/Errc.h"
1617 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/GCOV.h"
1818 #include "llvm/Support/Path.h"
1919 #include
2020 using namespace llvm;