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