LLVM  13.0.0git
GCOV.cpp
Go to the documentation of this file.
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"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/MD5.h"
22 #include "llvm/Support/Path.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,
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.
42 };
43 
44 namespace {
45 struct Summary {
46  Summary(StringRef Name) : Name(Name) {}
47 
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 {
58  uint64_t count = 0;
59  bool exists = false;
60 };
61 
62 struct SourceInfo {
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:
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.
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);
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  }
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().
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.
313 #endif
314 
315 bool GCOVArc::onTree() const { return flags & GCOV_ARC_ON_TREE; }
316 
317 //===----------------------------------------------------------------------===//
318 // GCOVFunction implementation.
319 
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 }
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 
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.
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 
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.
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.
422 #endif
423 
424 uint64_t
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.
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("");
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;
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 
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;
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 
943  StringRef gcno, StringRef gcda, GCOVFile &file) {
944  Context fi(options);
945  fi.print(filename, gcno, gcda, file);
946 }
llvm::GCOVFile::functions
SmallVector< std::unique_ptr< GCOVFunction >, 16 > functions
Definition: GCOV.h:205
i
i
Definition: README.txt:29
block
we get the following basic block
Definition: README_ALTIVEC.txt:95
llvm::GCOVFunction::artificial
uint8_t artificial
Definition: GCOV.h:257
llvm::StringRef::startswith
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:286
llvm::GCOVBuffer::cursor
DataExtractor::Cursor cursor
Definition: GCOV.h:179
llvm::GCOVBlock::srcs
iterator_range< EdgeIterator > srcs() const
Definition: GCOV.h:284
LLVM_DUMP_METHOD
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:499
llvm
Definition: AllocatorList.h:23
llvm::GCOVFile::RunCount
uint32_t RunCount
Definition: GCOV.h:207
llvm::GCOVFunction::getEntryCount
uint64_t getEntryCount() const
getEntryCount - Get the number of times the function was called by retrieving the entry block's count...
Definition: GCOV.cpp:344
llvm::GCOVFunction::cfgChecksum
uint32_t cfgChecksum
Definition: GCOV.h:252
llvm::sys::path::replace_path_prefix
bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
Definition: Path.cpp:516
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:153
llvm::GCOVBlock::pred
SmallVector< GCOVArc *, 2 > pred
Definition: GCOV.h:304
llvm::GCOVFunction::startLine
uint32_t startLine
Definition: GCOV.h:253
llvm::MD5::update
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
Definition: MD5.cpp:190
FileSystem.h
type
llvm::GCOVFunction::demangled
SmallString< 0 > demangled
Definition: GCOV.h:259
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:147
llvm::GCOVFile::cwd
StringRef cwd
Definition: GCOV.h:204
llvm::GCOVBuffer::de
DataExtractor de
Definition: GCOV.h:178
llvm::GCOVBlock::incoming
GCOVArc * incoming
Definition: GCOV.h:308
llvm::GCOVBlock
GCOVBlock - Collects block information.
Definition: GCOV.h:267
arc
objc arc
Definition: ObjCARCOpts.cpp:607
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1167
Path.h
llvm::sys::path::is_absolute
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:669
llvm::GCOV::GCOVVersion
GCOVVersion
Definition: GCOV.h:45
llvm::GCOVFunction::visited
DenseSet< const GCOVBlock * > visited
Definition: GCOV.h:263
GCOV_TAG_ARCS
@ GCOV_TAG_ARCS
Definition: GCOV.cpp:36
branchDiv
static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor)
Definition: GCOV.cpp:519
GCOV_ARC_ON_TREE
@ GCOV_ARC_ON_TREE
Definition: GCOV.cpp:31
llvm::GCOVFile::IdentToFunction
std::map< uint32_t, GCOVFunction * > IdentToFunction
Definition: GCOV.h:206
llvm::GCOVFile::ProgramCount
uint32_t ProgramCount
Definition: GCOV.h:208
llvm::Optional
Definition: APInt.h:33
llvm::GCOVBlock::count
uint64_t count
Definition: GCOV.h:303
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:892
STLExtras.h
Format.h
llvm::DataExtractor::skip
void skip(Cursor &C, uint64_t Length) const
Advance the Cursor position by the given number of bytes.
Definition: DataExtractor.cpp:229
llvm::GCOVFunction::getName
StringRef getName(bool demangle) const
Definition: GCOV.cpp:320
llvm::GCOV::V900
@ V900
Definition: GCOV.h:45
llvm::GCOVArc::flags
uint32_t flags
Definition: GCOV.h:223
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
llvm::GCOVFile::filenameToIdx
StringMap< unsigned > filenameToIdx
Definition: GCOV.h:198
llvm::GCOVFile::dump
void dump() const
dump - Dump GCOVFile content to dbgs() for debugging purposes.
Definition: GCOV.cpp:312
llvm::GCOVBlock::addDstEdge
void addDstEdge(GCOVArc *Edge)
Definition: GCOV.h:282
llvm::MD5::final
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
Definition: MD5.cpp:235
llvm::outs
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
Definition: raw_ostream.cpp:884
MD5.h
llvm::GCOVFunction::blocksRange
iterator_range< BlockIterator > blocksRange() const
Definition: GCOV.h:241
f
Itanium Name Demangler i e convert the string _Z1fv into f()". You can also use the CRTP base ManglingParser to perform some simple analysis on the mangled name
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::StringRef::split
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:727
llvm::GCOVFunction::ident
uint32_t ident
Definition: GCOV.h:250
llvm::GCOVBlock::number
uint32_t number
Definition: GCOV.h:302
llvm::GCOVBuffer::readGCDAFormat
bool readGCDAFormat()
readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
Definition: GCOV.h:97
GCOV.h
llvm::GCOV::V407
@ V407
Definition: GCOV.h:45
b
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int b
Definition: README.txt:418
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::GCOVBlock::lines
SmallVector< uint32_t, 4 > lines
Definition: GCOV.h:306
llvm::StringRef::iterator
const char * iterator
Definition: StringRef.h:62
llvm::GCOVBlock::succ
SmallVector< GCOVArc *, 2 > succ
Definition: GCOV.h:305
llvm::GCOVFile::Checksum
uint32_t Checksum
Definition: GCOV.h:203
llvm::ErrorOr::getError
std::error_code getError() const
Definition: ErrorOr.h:153
llvm::GCOVFunction::file
GCOVFile & file
Definition: GCOV.h:249
GCOV_TAG_FUNCTION
@ GCOV_TAG_FUNCTION
Definition: GCOV.cpp:34
llvm::GCOVBlock::getCyclesCount
static uint64_t getCyclesCount(const BlockVector &blocks)
Definition: GCOV.cpp:476
llvm::GCOVFunction::getFilename
StringRef getFilename() const
Definition: GCOV.cpp:340
llvm::GCOVFunction::endLine
uint32_t endLine
Definition: GCOV.h:255
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:230
llvm::GCOVBuffer::getString
StringRef getString()
Definition: GCOV.h:145
GCOV_TAG_PROGRAM_SUMMARY
@ GCOV_TAG_PROGRAM_SUMMARY
Definition: GCOV.cpp:41
formatPercentage
static uint32_t formatPercentage(uint64_t dividend, uint64_t divisor)
Definition: GCOV.cpp:509
llvm::StringRef::str
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:245
GCOV_TAG_OBJECT_SUMMARY
@ GCOV_TAG_OBJECT_SUMMARY
Definition: GCOV.cpp:40
llvm::demangle
std::string demangle(const std::string &MangledName)
Attempt to demangle a string using different demangling schemes.
Definition: Demangle.cpp:22
llvm::StringRef::equals
LLVM_NODISCARD bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Definition: StringRef.h:187
llvm::SmallString< 0 >
llvm::sys::fs::OF_TextWithCRLF
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
Definition: FileSystem.h:772
llvm::GCOVBlock::augmentOneCycle
static uint64_t augmentOneCycle(GCOVBlock *src, std::vector< std::pair< GCOVBlock *, size_t >> &stack)
Definition: GCOV.cpp:425
llvm::GCOVFile::getVersion
GCOV::GCOVVersion getVersion() const
Definition: GCOV.h:193
llvm::GCOVBuffer::readGCOVVersion
bool readGCOVVersion(GCOV::GCOVVersion &Version)
readGCOVVersion - Read GCOV version.
Definition: GCOV.h:111
llvm::GCOVFunction::getExitBlock
GCOVBlock & getExitBlock() const
Definition: GCOV.cpp:348
llvm::GCOVBlock::traversable
bool traversable
Definition: GCOV.h:307
GCOV_TAG_LINES
@ GCOV_TAG_LINES
Definition: GCOV.cpp:37
file
dot regions Print regions of function to dot file(with no function bodies)"
llvm::sys::fs::exists
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:1073
llvm::count
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1565
llvm::StringRef::end
iterator end() const
Definition: StringRef.h:130
llvm::Optional::emplace
void emplace(ArgTypes &&... Args)
Create a new object by constructing it in place with the given arguments.
Definition: Optional.h:264
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::MD5
Definition: MD5.h:41
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
llvm::MemoryBuffer::getFileOrSTDIN
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
Definition: MemoryBuffer.cpp:144
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1547
llvm::GCOVFunction::arcs
SmallVector< std::unique_ptr< GCOVArc >, 0 > arcs
Definition: GCOV.h:262
llvm::make_pointee_range
iterator_range< pointee_iterator< WrappedIteratorT > > make_pointee_range(RangeT &&Range)
Definition: iterator.h:312
GCOV_TAG_BLOCKS
@ GCOV_TAG_BLOCKS
Definition: GCOV.cpp:35
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::DataExtractor::Cursor::tell
uint64_t tell() const
Return the current position of this Cursor.
Definition: DataExtractor.h:71
GCOV_ARC_FALLTHROUGH
@ GCOV_ARC_FALLTHROUGH
Definition: GCOV.cpp:32
llvm::GCOVBuffer::readInt
bool readInt(uint32_t &Val)
Definition: GCOV.h:152
llvm::gcovOneInput
void gcovOneInput(const GCOV::Options &options, StringRef filename, StringRef gcno, StringRef gcda, GCOVFile &file)
Definition: GCOV.cpp:942
llvm::StringMapImpl::size
unsigned size() const
Definition: StringMap.h:93
llvm::GCOVFunction::Name
StringRef Name
Definition: GCOV.h:258
llvm::GCOVBuffer::readInt64
bool readInt64(uint64_t &Val)
Definition: GCOV.h:162
llvm::size
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1463
sink
gvn sink
When an instruction is found to only be used outside of the loop, this function moves it to the exit ...
Definition: GVNSink.cpp:924
Demangle.h
llvm::min
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:357
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
uint32_t
llvm::GCOVBuffer::getWord
uint32_t getWord()
Definition: GCOV.h:144
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::GCOV::V800
@ V800
Definition: GCOV.h:45
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
mangleCoveragePath
static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths)
Convert a path to a gcov filename.
Definition: GCOV.cpp:591
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:432
llvm::GCOVArc
Definition: GCOV.h:216
llvm::GCOVFunction::srcIdx
unsigned srcIdx
Definition: GCOV.h:260
llvm::GCOVFunction::dump
void dump() const
dump - Dump GCOVFunction content to dbgs() for debugging purposes.
Definition: GCOV.cpp:385
llvm::GCOVFile::print
void print(raw_ostream &OS) const
Definition: GCOV.cpp:305
llvm::MD5::MD5Result
Definition: MD5.h:55
llvm::empty
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Definition: STLExtras.h:254
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::GCOV::Options
A struct for passing gcov options between functions.
Definition: GCOV.h:48
llvm::GCOVArc::onTree
bool onTree() const
Definition: GCOV.cpp:315
options
The object format emitted by the WebAssembly backed is documented see the home and packaging for producing WebAssembly applications that can run in browsers and other environments wasi sdk provides a more minimal C C SDK based on llvm and a libc based on for producing WebAssemmbly applictions that use the WASI ABI Rust provides WebAssembly support integrated into Cargo There are two main options
Definition: README.txt:24
llvm::GCOVFile::GCNOInitialized
bool GCNOInitialized
Definition: GCOV.h:201
llvm::GCOVBlock::print
void print(raw_ostream &OS) const
collectLineCounts - Collect line counts.
Definition: GCOV.cpp:394
llvm::GCOVFunction::endColumn
uint32_t endColumn
Definition: GCOV.h:256
llvm::GCOV::V408
@ V408
Definition: GCOV.h:45
llvm::GCOVFunction::linenoChecksum
uint32_t linenoChecksum
Definition: GCOV.h:251
llvm::GCOVFunction::print
void print(raw_ostream &OS) const
Definition: GCOV.cpp:376
llvm::GCOVBuffer::readGCNOFormat
bool readGCNOFormat()
readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
Definition: GCOV.h:82
llvm::GCOVBlock::dsts
iterator_range< EdgeIterator > dsts() const
Definition: GCOV.h:288
llvm::GCOVFile::filenames
std::vector< std::string > filenames
Definition: GCOV.h:197
llvm::GCOVBuffer::readString
bool readString(StringRef &Str)
Definition: GCOV.h:170
llvm::GCOVFunction::startColumn
uint32_t startColumn
Definition: GCOV.h:254
llvm::GCOVFile::readGCDA
bool readGCDA(GCOVBuffer &Buffer)
readGCDA - Read GCDA buffer.
Definition: GCOV.cpp:202
llvm::sys::path::is_separator
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
Definition: Path.cpp:599
llvm::sys::path::filename
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:575
llvm::ErrorOr::get
reference get()
Definition: ErrorOr.h:150
llvm::GCOVFile
GCOVFile - Collects coverage information for one pair of coverage file (.gcno and ....
Definition: GCOV.h:187
llvm::sys::fs::status
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
N
#define N
llvm::GCOVBlock::addSrcEdge
void addSrcEdge(GCOVArc *Edge)
Definition: GCOV.h:280
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
GCOV_TAG_COUNTER_ARCS
@ GCOV_TAG_COUNTER_ARCS
Definition: GCOV.cpp:38
llvm::GCOVBlock::dump
void dump() const
dump - Dump GCOVBlock content to dbgs() for debugging purposes.
Definition: GCOV.cpp:421
llvm::GCOVFunction::treeArcs
SmallVector< std::unique_ptr< GCOVArc >, 0 > treeArcs
Definition: GCOV.h:262
stack
S is passed via registers r2 But gcc stores them to the stack
Definition: README.txt:189
llvm::StringRef::data
const LLVM_NODISCARD char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:149
pred
hexagon gen pred
Definition: HexagonGenPredicate.cpp:134
llvm::itaniumDemangle
char * itaniumDemangle(const char *mangled_name, char *buf, size_t *n, int *status)
Definition: ItaniumDemangle.cpp:326
llvm::GCOVFunction::blocks
SmallVector< std::unique_ptr< GCOVBlock >, 0 > blocks
Definition: GCOV.h:261
llvm::GCOVFunction
GCOVFunction - Collects function information.
Definition: GCOV.h:229
llvm::GCOVBuffer
GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific read operations.
Definition: GCOV.h:76
raw_ostream.h
d
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int int int d
Definition: README.txt:418
llvm::GCOVFile::Version
GCOV::GCOVVersion Version
Definition: GCOV.h:202
branches
arc branch ARC finalize branches
Definition: ARCBranchFinalize.cpp:66
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:128
llvm::pdb::PDB_SymType::Block
@ Block
Debug.h
llvm::StringMap::try_emplace
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&... Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
Definition: StringMap.h:315
llvm::GCOVFunction::propagateCounts
uint64_t propagateCounts(const GCOVBlock &v, GCOVArc *pred)
Definition: GCOV.cpp:356
llvm::GCOVFile::readGCNO
bool readGCNO(GCOVBuffer &Buffer)
readGCNO - Read GCNO buffer.
Definition: GCOV.cpp:101