]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/IR/GCOV.cpp
Merge ^/head r313055 through r313300.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / IR / GCOV.cpp
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/Path.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <algorithm>
23 #include <system_error>
24
25 using namespace llvm;
26
27 //===----------------------------------------------------------------------===//
28 // GCOVFile implementation.
29
30 /// readGCNO - Read GCNO buffer.
31 bool 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().
54 bool 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.
107 LLVM_DUMP_METHOD void 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.
114 void 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.
126 bool 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.
249 bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
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.
347 LLVM_DUMP_METHOD void GCOVFunction::dump() const {
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.
356 void GCOVFunction::collectLineCounts(FileInfo &FI) {
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.
371 GCOVBlock::~GCOVBlock() {
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.
389 void GCOVBlock::sortDstEdges() {
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.
398 void GCOVBlock::collectLineCounts(FileInfo &FI) {
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.
404 LLVM_DUMP_METHOD void GCOVBlock::dump() const {
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) {
483     ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
484         MemoryBuffer::getFileOrSTDIN(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,
563                                               sys::fs::F_Text);
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.
607         DenseMap<const GCOVFunction *, bool> LineExecs;
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 }