Home | History | Annotate | Line # | Download | only in ProfileData
      1 //===- GCOV.cpp - LLVM coverage tool --------------------------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // GCOV implements the interface to read and write coverage files that use
     10 // 'gcov' format.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/ProfileData/GCOV.h"
     15 #include "llvm/ADT/STLExtras.h"
     16 #include "llvm/Config/llvm-config.h"
     17 #include "llvm/Demangle/Demangle.h"
     18 #include "llvm/Support/Debug.h"
     19 #include "llvm/Support/FileSystem.h"
     20 #include "llvm/Support/Format.h"
     21 #include "llvm/Support/MD5.h"
     22 #include "llvm/Support/Path.h"
     23 #include "llvm/Support/raw_ostream.h"
     24 #include <algorithm>
     25 #include <system_error>
     26 #include <unordered_map>
     27 
     28 using namespace llvm;
     29 
     30 enum : uint32_t {
     31   GCOV_ARC_ON_TREE = 1 << 0,
     32   GCOV_ARC_FALLTHROUGH = 1 << 2,
     33 
     34   GCOV_TAG_FUNCTION = 0x01000000,
     35   GCOV_TAG_BLOCKS = 0x01410000,
     36   GCOV_TAG_ARCS = 0x01430000,
     37   GCOV_TAG_LINES = 0x01450000,
     38   GCOV_TAG_COUNTER_ARCS = 0x01a10000,
     39   // GCOV_TAG_OBJECT_SUMMARY superseded GCOV_TAG_PROGRAM_SUMMARY in GCC 9.
     40   GCOV_TAG_OBJECT_SUMMARY = 0xa1000000,
     41   GCOV_TAG_PROGRAM_SUMMARY = 0xa3000000,
     42 };
     43 
     44 namespace {
     45 struct Summary {
     46   Summary(StringRef Name) : Name(Name) {}
     47 
     48   StringRef Name;
     49   uint64_t lines = 0;
     50   uint64_t linesExec = 0;
     51   uint64_t branches = 0;
     52   uint64_t branchesExec = 0;
     53   uint64_t branchesTaken = 0;
     54 };
     55 
     56 struct LineInfo {
     57   SmallVector<const GCOVBlock *, 1> blocks;
     58   uint64_t count = 0;
     59   bool exists = false;
     60 };
     61 
     62 struct SourceInfo {
     63   StringRef filename;
     64   SmallString<0> displayName;
     65   std::vector<std::vector<const GCOVFunction *>> startLineToFunctions;
     66   std::vector<LineInfo> lines;
     67   bool ignored = false;
     68   SourceInfo(StringRef filename) : filename(filename) {}
     69 };
     70 
     71 class Context {
     72 public:
     73   Context(const GCOV::Options &Options) : options(Options) {}
     74   void print(StringRef filename, StringRef gcno, StringRef gcda,
     75              GCOVFile &file);
     76 
     77 private:
     78   std::string getCoveragePath(StringRef filename, StringRef mainFilename) const;
     79   void printFunctionDetails(const GCOVFunction &f, raw_ostream &os) const;
     80   void printBranchInfo(const GCOVBlock &Block, uint32_t &edgeIdx,
     81                        raw_ostream &OS) const;
     82   void printSummary(const Summary &summary, raw_ostream &os) const;
     83 
     84   void collectFunction(GCOVFunction &f, Summary &summary);
     85   void collectSourceLine(SourceInfo &si, Summary *summary, LineInfo &line,
     86                          size_t lineNum) const;
     87   void collectSource(SourceInfo &si, Summary &summary) const;
     88   void annotateSource(SourceInfo &si, const GCOVFile &file, StringRef gcno,
     89                       StringRef gcda, raw_ostream &os) const;
     90   void printSourceToIntermediate(const SourceInfo &si, raw_ostream &os) const;
     91 
     92   const GCOV::Options &options;
     93   std::vector<SourceInfo> sources;
     94 };
     95 } // namespace
     96 
     97 //===----------------------------------------------------------------------===//
     98 // GCOVFile implementation.
     99 
    100 /// readGCNO - Read GCNO buffer.
    101 bool GCOVFile::readGCNO(GCOVBuffer &buf) {
    102   if (!buf.readGCNOFormat())
    103     return false;
    104   if (!buf.readGCOVVersion(Version))
    105     return false;
    106 
    107   Checksum = buf.getWord();
    108   if (Version >= GCOV::V900)
    109     cwd = buf.getString();
    110   if (Version >= GCOV::V800)
    111     buf.getWord(); // hasUnexecutedBlocks
    112 
    113   uint32_t tag, length;
    114   GCOVFunction *fn = nullptr;
    115   while ((tag = buf.getWord())) {
    116     if (!buf.readInt(length))
    117       return false;
    118     if (tag == GCOV_TAG_FUNCTION) {
    119       functions.push_back(std::make_unique<GCOVFunction>(*this));
    120       fn = functions.back().get();
    121       fn->ident = buf.getWord();
    122       fn->linenoChecksum = buf.getWord();
    123       if (Version >= GCOV::V407)
    124         fn->cfgChecksum = buf.getWord();
    125       buf.readString(fn->Name);
    126       StringRef filename;
    127       if (Version < GCOV::V800) {
    128         filename = buf.getString();
    129         fn->startLine = buf.getWord();
    130       } else {
    131         fn->artificial = buf.getWord();
    132         filename = buf.getString();
    133         fn->startLine = buf.getWord();
    134         fn->startColumn = buf.getWord();
    135         fn->endLine = buf.getWord();
    136         if (Version >= GCOV::V900)
    137           fn->endColumn = buf.getWord();
    138       }
    139       auto r = filenameToIdx.try_emplace(filename, filenameToIdx.size());
    140       if (r.second)
    141         filenames.emplace_back(filename);
    142       fn->srcIdx = r.first->second;
    143       IdentToFunction[fn->ident] = fn;
    144     } else if (tag == GCOV_TAG_BLOCKS && fn) {
    145       if (Version < GCOV::V800) {
    146         for (uint32_t i = 0; i != length; ++i) {
    147           buf.getWord(); // Ignored block flags
    148           fn->blocks.push_back(std::make_unique<GCOVBlock>(i));
    149         }
    150       } else {
    151         uint32_t num = buf.getWord();
    152         for (uint32_t i = 0; i != num; ++i)
    153           fn->blocks.push_back(std::make_unique<GCOVBlock>(i));
    154       }
    155     } else if (tag == GCOV_TAG_ARCS && fn) {
    156       uint32_t srcNo = buf.getWord();
    157       if (srcNo >= fn->blocks.size()) {
    158         errs() << "unexpected block number: " << srcNo << " (in "
    159                << fn->blocks.size() << ")\n";
    160         return false;
    161       }
    162       GCOVBlock *src = fn->blocks[srcNo].get();
    163       for (uint32_t i = 0, e = (length - 1) / 2; i != e; ++i) {
    164         uint32_t dstNo = buf.getWord(), flags = buf.getWord();
    165         GCOVBlock *dst = fn->blocks[dstNo].get();
    166         auto arc = std::make_unique<GCOVArc>(*src, *dst, flags);
    167         src->addDstEdge(arc.get());
    168         dst->addSrcEdge(arc.get());
    169         if (arc->onTree())
    170           fn->treeArcs.push_back(std::move(arc));
    171         else
    172           fn->arcs.push_back(std::move(arc));
    173       }
    174     } else if (tag == GCOV_TAG_LINES && fn) {
    175       uint32_t srcNo = buf.getWord();
    176       if (srcNo >= fn->blocks.size()) {
    177         errs() << "unexpected block number: " << srcNo << " (in "
    178                << fn->blocks.size() << ")\n";
    179         return false;
    180       }
    181       GCOVBlock &Block = *fn->blocks[srcNo];
    182       for (;;) {
    183         uint32_t line = buf.getWord();
    184         if (line)
    185           Block.addLine(line);
    186         else {
    187           StringRef filename = buf.getString();
    188           if (filename.empty())
    189             break;
    190           // TODO Unhandled
    191         }
    192       }
    193     }
    194   }
    195 
    196   GCNOInitialized = true;
    197   return true;
    198 }
    199 
    200 /// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
    201 /// called after readGCNO().
    202 bool GCOVFile::readGCDA(GCOVBuffer &buf) {
    203   assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
    204   if (!buf.readGCDAFormat())
    205     return false;
    206   GCOV::GCOVVersion GCDAVersion;
    207   if (!buf.readGCOVVersion(GCDAVersion))
    208     return false;
    209   if (Version != GCDAVersion) {
    210     errs() << "GCOV versions do not match.\n";
    211     return false;
    212   }
    213 
    214   uint32_t GCDAChecksum;
    215   if (!buf.readInt(GCDAChecksum))
    216     return false;
    217   if (Checksum != GCDAChecksum) {
    218     errs() << "File checksums do not match: " << Checksum
    219            << " != " << GCDAChecksum << ".\n";
    220     return false;
    221   }
    222   uint32_t dummy, tag, length;
    223   uint32_t ident;
    224   GCOVFunction *fn = nullptr;
    225   while ((tag = buf.getWord())) {
    226     if (!buf.readInt(length))
    227       return false;
    228     uint32_t pos = buf.cursor.tell();
    229     if (tag == GCOV_TAG_OBJECT_SUMMARY) {
    230       buf.readInt(RunCount);
    231       buf.readInt(dummy);
    232       // clang<11 uses a fake 4.2 format which sets length to 9.
    233       if (length == 9)
    234         buf.readInt(RunCount);
    235     } else if (tag == GCOV_TAG_PROGRAM_SUMMARY) {
    236       // clang<11 uses a fake 4.2 format which sets length to 0.
    237       if (length > 0) {
    238         buf.readInt(dummy);
    239         buf.readInt(dummy);
    240         buf.readInt(RunCount);
    241       }
    242       ++ProgramCount;
    243     } else if (tag == GCOV_TAG_FUNCTION) {
    244       if (length == 0) // Placeholder
    245         continue;
    246       // As of GCC 10, GCOV_TAG_FUNCTION_LENGTH has never been larger than 3.
    247       // However, clang<11 uses a fake 4.2 format which may set length larger
    248       // than 3.
    249       if (length < 2 || !buf.readInt(ident))
    250         return false;
    251       auto It = IdentToFunction.find(ident);
    252       uint32_t linenoChecksum, cfgChecksum = 0;
    253       buf.readInt(linenoChecksum);
    254       if (Version >= GCOV::V407)
    255         buf.readInt(cfgChecksum);
    256       if (It != IdentToFunction.end()) {
    257         fn = It->second;
    258         if (linenoChecksum != fn->linenoChecksum ||
    259             cfgChecksum != fn->cfgChecksum) {
    260           errs() << fn->Name
    261                  << format(": checksum mismatch, (%u, %u) != (%u, %u)\n",
    262                            linenoChecksum, cfgChecksum, fn->linenoChecksum,
    263                            fn->cfgChecksum);
    264           return false;
    265         }
    266       }
    267     } else if (tag == GCOV_TAG_COUNTER_ARCS && fn) {
    268       if (length != 2 * fn->arcs.size()) {
    269         errs() << fn->Name
    270                << format(
    271                       ": GCOV_TAG_COUNTER_ARCS mismatch, got %u, expected %u\n",
    272                       length, unsigned(2 * fn->arcs.size()));
    273         return false;
    274       }
    275       for (std::unique_ptr<GCOVArc> &arc : fn->arcs) {
    276         if (!buf.readInt64(arc->count))
    277           return false;
    278         arc->src.count += arc->count;
    279       }
    280 
    281       if (fn->blocks.size() >= 2) {
    282         GCOVBlock &src = *fn->blocks[0];
    283         GCOVBlock &sink =
    284             Version < GCOV::V408 ? *fn->blocks.back() : *fn->blocks[1];
    285         auto arc = std::make_unique<GCOVArc>(sink, src, GCOV_ARC_ON_TREE);
    286         sink.addDstEdge(arc.get());
    287         src.addSrcEdge(arc.get());
    288         fn->treeArcs.push_back(std::move(arc));
    289 
    290         for (GCOVBlock &block : fn->blocksRange())
    291           fn->propagateCounts(block, nullptr);
    292         for (size_t i = fn->treeArcs.size() - 1; i; --i)
    293           fn->treeArcs[i - 1]->src.count += fn->treeArcs[i - 1]->count;
    294       }
    295     }
    296     pos += 4 * length;
    297     if (pos < buf.cursor.tell())
    298       return false;
    299     buf.de.skip(buf.cursor, pos - buf.cursor.tell());
    300   }
    301 
    302   return true;
    303 }
    304 
    305 void GCOVFile::print(raw_ostream &OS) const {
    306   for (const GCOVFunction &f : *this)
    307     f.print(OS);
    308 }
    309 
    310 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    311 /// dump - Dump GCOVFile content to dbgs() for debugging purposes.
    312 LLVM_DUMP_METHOD void GCOVFile::dump() const { print(dbgs()); }
    313 #endif
    314 
    315 bool GCOVArc::onTree() const { return flags & GCOV_ARC_ON_TREE; }
    316 
    317 //===----------------------------------------------------------------------===//
    318 // GCOVFunction implementation.
    319 
    320 StringRef GCOVFunction::getName(bool demangle) const {
    321   if (!demangle)
    322     return Name;
    323   if (demangled.empty()) {
    324     do {
    325       if (Name.startswith("_Z")) {
    326         int status = 0;
    327         // Name is guaranteed to be NUL-terminated.
    328         char *res = itaniumDemangle(Name.data(), nullptr, nullptr, &status);
    329         if (status == 0) {
    330           demangled = res;
    331           free(res);
    332           break;
    333         }
    334       }
    335       demangled = Name;
    336     } while (0);
    337   }
    338   return demangled;
    339 }
    340 StringRef GCOVFunction::getFilename() const { return file.filenames[srcIdx]; }
    341 
    342 /// getEntryCount - Get the number of times the function was called by
    343 /// retrieving the entry block's count.
    344 uint64_t GCOVFunction::getEntryCount() const {
    345   return blocks.front()->getCount();
    346 }
    347 
    348 GCOVBlock &GCOVFunction::getExitBlock() const {
    349   return file.getVersion() < GCOV::V408 ? *blocks.back() : *blocks[1];
    350 }
    351 
    352 // For each basic block, the sum of incoming edge counts equals the sum of
    353 // outgoing edge counts by Kirchoff's circuit law. If the unmeasured arcs form a
    354 // spanning tree, the count for each unmeasured arc (GCOV_ARC_ON_TREE) can be
    355 // uniquely identified.
    356 uint64_t GCOVFunction::propagateCounts(const GCOVBlock &v, GCOVArc *pred) {
    357   // If GCOV_ARC_ON_TREE edges do form a tree, visited is not needed; otherwise
    358   // this prevents infinite recursion.
    359   if (!visited.insert(&v).second)
    360     return 0;
    361 
    362   uint64_t excess = 0;
    363   for (GCOVArc *e : v.srcs())
    364     if (e != pred)
    365       excess += e->onTree() ? propagateCounts(e->src, e) : e->count;
    366   for (GCOVArc *e : v.dsts())
    367     if (e != pred)
    368       excess -= e->onTree() ? propagateCounts(e->dst, e) : e->count;
    369   if (int64_t(excess) < 0)
    370     excess = -excess;
    371   if (pred)
    372     pred->count = excess;
    373   return excess;
    374 }
    375 
    376 void GCOVFunction::print(raw_ostream &OS) const {
    377   OS << "===== " << Name << " (" << ident << ") @ " << getFilename() << ":"
    378      << startLine << "\n";
    379   for (const auto &Block : blocks)
    380     Block->print(OS);
    381 }
    382 
    383 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    384 /// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
    385 LLVM_DUMP_METHOD void GCOVFunction::dump() const { print(dbgs()); }
    386 #endif
    387 
    388 /// collectLineCounts - Collect line counts. This must be used after
    389 /// reading .gcno and .gcda files.
    390 
    391 //===----------------------------------------------------------------------===//
    392 // GCOVBlock implementation.
    393 
    394 void GCOVBlock::print(raw_ostream &OS) const {
    395   OS << "Block : " << number << " Counter : " << count << "\n";
    396   if (!pred.empty()) {
    397     OS << "\tSource Edges : ";
    398     for (const GCOVArc *Edge : pred)
    399       OS << Edge->src.number << " (" << Edge->count << "), ";
    400     OS << "\n";
    401   }
    402   if (!succ.empty()) {
    403     OS << "\tDestination Edges : ";
    404     for (const GCOVArc *Edge : succ) {
    405       if (Edge->flags & GCOV_ARC_ON_TREE)
    406         OS << '*';
    407       OS << Edge->dst.number << " (" << Edge->count << "), ";
    408     }
    409     OS << "\n";
    410   }
    411   if (!lines.empty()) {
    412     OS << "\tLines : ";
    413     for (uint32_t N : lines)
    414       OS << (N) << ",";
    415     OS << "\n";
    416   }
    417 }
    418 
    419 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    420 /// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
    421 LLVM_DUMP_METHOD void GCOVBlock::dump() const { print(dbgs()); }
    422 #endif
    423 
    424 uint64_t
    425 GCOVBlock::augmentOneCycle(GCOVBlock *src,
    426                            std::vector<std::pair<GCOVBlock *, size_t>> &stack) {
    427   GCOVBlock *u;
    428   size_t i;
    429   stack.clear();
    430   stack.emplace_back(src, 0);
    431   src->incoming = (GCOVArc *)1; // Mark u available for cycle detection
    432   for (;;) {
    433     std::tie(u, i) = stack.back();
    434     if (i == u->succ.size()) {
    435       u->traversable = false;
    436       stack.pop_back();
    437       if (stack.empty())
    438         break;
    439       continue;
    440     }
    441     ++stack.back().second;
    442     GCOVArc *succ = u->succ[i];
    443     // Ignore saturated arcs (cycleCount has been reduced to 0) and visited
    444     // blocks. Ignore self arcs to guard against bad input (.gcno has no
    445     // self arcs).
    446     if (succ->cycleCount == 0 || !succ->dst.traversable || &succ->dst == u)
    447       continue;
    448     if (succ->dst.incoming == nullptr) {
    449       succ->dst.incoming = succ;
    450       stack.emplace_back(&succ->dst, 0);
    451       continue;
    452     }
    453     uint64_t minCount = succ->cycleCount;
    454     for (GCOVBlock *v = u;;) {
    455       minCount = std::min(minCount, v->incoming->cycleCount);
    456       v = &v->incoming->src;
    457       if (v == &succ->dst)
    458         break;
    459     }
    460     succ->cycleCount -= minCount;
    461     for (GCOVBlock *v = u;;) {
    462       v->incoming->cycleCount -= minCount;
    463       v = &v->incoming->src;
    464       if (v == &succ->dst)
    465         break;
    466     }
    467     return minCount;
    468   }
    469   return 0;
    470 }
    471 
    472 // Get the total execution count of loops among blocks on the same line.
    473 // Assuming a reducible flow graph, the count is the sum of back edge counts.
    474 // Identifying loops is complex, so we simply find cycles and perform cycle
    475 // cancelling iteratively.
    476 uint64_t GCOVBlock::getCyclesCount(const BlockVector &blocks) {
    477   std::vector<std::pair<GCOVBlock *, size_t>> stack;
    478   uint64_t count = 0, d;
    479   for (;;) {
    480     // Make blocks on the line traversable and try finding a cycle.
    481     for (auto b : blocks) {
    482       const_cast<GCOVBlock *>(b)->traversable = true;
    483       const_cast<GCOVBlock *>(b)->incoming = nullptr;
    484     }
    485     d = 0;
    486     for (auto block : blocks) {
    487       auto *b = const_cast<GCOVBlock *>(block);
    488       if (b->traversable && (d = augmentOneCycle(b, stack)) > 0)
    489         break;
    490     }
    491     if (d == 0)
    492       break;
    493     count += d;
    494   }
    495   // If there is no more loop, all traversable bits should have been cleared.
    496   // This property is needed by subsequent calls.
    497   for (auto b : blocks) {
    498     assert(!b->traversable);
    499     (void)b;
    500   }
    501   return count;
    502 }
    503 
    504 //===----------------------------------------------------------------------===//
    505 // FileInfo implementation.
    506 
    507 // Format dividend/divisor as a percentage. Return 1 if the result is greater
    508 // than 0% and less than 1%.
    509 static uint32_t formatPercentage(uint64_t dividend, uint64_t divisor) {
    510   if (!dividend || !divisor)
    511     return 0;
    512   dividend *= 100;
    513   return dividend < divisor ? 1 : dividend / divisor;
    514 }
    515 
    516 // This custom division function mimics gcov's branch ouputs:
    517 //   - Round to closest whole number
    518 //   - Only output 0% or 100% if it's exactly that value
    519 static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) {
    520   if (!Numerator)
    521     return 0;
    522   if (Numerator == Divisor)
    523     return 100;
    524 
    525   uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor;
    526   if (Res == 0)
    527     return 1;
    528   if (Res == 100)
    529     return 99;
    530   return Res;
    531 }
    532 
    533 namespace {
    534 struct formatBranchInfo {
    535   formatBranchInfo(const GCOV::Options &Options, uint64_t Count, uint64_t Total)
    536       : Options(Options), Count(Count), Total(Total) {}
    537 
    538   void print(raw_ostream &OS) const {
    539     if (!Total)
    540       OS << "never executed";
    541     else if (Options.BranchCount)
    542       OS << "taken " << Count;
    543     else
    544       OS << "taken " << branchDiv(Count, Total) << "%";
    545   }
    546 
    547   const GCOV::Options &Options;
    548   uint64_t Count;
    549   uint64_t Total;
    550 };
    551 
    552 static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
    553   FBI.print(OS);
    554   return OS;
    555 }
    556 
    557 class LineConsumer {
    558   std::unique_ptr<MemoryBuffer> Buffer;
    559   StringRef Remaining;
    560 
    561 public:
    562   LineConsumer() = default;
    563   LineConsumer(StringRef Filename) {
    564     // Open source files without requiring a NUL terminator. The concurrent
    565     // modification may nullify the NUL terminator condition.
    566     ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
    567         MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/false,
    568                                      /*RequiresNullTerminator=*/false);
    569     if (std::error_code EC = BufferOrErr.getError()) {
    570       errs() << Filename << ": " << EC.message() << "\n";
    571       Remaining = "";
    572     } else {
    573       Buffer = std::move(BufferOrErr.get());
    574       Remaining = Buffer->getBuffer();
    575     }
    576   }
    577   bool empty() { return Remaining.empty(); }
    578   void printNext(raw_ostream &OS, uint32_t LineNum) {
    579     StringRef Line;
    580     if (empty())
    581       Line = "/*EOF*/";
    582     else
    583       std::tie(Line, Remaining) = Remaining.split("\n");
    584     OS << format("%5u:", LineNum) << Line << "\n";
    585   }
    586 };
    587 } // end anonymous namespace
    588 
    589 /// Convert a path to a gcov filename. If PreservePaths is true, this
    590 /// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
    591 static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
    592   if (!PreservePaths)
    593     return sys::path::filename(Filename).str();
    594 
    595   // This behaviour is defined by gcov in terms of text replacements, so it's
    596   // not likely to do anything useful on filesystems with different textual
    597   // conventions.
    598   llvm::SmallString<256> Result("");
    599   StringRef::iterator I, S, E;
    600   for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) {
    601     if (*I != '/')
    602       continue;
    603 
    604     if (I - S == 1 && *S == '.') {
    605       // ".", the current directory, is skipped.
    606     } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') {
    607       // "..", the parent directory, is replaced with "^".
    608       Result.append("^#");
    609     } else {
    610       if (S < I)
    611         // Leave other components intact,
    612         Result.append(S, I);
    613       // And separate with "#".
    614       Result.push_back('#');
    615     }
    616     S = I + 1;
    617   }
    618 
    619   if (S < I)
    620     Result.append(S, I);
    621   return std::string(Result.str());
    622 }
    623 
    624 std::string Context::getCoveragePath(StringRef filename,
    625                                      StringRef mainFilename) const {
    626   if (options.NoOutput)
    627     // This is probably a bug in gcov, but when -n is specified, paths aren't
    628     // mangled at all, and the -l and -p options are ignored. Here, we do the
    629     // same.
    630     return std::string(filename);
    631 
    632   std::string CoveragePath;
    633   if (options.LongFileNames && !filename.equals(mainFilename))
    634     CoveragePath =
    635         mangleCoveragePath(mainFilename, options.PreservePaths) + "##";
    636   CoveragePath += mangleCoveragePath(filename, options.PreservePaths);
    637   if (options.HashFilenames) {
    638     MD5 Hasher;
    639     MD5::MD5Result Result;
    640     Hasher.update(filename.str());
    641     Hasher.final(Result);
    642     CoveragePath += "##" + std::string(Result.digest());
    643   }
    644   CoveragePath += ".gcov";
    645   return CoveragePath;
    646 }
    647 
    648 void Context::collectFunction(GCOVFunction &f, Summary &summary) {
    649   SourceInfo &si = sources[f.srcIdx];
    650   if (f.startLine >= si.startLineToFunctions.size())
    651     si.startLineToFunctions.resize(f.startLine + 1);
    652   si.startLineToFunctions[f.startLine].push_back(&f);
    653   for (const GCOVBlock &b : f.blocksRange()) {
    654     if (b.lines.empty())
    655       continue;
    656     uint32_t maxLineNum = *std::max_element(b.lines.begin(), b.lines.end());
    657     if (maxLineNum >= si.lines.size())
    658       si.lines.resize(maxLineNum + 1);
    659     for (uint32_t lineNum : b.lines) {
    660       LineInfo &line = si.lines[lineNum];
    661       if (!line.exists)
    662         ++summary.lines;
    663       if (line.count == 0 && b.count)
    664         ++summary.linesExec;
    665       line.exists = true;
    666       line.count += b.count;
    667       line.blocks.push_back(&b);
    668     }
    669   }
    670 }
    671 
    672 void Context::collectSourceLine(SourceInfo &si, Summary *summary,
    673                                 LineInfo &line, size_t lineNum) const {
    674   uint64_t count = 0;
    675   for (const GCOVBlock *b : line.blocks) {
    676     if (b->number == 0) {
    677       // For nonstandard control flows, arcs into the exit block may be
    678       // duplicately counted (fork) or not be counted (abnormal exit), and thus
    679       // the (exit,entry) counter may be inaccurate. Count the entry block with
    680       // the outgoing arcs.
    681       for (const GCOVArc *arc : b->succ)
    682         count += arc->count;
    683     } else {
    684       // Add counts from predecessors that are not on the same line.
    685       for (const GCOVArc *arc : b->pred)
    686         if (!llvm::is_contained(line.blocks, &arc->src))
    687           count += arc->count;
    688     }
    689     for (GCOVArc *arc : b->succ)
    690       arc->cycleCount = arc->count;
    691   }
    692 
    693   count += GCOVBlock::getCyclesCount(line.blocks);
    694   line.count = count;
    695   if (line.exists) {
    696     ++summary->lines;
    697     if (line.count != 0)
    698       ++summary->linesExec;
    699   }
    700 
    701   if (options.BranchInfo)
    702     for (const GCOVBlock *b : line.blocks) {
    703       if (b->getLastLine() != lineNum)
    704         continue;
    705       int branches = 0, execBranches = 0, takenBranches = 0;
    706       for (const GCOVArc *arc : b->succ) {
    707         ++branches;
    708         if (count != 0)
    709           ++execBranches;
    710         if (arc->count != 0)
    711           ++takenBranches;
    712       }
    713       if (branches > 1) {
    714         summary->branches += branches;
    715         summary->branchesExec += execBranches;
    716         summary->branchesTaken += takenBranches;
    717       }
    718     }
    719 }
    720 
    721 void Context::collectSource(SourceInfo &si, Summary &summary) const {
    722   size_t lineNum = 0;
    723   for (LineInfo &line : si.lines) {
    724     collectSourceLine(si, &summary, line, lineNum);
    725     ++lineNum;
    726   }
    727 }
    728 
    729 void Context::annotateSource(SourceInfo &si, const GCOVFile &file,
    730                              StringRef gcno, StringRef gcda,
    731                              raw_ostream &os) const {
    732   auto source =
    733       options.Intermediate ? LineConsumer() : LineConsumer(si.filename);
    734 
    735   os << "        -:    0:Source:" << si.displayName << '\n';
    736   os << "        -:    0:Graph:" << gcno << '\n';
    737   os << "        -:    0:Data:" << gcda << '\n';
    738   os << "        -:    0:Runs:" << file.RunCount << '\n';
    739   if (file.Version < GCOV::V900)
    740     os << "        -:    0:Programs:" << file.ProgramCount << '\n';
    741 
    742   for (size_t lineNum = 1; !source.empty(); ++lineNum) {
    743     if (lineNum >= si.lines.size()) {
    744       os << "        -:";
    745       source.printNext(os, lineNum);
    746       continue;
    747     }
    748 
    749     const LineInfo &line = si.lines[lineNum];
    750     if (options.BranchInfo && lineNum < si.startLineToFunctions.size())
    751       for (const auto *f : si.startLineToFunctions[lineNum])
    752         printFunctionDetails(*f, os);
    753     if (!line.exists)
    754       os << "        -:";
    755     else if (line.count == 0)
    756       os << "    #####:";
    757     else
    758       os << format("%9" PRIu64 ":", line.count);
    759     source.printNext(os, lineNum);
    760 
    761     uint32_t blockIdx = 0, edgeIdx = 0;
    762     for (const GCOVBlock *b : line.blocks) {
    763       if (b->getLastLine() != lineNum)
    764         continue;
    765       if (options.AllBlocks) {
    766         if (b->getCount() == 0)
    767           os << "    $$$$$:";
    768         else
    769           os << format("%9" PRIu64 ":", b->count);
    770         os << format("%5u-block %2u\n", lineNum, blockIdx++);
    771       }
    772       if (options.BranchInfo) {
    773         size_t NumEdges = b->succ.size();
    774         if (NumEdges > 1)
    775           printBranchInfo(*b, edgeIdx, os);
    776         else if (options.UncondBranch && NumEdges == 1) {
    777           uint64_t count = b->succ[0]->count;
    778           os << format("unconditional %2u ", edgeIdx++)
    779              << formatBranchInfo(options, count, count) << '\n';
    780         }
    781       }
    782     }
    783   }
    784 }
    785 
    786 void Context::printSourceToIntermediate(const SourceInfo &si,
    787                                         raw_ostream &os) const {
    788   os << "file:" << si.filename << '\n';
    789   for (const auto &fs : si.startLineToFunctions)
    790     for (const GCOVFunction *f : fs)
    791       os << "function:" << f->startLine << ',' << f->getEntryCount() << ','
    792          << f->getName(options.Demangle) << '\n';
    793   for (size_t lineNum = 1, size = si.lines.size(); lineNum < size; ++lineNum) {
    794     const LineInfo &line = si.lines[lineNum];
    795     if (line.blocks.empty())
    796       continue;
    797     // GCC 8 (r254259) added third third field for Ada:
    798     // lcount:<line>,<count>,<has_unexecuted_blocks>
    799     // We don't need the third field.
    800     os << "lcount:" << lineNum << ',' << line.count << '\n';
    801 
    802     if (!options.BranchInfo)
    803       continue;
    804     for (const GCOVBlock *b : line.blocks) {
    805       if (b->succ.size() < 2 || b->getLastLine() != lineNum)
    806         continue;
    807       for (const GCOVArc *arc : b->succ) {
    808         const char *type =
    809             b->getCount() ? arc->count ? "taken" : "nottaken" : "notexec";
    810         os << "branch:" << lineNum << ',' << type << '\n';
    811       }
    812     }
    813   }
    814 }
    815 
    816 void Context::print(StringRef filename, StringRef gcno, StringRef gcda,
    817                     GCOVFile &file) {
    818   for (StringRef filename : file.filenames) {
    819     sources.emplace_back(filename);
    820     SourceInfo &si = sources.back();
    821     si.displayName = si.filename;
    822     if (!options.SourcePrefix.empty() &&
    823         sys::path::replace_path_prefix(si.displayName, options.SourcePrefix,
    824                                        "") &&
    825         !si.displayName.empty()) {
    826       // TODO replace_path_prefix may strip the prefix even if the remaining
    827       // part does not start with a separator.
    828       if (sys::path::is_separator(si.displayName[0]))
    829         si.displayName.erase(si.displayName.begin());
    830       else
    831         si.displayName = si.filename;
    832     }
    833     if (options.RelativeOnly && sys::path::is_absolute(si.displayName))
    834       si.ignored = true;
    835   }
    836 
    837   raw_ostream &os = llvm::outs();
    838   for (GCOVFunction &f : make_pointee_range(file.functions)) {
    839     Summary summary(f.getName(options.Demangle));
    840     collectFunction(f, summary);
    841     if (options.FuncCoverage && !options.UseStdout) {
    842       os << "Function '" << summary.Name << "'\n";
    843       printSummary(summary, os);
    844       os << '\n';
    845     }
    846   }
    847 
    848   for (SourceInfo &si : sources) {
    849     if (si.ignored)
    850       continue;
    851     Summary summary(si.displayName);
    852     collectSource(si, summary);
    853 
    854     // Print file summary unless -t is specified.
    855     std::string gcovName = getCoveragePath(si.filename, filename);
    856     if (!options.UseStdout) {
    857       os << "File '" << summary.Name << "'\n";
    858       printSummary(summary, os);
    859       if (!options.NoOutput && !options.Intermediate)
    860         os << "Creating '" << gcovName << "'\n";
    861       os << '\n';
    862     }
    863 
    864     if (options.NoOutput || options.Intermediate)
    865       continue;
    866     Optional<raw_fd_ostream> os;
    867     if (!options.UseStdout) {
    868       std::error_code ec;
    869       os.emplace(gcovName, ec, sys::fs::OF_TextWithCRLF);
    870       if (ec) {
    871         errs() << ec.message() << '\n';
    872         continue;
    873       }
    874     }
    875     annotateSource(si, file, gcno, gcda,
    876                    options.UseStdout ? llvm::outs() : *os);
    877   }
    878 
    879   if (options.Intermediate && !options.NoOutput) {
    880     // gcov 7.* unexpectedly create multiple .gcov files, which was fixed in 8.0
    881     // (PR GCC/82702). We create just one file.
    882     std::string outputPath(sys::path::filename(filename));
    883     std::error_code ec;
    884     raw_fd_ostream os(outputPath + ".gcov", ec, sys::fs::OF_TextWithCRLF);
    885     if (ec) {
    886       errs() << ec.message() << '\n';
    887       return;
    888     }
    889 
    890     for (const SourceInfo &si : sources)
    891       printSourceToIntermediate(si, os);
    892   }
    893 }
    894 
    895 void Context::printFunctionDetails(const GCOVFunction &f,
    896                                    raw_ostream &os) const {
    897   const uint64_t entryCount = f.getEntryCount();
    898   uint32_t blocksExec = 0;
    899   const GCOVBlock &exitBlock = f.getExitBlock();
    900   uint64_t exitCount = 0;
    901   for (const GCOVArc *arc : exitBlock.pred)
    902     exitCount += arc->count;
    903   for (const GCOVBlock &b : f.blocksRange())
    904     if (b.number != 0 && &b != &exitBlock && b.getCount())
    905       ++blocksExec;
    906 
    907   os << "function " << f.getName(options.Demangle) << " called " << entryCount
    908      << " returned " << formatPercentage(exitCount, entryCount)
    909      << "% blocks executed "
    910      << formatPercentage(blocksExec, f.blocks.size() - 2) << "%\n";
    911 }
    912 
    913 /// printBranchInfo - Print conditional branch probabilities.
    914 void Context::printBranchInfo(const GCOVBlock &Block, uint32_t &edgeIdx,
    915                               raw_ostream &os) const {
    916   uint64_t total = 0;
    917   for (const GCOVArc *arc : Block.dsts())
    918     total += arc->count;
    919   for (const GCOVArc *arc : Block.dsts())
    920     os << format("branch %2u ", edgeIdx++)
    921        << formatBranchInfo(options, arc->count, total) << '\n';
    922 }
    923 
    924 void Context::printSummary(const Summary &summary, raw_ostream &os) const {
    925   os << format("Lines executed:%.2f%% of %" PRIu64 "\n",
    926                double(summary.linesExec) * 100 / summary.lines, summary.lines);
    927   if (options.BranchInfo) {
    928     if (summary.branches == 0) {
    929       os << "No branches\n";
    930     } else {
    931       os << format("Branches executed:%.2f%% of %" PRIu64 "\n",
    932                    double(summary.branchesExec) * 100 / summary.branches,
    933                    summary.branches);
    934       os << format("Taken at least once:%.2f%% of %" PRIu64 "\n",
    935                    double(summary.branchesTaken) * 100 / summary.branches,
    936                    summary.branches);
    937     }
    938     os << "No calls\n";
    939   }
    940 }
    941 
    942 void llvm::gcovOneInput(const GCOV::Options &options, StringRef filename,
    943                         StringRef gcno, StringRef gcda, GCOVFile &file) {
    944   Context fi(options);
    945   fi.print(filename, gcno, gcda, file);
    946 }
    947