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