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

Generated by: LCOV version 1.13