LCOV - code coverage report
Current view: top level - lib/IR - GCOV.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 376 425 88.5 %
Date: 2017-09-14 15:23:50 Functions: 29 29 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13