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"
18#include "llvm/Support/FileSystem.h"
19#include "llvm/Support/Format.h"
20#include "llvm/Support/MemoryObject.h"
21#include "llvm/Support/Path.h"
22#include "llvm/Support/raw_ostream.h"
23#include <algorithm>
24#include <system_error>
25using namespace llvm;
26
27//===----------------------------------------------------------------------===//
28// GCOVFile implementation.
29
30/// readGCNO - Read GCNO buffer.
31bool GCOVFile::readGCNO(GCOVBuffer &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().
54bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
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;
84    uint32_t Dummy;
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.
107void GCOVFile::dump() const {
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.
114void GCOVFile::collectLineCounts(FileInfo &FI) {
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.
126bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
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.
249bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
250  uint32_t Dummy;
251  if (!Buff.readInt(Dummy))
252    return false; // Function header length
253
254  uint32_t GCDAIdent;
255  if (!Buff.readInt(GCDAIdent))
256    return false;
257  if (Ident != GCDAIdent) {
258    errs() << "Function identifiers do not match: " << Ident
259           << " != " << GCDAIdent << " (in " << Name << ").\n";
260    return false;
261  }
262
263  uint32_t GCDAChecksum;
264  if (!Buff.readInt(GCDAChecksum))
265    return false;
266  if (Checksum != GCDAChecksum) {
267    errs() << "Function checksums do not match: " << Checksum
268           << " != " << GCDAChecksum << " (in " << Name << ").\n";
269    return false;
270  }
271
272  uint32_t CfgChecksum;
273  if (Version != GCOV::V402) {
274    if (!Buff.readInt(CfgChecksum))
275      return false;
276    if (Parent.getChecksum() != CfgChecksum) {
277      errs() << "File checksums do not match: " << Parent.getChecksum()
278             << " != " << CfgChecksum << " (in " << Name << ").\n";
279      return false;
280    }
281  }
282
283  StringRef GCDAName;
284  if (!Buff.readString(GCDAName))
285    return false;
286  if (Name != GCDAName) {
287    errs() << "Function names do not match: " << Name << " != " << GCDAName
288           << ".\n";
289    return false;
290  }
291
292  if (!Buff.readArcTag()) {
293    errs() << "Arc tag not found (in " << Name << ").\n";
294    return false;
295  }
296
297  uint32_t Count;
298  if (!Buff.readInt(Count))
299    return false;
300  Count /= 2;
301
302  // This for loop adds the counts for each block. A second nested loop is
303  // required to combine the edge counts that are contained in the GCDA file.
304  for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) {
305    // The last block is always reserved for exit block
306    if (BlockNo >= Blocks.size()) {
307      errs() << "Unexpected number of edges (in " << Name << ").\n";
308      return false;
309    }
310    if (BlockNo == Blocks.size() - 1)
311      errs() << "(" << Name << ") has arcs from exit block.\n";
312    GCOVBlock &Block = *Blocks[BlockNo];
313    for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
314         ++EdgeNo) {
315      if (Count == 0) {
316        errs() << "Unexpected number of edges (in " << Name << ").\n";
317        return false;
318      }
319      uint64_t ArcCount;
320      if (!Buff.readInt64(ArcCount))
321        return false;
322      Block.addCount(EdgeNo, ArcCount);
323      --Count;
324    }
325    Block.sortDstEdges();
326  }
327  return true;
328}
329
330/// getEntryCount - Get the number of times the function was called by
331/// retrieving the entry block's count.
332uint64_t GCOVFunction::getEntryCount() const {
333  return Blocks.front()->getCount();
334}
335
336/// getExitCount - Get the number of times the function returned by retrieving
337/// the exit block's count.
338uint64_t GCOVFunction::getExitCount() const {
339  return Blocks.back()->getCount();
340}
341
342/// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
343void GCOVFunction::dump() const {
344  dbgs() << "===== " << Name << " (" << Ident << ") @ " << Filename << ":"
345         << LineNumber << "\n";
346  for (const auto &Block : Blocks)
347    Block->dump();
348}
349
350/// collectLineCounts - Collect line counts. This must be used after
351/// reading .gcno and .gcda files.
352void GCOVFunction::collectLineCounts(FileInfo &FI) {
353  // If the line number is zero, this is a function that doesn't actually appear
354  // in the source file, so there isn't anything we can do with it.
355  if (LineNumber == 0)
356    return;
357
358  for (const auto &Block : Blocks)
359    Block->collectLineCounts(FI);
360  FI.addFunctionLine(Filename, LineNumber, this);
361}
362
363//===----------------------------------------------------------------------===//
364// GCOVBlock implementation.
365
366/// ~GCOVBlock - Delete GCOVBlock and its content.
367GCOVBlock::~GCOVBlock() {
368  SrcEdges.clear();
369  DstEdges.clear();
370  Lines.clear();
371}
372
373/// addCount - Add to block counter while storing the edge count. If the
374/// destination has no outgoing edges, also update that block's count too.
375void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
376  assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
377  DstEdges[DstEdgeNo]->Count = N;
378  Counter += N;
379  if (!DstEdges[DstEdgeNo]->Dst.getNumDstEdges())
380    DstEdges[DstEdgeNo]->Dst.Counter += N;
381}
382
383/// sortDstEdges - Sort destination edges by block number, nop if already
384/// sorted. This is required for printing branch info in the correct order.
385void GCOVBlock::sortDstEdges() {
386  if (!DstEdgesAreSorted) {
387    SortDstEdgesFunctor SortEdges;
388    std::stable_sort(DstEdges.begin(), DstEdges.end(), SortEdges);
389  }
390}
391
392/// collectLineCounts - Collect line counts. This must be used after
393/// reading .gcno and .gcda files.
394void GCOVBlock::collectLineCounts(FileInfo &FI) {
395  for (uint32_t N : Lines)
396    FI.addBlockLine(Parent.getFilename(), N, this);
397}
398
399/// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
400void GCOVBlock::dump() const {
401  dbgs() << "Block : " << Number << " Counter : " << Counter << "\n";
402  if (!SrcEdges.empty()) {
403    dbgs() << "\tSource Edges : ";
404    for (const GCOVEdge *Edge : SrcEdges)
405      dbgs() << Edge->Src.Number << " (" << Edge->Count << "), ";
406    dbgs() << "\n";
407  }
408  if (!DstEdges.empty()) {
409    dbgs() << "\tDestination Edges : ";
410    for (const GCOVEdge *Edge : DstEdges)
411      dbgs() << Edge->Dst.Number << " (" << Edge->Count << "), ";
412    dbgs() << "\n";
413  }
414  if (!Lines.empty()) {
415    dbgs() << "\tLines : ";
416    for (uint32_t N : Lines)
417      dbgs() << (N) << ",";
418    dbgs() << "\n";
419  }
420}
421
422//===----------------------------------------------------------------------===//
423// FileInfo implementation.
424
425// Safe integer division, returns 0 if numerator is 0.
426static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) {
427  if (!Numerator)
428    return 0;
429  return Numerator / Divisor;
430}
431
432// This custom division function mimics gcov's branch ouputs:
433//   - Round to closest whole number
434//   - Only output 0% or 100% if it's exactly that value
435static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) {
436  if (!Numerator)
437    return 0;
438  if (Numerator == Divisor)
439    return 100;
440
441  uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor;
442  if (Res == 0)
443    return 1;
444  if (Res == 100)
445    return 99;
446  return Res;
447}
448
449namespace {
450struct formatBranchInfo {
451  formatBranchInfo(const GCOVOptions &Options, uint64_t Count, uint64_t Total)
452      : Options(Options), Count(Count), Total(Total) {}
453
454  void print(raw_ostream &OS) const {
455    if (!Total)
456      OS << "never executed";
457    else if (Options.BranchCount)
458      OS << "taken " << Count;
459    else
460      OS << "taken " << branchDiv(Count, Total) << "%";
461  }
462
463  const GCOVOptions &Options;
464  uint64_t Count;
465  uint64_t Total;
466};
467
468static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
469  FBI.print(OS);
470  return OS;
471}
472
473class LineConsumer {
474  std::unique_ptr<MemoryBuffer> Buffer;
475  StringRef Remaining;
476
477public:
478  LineConsumer(StringRef Filename) {
479    ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
480        MemoryBuffer::getFileOrSTDIN(Filename);
481    if (std::error_code EC = BufferOrErr.getError()) {
482      errs() << Filename << ": " << EC.message() << "\n";
483      Remaining = "";
484    } else {
485      Buffer = std::move(BufferOrErr.get());
486      Remaining = Buffer->getBuffer();
487    }
488  }
489  bool empty() { return Remaining.empty(); }
490  void printNext(raw_ostream &OS, uint32_t LineNum) {
491    StringRef Line;
492    if (empty())
493      Line = "/*EOF*/";
494    else
495      std::tie(Line, Remaining) = Remaining.split("\n");
496    OS << format("%5u:", LineNum) << Line << "\n";
497  }
498};
499}
500
501/// Convert a path to a gcov filename. If PreservePaths is true, this
502/// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
503static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
504  if (!PreservePaths)
505    return sys::path::filename(Filename).str();
506
507  // This behaviour is defined by gcov in terms of text replacements, so it's
508  // not likely to do anything useful on filesystems with different textual
509  // conventions.
510  llvm::SmallString<256> Result("");
511  StringRef::iterator I, S, E;
512  for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) {
513    if (*I != '/')
514      continue;
515
516    if (I - S == 1 && *S == '.') {
517      // ".", the current directory, is skipped.
518    } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') {
519      // "..", the parent directory, is replaced with "^".
520      Result.append("^#");
521    } else {
522      if (S < I)
523        // Leave other components intact,
524        Result.append(S, I);
525      // And separate with "#".
526      Result.push_back('#');
527    }
528    S = I + 1;
529  }
530
531  if (S < I)
532    Result.append(S, I);
533  return Result.str();
534}
535
536std::string FileInfo::getCoveragePath(StringRef Filename,
537                                      StringRef MainFilename) {
538  if (Options.NoOutput)
539    // This is probably a bug in gcov, but when -n is specified, paths aren't
540    // mangled at all, and the -l and -p options are ignored. Here, we do the
541    // same.
542    return Filename;
543
544  std::string CoveragePath;
545  if (Options.LongFileNames && !Filename.equals(MainFilename))
546    CoveragePath =
547        mangleCoveragePath(MainFilename, Options.PreservePaths) + "##";
548  CoveragePath += mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov";
549  return CoveragePath;
550}
551
552std::unique_ptr<raw_ostream>
553FileInfo::openCoveragePath(StringRef CoveragePath) {
554  if (Options.NoOutput)
555    return llvm::make_unique<raw_null_ostream>();
556
557  std::error_code EC;
558  auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath, EC,
559                                              sys::fs::F_Text);
560  if (EC) {
561    errs() << EC.message() << "\n";
562    return llvm::make_unique<raw_null_ostream>();
563  }
564  return std::move(OS);
565}
566
567/// print -  Print source files with collected line count information.
568void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
569                     StringRef GCNOFile, StringRef GCDAFile) {
570  for (const auto &LI : LineInfo) {
571    StringRef Filename = LI.first();
572    auto AllLines = LineConsumer(Filename);
573
574    std::string CoveragePath = getCoveragePath(Filename, MainFilename);
575    std::unique_ptr<raw_ostream> CovStream = openCoveragePath(CoveragePath);
576    raw_ostream &CovOS = *CovStream;
577
578    CovOS << "        -:    0:Source:" << Filename << "\n";
579    CovOS << "        -:    0:Graph:" << GCNOFile << "\n";
580    CovOS << "        -:    0:Data:" << GCDAFile << "\n";
581    CovOS << "        -:    0:Runs:" << RunCount << "\n";
582    CovOS << "        -:    0:Programs:" << ProgramCount << "\n";
583
584    const LineData &Line = LI.second;
585    GCOVCoverage FileCoverage(Filename);
586    for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || !AllLines.empty();
587         ++LineIndex) {
588      if (Options.BranchInfo) {
589        FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
590        if (FuncsIt != Line.Functions.end())
591          printFunctionSummary(CovOS, FuncsIt->second);
592      }
593
594      BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex);
595      if (BlocksIt == Line.Blocks.end()) {
596        // No basic blocks are on this line. Not an executable line of code.
597        CovOS << "        -:";
598        AllLines.printNext(CovOS, LineIndex + 1);
599      } else {
600        const BlockVector &Blocks = BlocksIt->second;
601
602        // Add up the block counts to form line counts.
603        DenseMap<const GCOVFunction *, bool> LineExecs;
604        uint64_t LineCount = 0;
605        for (const GCOVBlock *Block : Blocks) {
606          if (Options.AllBlocks) {
607            // Only take the highest block count for that line.
608            uint64_t BlockCount = Block->getCount();
609            LineCount = LineCount > BlockCount ? LineCount : BlockCount;
610          } else {
611            // Sum up all of the block counts.
612            LineCount += Block->getCount();
613          }
614
615          if (Options.FuncCoverage) {
616            // This is a slightly convoluted way to most accurately gather line
617            // statistics for functions. Basically what is happening is that we
618            // don't want to count a single line with multiple blocks more than
619            // once. However, we also don't simply want to give the total line
620            // count to every function that starts on the line. Thus, what is
621            // happening here are two things:
622            // 1) Ensure that the number of logical lines is only incremented
623            //    once per function.
624            // 2) If there are multiple blocks on the same line, ensure that the
625            //    number of lines executed is incremented as long as at least
626            //    one of the blocks are executed.
627            const GCOVFunction *Function = &Block->getParent();
628            if (FuncCoverages.find(Function) == FuncCoverages.end()) {
629              std::pair<const GCOVFunction *, GCOVCoverage> KeyValue(
630                  Function, GCOVCoverage(Function->getName()));
631              FuncCoverages.insert(KeyValue);
632            }
633            GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
634
635            if (LineExecs.find(Function) == LineExecs.end()) {
636              if (Block->getCount()) {
637                ++FuncCoverage.LinesExec;
638                LineExecs[Function] = true;
639              } else {
640                LineExecs[Function] = false;
641              }
642              ++FuncCoverage.LogicalLines;
643            } else if (!LineExecs[Function] && Block->getCount()) {
644              ++FuncCoverage.LinesExec;
645              LineExecs[Function] = true;
646            }
647          }
648        }
649
650        if (LineCount == 0)
651          CovOS << "    #####:";
652        else {
653          CovOS << format("%9" PRIu64 ":", LineCount);
654          ++FileCoverage.LinesExec;
655        }
656        ++FileCoverage.LogicalLines;
657
658        AllLines.printNext(CovOS, LineIndex + 1);
659
660        uint32_t BlockNo = 0;
661        uint32_t EdgeNo = 0;
662        for (const GCOVBlock *Block : Blocks) {
663          // Only print block and branch information at the end of the block.
664          if (Block->getLastLine() != LineIndex + 1)
665            continue;
666          if (Options.AllBlocks)
667            printBlockInfo(CovOS, *Block, LineIndex, BlockNo);
668          if (Options.BranchInfo) {
669            size_t NumEdges = Block->getNumDstEdges();
670            if (NumEdges > 1)
671              printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo);
672            else if (Options.UncondBranch && NumEdges == 1)
673              printUncondBranchInfo(CovOS, EdgeNo,
674                                    (*Block->dst_begin())->Count);
675          }
676        }
677      }
678    }
679    FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage));
680  }
681
682  // FIXME: There is no way to detect calls given current instrumentation.
683  if (Options.FuncCoverage)
684    printFuncCoverage(InfoOS);
685  printFileCoverage(InfoOS);
686  return;
687}
688
689/// printFunctionSummary - Print function and block summary.
690void FileInfo::printFunctionSummary(raw_ostream &OS,
691                                    const FunctionVector &Funcs) const {
692  for (const GCOVFunction *Func : Funcs) {
693    uint64_t EntryCount = Func->getEntryCount();
694    uint32_t BlocksExec = 0;
695    for (const GCOVBlock &Block : Func->blocks())
696      if (Block.getNumDstEdges() && Block.getCount())
697        ++BlocksExec;
698
699    OS << "function " << Func->getName() << " called " << EntryCount
700       << " returned " << safeDiv(Func->getExitCount() * 100, EntryCount)
701       << "% blocks executed "
702       << safeDiv(BlocksExec * 100, Func->getNumBlocks() - 1) << "%\n";
703  }
704}
705
706/// printBlockInfo - Output counts for each block.
707void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
708                              uint32_t LineIndex, uint32_t &BlockNo) const {
709  if (Block.getCount() == 0)
710    OS << "    $$$$$:";
711  else
712    OS << format("%9" PRIu64 ":", Block.getCount());
713  OS << format("%5u-block %2u\n", LineIndex + 1, BlockNo++);
714}
715
716/// printBranchInfo - Print conditional branch probabilities.
717void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
718                               GCOVCoverage &Coverage, uint32_t &EdgeNo) {
719  SmallVector<uint64_t, 16> BranchCounts;
720  uint64_t TotalCounts = 0;
721  for (const GCOVEdge *Edge : Block.dsts()) {
722    BranchCounts.push_back(Edge->Count);
723    TotalCounts += Edge->Count;
724    if (Block.getCount())
725      ++Coverage.BranchesExec;
726    if (Edge->Count)
727      ++Coverage.BranchesTaken;
728    ++Coverage.Branches;
729
730    if (Options.FuncCoverage) {
731      const GCOVFunction *Function = &Block.getParent();
732      GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
733      if (Block.getCount())
734        ++FuncCoverage.BranchesExec;
735      if (Edge->Count)
736        ++FuncCoverage.BranchesTaken;
737      ++FuncCoverage.Branches;
738    }
739  }
740
741  for (uint64_t N : BranchCounts)
742    OS << format("branch %2u ", EdgeNo++)
743       << formatBranchInfo(Options, N, TotalCounts) << "\n";
744}
745
746/// printUncondBranchInfo - Print unconditional branch probabilities.
747void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
748                                     uint64_t Count) const {
749  OS << format("unconditional %2u ", EdgeNo++)
750     << formatBranchInfo(Options, Count, Count) << "\n";
751}
752
753// printCoverage - Print generic coverage info used by both printFuncCoverage
754// and printFileCoverage.
755void FileInfo::printCoverage(raw_ostream &OS,
756                             const GCOVCoverage &Coverage) const {
757  OS << format("Lines executed:%.2f%% of %u\n",
758               double(Coverage.LinesExec) * 100 / Coverage.LogicalLines,
759               Coverage.LogicalLines);
760  if (Options.BranchInfo) {
761    if (Coverage.Branches) {
762      OS << format("Branches executed:%.2f%% of %u\n",
763                   double(Coverage.BranchesExec) * 100 / Coverage.Branches,
764                   Coverage.Branches);
765      OS << format("Taken at least once:%.2f%% of %u\n",
766                   double(Coverage.BranchesTaken) * 100 / Coverage.Branches,
767                   Coverage.Branches);
768    } else {
769      OS << "No branches\n";
770    }
771    OS << "No calls\n"; // to be consistent with gcov
772  }
773}
774
775// printFuncCoverage - Print per-function coverage info.
776void FileInfo::printFuncCoverage(raw_ostream &OS) const {
777  for (const auto &FC : FuncCoverages) {
778    const GCOVCoverage &Coverage = FC.second;
779    OS << "Function '" << Coverage.Name << "'\n";
780    printCoverage(OS, Coverage);
781    OS << "\n";
782  }
783}
784
785// printFileCoverage - Print per-file coverage info.
786void FileInfo::printFileCoverage(raw_ostream &OS) const {
787  for (const auto &FC : FileCoverages) {
788    const std::string &Filename = FC.first;
789    const GCOVCoverage &Coverage = FC.second;
790    OS << "File '" << Coverage.Name << "'\n";
791    printCoverage(OS, Coverage);
792    if (!Options.NoOutput)
793      OS << Coverage.Name << ":creating '" << Filename << "'\n";
794    OS << "\n";
795  }
796}
797