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

Generated by: LCOV version 1.13