LLVM: lib/ProfileData/GCOV.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
17#include "llvm/Config/llvm-config.h"
25#include
26#include
27#include <system_error>
28
29using namespace llvm;
30
34
40
43};
44
45namespace {
48
55};
56
57struct LineInfo {
61};
62
63struct SourceInfo {
66 std::vector<std::vector<const GCOVFunction *>> startLineToFunctions;
67 std::vector lines;
70};
71
72class Context {
73public:
77
78private:
79 std::string getCoveragePath(StringRef filename, StringRef mainFilename) 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;
91 void printSourceToIntermediate(const SourceInfo &si, raw_ostream &os) const;
92
94 std::vector sources;
95};
96}
97
98
99
100
101
104 return false;
106 return false;
107
110 return false;
112 buf.getWord();
113
116 while ((tag = buf.getWord())) {
117 if (!buf.readInt(length))
118 return false;
121 functions.push_back(std::make_unique(*this));
131 return false;
133 } else {
136 return false;
142 }
143 fn->srcIdx = addNormalizedPathToMap(filename);
147 for (uint32_t i = 0; i != length; ++i) {
148 buf.getWord();
149 fn->blocks.push_back(std::make_unique(i));
150 }
151 } else {
153 for (uint32_t i = 0; i != num; ++i)
154 fn->blocks.push_back(std::make_unique(i));
155 }
158 if (srcNo >= fn->blocks.size()) {
159 errs() << "unexpected block number: " << srcNo << " (in "
160 << fn->blocks.size() << ")\n";
161 return false;
162 }
166 for (uint32_t i = 0; i != e; ++i) {
169 auto arc = std::make_unique(*src, *dst, flags);
172 if (arc->onTree())
173 fn->treeArcs.push_back(std::move(arc));
174 else
175 fn->arcs.push_back(std::move(arc));
176 }
179 if (srcNo >= fn->blocks.size()) {
180 errs() << "unexpected block number: " << srcNo << " (in "
181 << fn->blocks.size() << ")\n";
182 return false;
183 }
185 for (;;) {
187 if (line)
188 Block.addLine(line);
189 else {
192 if (filename.empty())
193 break;
194
195 }
196 }
197 }
200 return false;
202 }
203
205 return true;
206}
207
208
209
213 return false;
216 return false;
217 if (version != GCDAVersion) {
218 errs() << "GCOV versions do not match.\n";
219 return false;
220 }
221
223 if (!buf.readInt(GCDAChecksum))
224 return false;
225 if (checksum != GCDAChecksum) {
226 errs() << "file checksums do not match: " << checksum
227 << " != " << GCDAChecksum << "\n";
228 return false;
229 }
233 while ((tag = buf.getWord())) {
234 if (!buf.readInt(length))
235 return false;
246 if (length == 0)
247 continue;
248 if (length < 2 || !buf.readInt(ident))
249 return false;
251 uint32_t linenoChecksum, cfgChecksum = 0;
252 buf.readInt(linenoChecksum);
254 buf.readInt(cfgChecksum);
256 fn = It->second;
260 << format(": checksum mismatch, (%u, %u) != (%u, %u)\n",
263 return false;
264 }
265 }
269 expected *= 4;
270 if (length != expected) {
273 ": GCOV_TAG_COUNTER_ARCS mismatch, got %u, expected %u\n",
274 length, expected);
275 return false;
276 }
277 for (std::unique_ptr &arc : fn->arcs) {
279 return false;
280 arc->src.count += arc->count;
281 }
282
283 if (fn->blocks.size() >= 2) {
288 sink.addDstEdge(arc.get());
290 fn->treeArcs.push_back(std::move(arc));
291
294 for (size_t i = fn->treeArcs.size() - 1; i; --i)
295 fn->treeArcs[i - 1]->src.count += fn->treeArcs[i - 1]->count;
296 }
297 }
300 return false;
302 }
303
304 return true;
305}
306
309 f.print(OS);
310}
311
312#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
313
315#endif
316
317unsigned GCOVFile::addNormalizedPathToMap(StringRef filename) {
318
321 filename = P.str();
322
324 if (r.second)
325 filenames.emplace_back(filename);
326
327 return r.first->second;
328}
329
331
332
333
334
339 do {
341
344 free(res);
345 break;
346 }
347 }
349 } while (false);
350 }
352}
354
355
356
358 return blocks.front()->getCount();
359}
360
363}
364
365
366
367
368
369
370
371
373 struct Elem {
376 bool inDst;
377 size_t i = 0;
379 };
380
383 for (;;) {
384 Elem &u = stack.back();
385
386
387 if (u.i == 0 && .insert(&u.v).second) {
389 if (stack.empty())
390 break;
391 continue;
392 }
393 if (u.i < u.v.pred.size()) {
394 GCOVArc *e = u.v.pred[u.i++];
395 if (e != u.pred) {
396 if (e->onTree())
397 stack.push_back({e->src, e, false});
398 else
399 u.excess += e->count;
400 }
401 } else if (u.i < u.v.pred.size() + u.v.succ.size()) {
402 GCOVArc *e = u.v.succ[u.i++ - u.v.pred.size()];
403 if (e != u.pred) {
404 if (e->onTree())
405 stack.push_back({e->dst, e, true});
406 else
407 u.excess -= e->count;
408 }
409 } else {
411 if (static_cast<int64_t>(excess) < 0)
412 excess = -excess;
413 if (u.pred)
414 u.pred->count = excess;
415 bool inDst = u.inDst;
417 if (stack.empty())
418 break;
419 stack.back().excess += inDst ? -excess : excess;
420 }
421 }
422}
423
429}
430
431#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
432
434#endif
435
436
437
438
439
440
441
443 OS << "Block : " << number << " Counter : " << count << "\n";
444 if (.empty()) {
445 OS << "\tSource Edges : ";
447 OS << Edge->src.number << " (" << Edge->count << "), ";
448 OS << "\n";
449 }
450 if (.empty()) {
451 OS << "\tDestination Edges : ";
454 OS << '*';
455 OS << Edge->dst.number << " (" << Edge->count << "), ";
456 }
457 OS << "\n";
458 }
460 OS << "\tLines : ";
463 OS << "\n";
464 }
465}
466
467#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
468
470#endif
471
474 std::vector<std::pair<GCOVBlock *, size_t>> &stack) {
476 size_t i;
477 stack.clear();
478 stack.emplace_back(src, 0);
479 src->incoming = (GCOVArc *)1;
480 for (;;) {
481 std::tie(u, i) = stack.back();
482 if (i == u->succ.size()) {
483 u->traversable = false;
484 stack.pop_back();
485 if (stack.empty())
486 break;
487 continue;
488 }
489 ++stack.back().second;
491
492
493
494 if (succ->cycleCount == 0 || ->dst.traversable || &succ->dst == u)
495 continue;
496 if (succ->dst.incoming == nullptr) {
498 stack.emplace_back(&succ->dst, 0);
499 continue;
500 }
503 minCount = std::min(minCount, v->incoming->cycleCount);
504 v = &v->incoming->src;
505 if (v == &succ->dst)
506 break;
507 }
508 succ->cycleCount -= minCount;
510 v->incoming->cycleCount -= minCount;
511 v = &v->incoming->src;
512 if (v == &succ->dst)
513 break;
514 }
515 return minCount;
516 }
517 return 0;
518}
519
520
521
522
523
525 std::vector<std::pair<GCOVBlock *, size_t>> stack;
527 for (;;) {
528
529 for (const auto *b : blocks) {
532 }
533 d = 0;
536 if (b->traversable && (d = augmentOneCycle(b, stack)) > 0)
537 break;
538 }
539 if (d == 0)
540 break;
542 }
543
544
545 for (const auto *b : blocks) {
546 assert(!b->traversable);
547 (void)b;
548 }
550}
551
552
553
554
555
556
558 if (!dividend || !divisor)
559 return 0;
560 dividend *= 100;
561 return dividend < divisor ? 1 : dividend / divisor;
562}
563
564
565
566
568 if (!Numerator)
569 return 0;
570 if (Numerator == Divisor)
571 return 100;
572
573 uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor;
574 if (Res == 0)
575 return 1;
576 if (Res == 100)
577 return 99;
578 return Res;
579}
580
581namespace {
582struct formatBranchInfo {
585
588 OS << "never executed";
589 else if (Options.BranchCount)
590 OS << "taken " << Count;
591 else
593 }
594
598};
599
601 FBI.print(OS);
602 return OS;
603}
604
605class LineConsumer {
606 std::unique_ptr Buffer;
608
609public:
610 LineConsumer() = default;
611 LineConsumer(StringRef Filename) {
612
613
616 false);
617 if (std::error_code EC = BufferOrErr.getError()) {
619 Remaining = "";
620 } else {
621 Buffer = std::move(BufferOrErr.get());
622 Remaining = Buffer->getBuffer();
623 }
624 }
625 bool empty() { return Remaining.empty(); }
628 if (empty())
629 Line = "/*EOF*/";
630 else
631 std::tie(Line, Remaining) = Remaining.split("\n");
632 OS << format("%5u:", LineNum) << Line << "\n";
633 }
634};
635}
636
637
638
640 if (!PreservePaths)
642
643
644
645
648 for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) {
649 if (*I != '/')
650 continue;
651
652 if (I - S == 1 && *S == '.') {
653
654 } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') {
655
656 Result.append("^#");
657 } else {
658 if (S < I)
659
660 Result.append(S, I);
661
662 Result.push_back('#');
663 }
664 S = I + 1;
665 }
666
667 if (S < I)
668 Result.append(S, I);
669 return std::string(Result);
670}
671
672std::string Context::getCoveragePath(StringRef filename,
675
676
677
678 return std::string(filename);
679
680 std::string CoveragePath;
681 if (options.LongFileNames && filename != mainFilename)
682 CoveragePath =
685 if (options.HashFilenames) {
686 MD5 Hasher;
689 Hasher.final(Result);
690 CoveragePath += "##" + std::string(Result.digest());
691 }
692 CoveragePath += ".gcov";
693 return CoveragePath;
694}
695
696void Context::collectFunction(GCOVFunction &f, Summary &summary) {
697 SourceInfo &si = sources[f.srcIdx];
698 if (f.startLine >= si.startLineToFunctions.size())
699 si.startLineToFunctions.resize(f.startLine + 1);
700 si.startLineToFunctions[f.startLine].push_back(&f);
703 for (const GCOVBlock &b : f.blocksRange()) {
704 if (b.lines.empty())
705 continue;
707 if (maxLineNum >= si.lines.size())
708 si.lines.resize(maxLineNum + 1);
709 for (uint32_t lineNum : b.lines) {
710 LineInfo &line = si.lines[lineNum];
711 if (lines.insert(lineNum).second)
712 ++summary.lines;
713 if (b.count && linesExec.insert(lineNum).second)
714 ++summary.linesExec;
715 line.exists = true;
716 line.count += b.count;
717 line.blocks.push_back(&b);
718 }
719 }
720}
721
722void Context::collectSourceLine(SourceInfo &si, Summary *summary,
723 LineInfo &line, size_t lineNum) const {
725 for (const GCOVBlock *b : line.blocks) {
726 if (b->number == 0) {
727
728
729
730
731 for (const GCOVArc *arc : b->succ)
733 } else {
734
735 for (const GCOVArc *arc : b->pred)
738 }
741 }
742
744 line.count = count;
745 if (line.exists) {
746 ++summary->lines;
747 if (line.count != 0)
748 ++summary->linesExec;
749 }
750
752 for (const GCOVBlock *b : line.blocks) {
753 if (b->getLastLine() != lineNum)
754 continue;
755 int branches = 0, execBranches = 0, takenBranches = 0;
756 for (const GCOVArc *arc : b->succ) {
759 ++execBranches;
760 if (arc->count != 0)
761 ++takenBranches;
762 }
764 summary->branches += branches;
765 summary->branchesExec += execBranches;
766 summary->branchesTaken += takenBranches;
767 }
768 }
769}
770
771void Context::collectSource(SourceInfo &si, Summary &summary) const {
772 size_t lineNum = 0;
773 for (LineInfo &line : si.lines) {
774 collectSourceLine(si, &summary, line, lineNum);
775 ++lineNum;
776 }
777}
778
779void Context::annotateSource(SourceInfo &si, const GCOVFile &file,
782 auto source =
783 options.Intermediate ? LineConsumer() : LineConsumer(si.filename);
784
785 os << " -: 0:Source:" << si.displayName << '\n';
786 os << " -: 0:Graph:" << gcno << '\n';
787 os << " -: 0:Data:" << gcda << '\n';
788 os << " -: 0:Runs:" << file.runCount << '\n';
790 os << " -: 0:Programs:" << file.programCount << '\n';
791
792 for (size_t lineNum = 1; !source.empty(); ++lineNum) {
793 if (lineNum >= si.lines.size()) {
794 os << " -:";
795 source.printNext(os, lineNum);
796 continue;
797 }
798
799 const LineInfo &line = si.lines[lineNum];
800 if (options.BranchInfo && lineNum < si.startLineToFunctions.size())
801 for (const auto *f : si.startLineToFunctions[lineNum])
802 printFunctionDetails(*f, os);
803 if (!line.exists)
804 os << " -:";
805 else if (line.count == 0)
806 os << " #####:";
807 else
808 os << format("%9" PRIu64 ":", line.count);
809 source.printNext(os, lineNum);
810
811 uint32_t blockIdx = 0, edgeIdx = 0;
812 for (const GCOVBlock *b : line.blocks) {
813 if (b->getLastLine() != lineNum)
814 continue;
816 if (b->getCount() == 0)
817 os << " $$$:";
818 else
819 os << format("%9" PRIu64 ":", b->count);
820 os << format("%5u-block %2u\n", lineNum, blockIdx++);
821 }
822 if (options.BranchInfo) {
823 size_t NumEdges = b->succ.size();
824 if (NumEdges > 1)
825 printBranchInfo(*b, edgeIdx, os);
826 else if (options.UncondBranch && NumEdges == 1) {
828 os << format("unconditional %2u ", edgeIdx++)
829 << formatBranchInfo(options, count, count) << '\n';
830 }
831 }
832 }
833 }
834}
835
836void Context::printSourceToIntermediate(const SourceInfo &si,
838 os << "file:" << si.filename << '\n';
839 for (const auto &fs : si.startLineToFunctions)
841 os << "function:" << f->startLine << ',' << f->getEntryCount() << ','
842 << f->getName(options.Demangle) << '\n';
843 for (size_t lineNum = 1, size = si.lines.size(); lineNum < size; ++lineNum) {
844 const LineInfo &line = si.lines[lineNum];
845 if (line.blocks.empty())
846 continue;
847
848
849
850 os << "lcount:" << lineNum << ',' << line.count << '\n';
851
853 continue;
854 for (const GCOVBlock *b : line.blocks) {
855 if (b->succ.size() < 2 || b->getLastLine() != lineNum)
856 continue;
857 for (const GCOVArc *arc : b->succ) {
858 const char *type =
859 b->getCount() ? arc->count ? "taken" : "nottaken" : "notexec";
860 os << "branch:" << lineNum << ',' << type << '\n';
861 }
862 }
863 }
864}
865
869 sources.emplace_back(filename);
870 SourceInfo &si = sources.back();
871 si.displayName = si.filename;
872 if (.SourcePrefix.empty() &&
874 "") &&
875 !si.displayName.empty()) {
876
877
879 si.displayName.erase(si.displayName.begin());
880 else
881 si.displayName = si.filename;
882 }
884 si.ignored = true;
885 }
886
890 collectFunction(f, summary);
892 os << "Function '" << summary.Name << "'\n";
893 printSummary(summary, os);
894 os << '\n';
895 }
896 }
897
898 for (SourceInfo &si : sources) {
899 if (si.ignored)
900 continue;
901 Summary summary(si.displayName);
902 collectSource(si, summary);
903
904
905 std::string gcovName = getCoveragePath(si.filename, filename);
906 if (.UseStdout) {
907 os << "File '" << summary.Name << "'\n";
908 printSummary(summary, os);
910 os << "Creating '" << gcovName << "'\n";
911 os << '\n';
912 }
913
915 continue;
916 std::optional<raw_fd_ostream> os;
917 if (.UseStdout) {
918 std::error_code ec;
920 if (ec) {
921 errs() << ec.message() << '\n';
922 continue;
923 }
924 }
925 annotateSource(si, file, gcno, gcda,
927 }
928
930
931
933 std::error_code ec;
935 if (ec) {
936 errs() << ec.message() << '\n';
937 return;
938 }
939
940 for (const SourceInfo &si : sources)
941 printSourceToIntermediate(si, os);
942 }
943}
944
945void Context::printFunctionDetails(const GCOVFunction &f,
947 const uint64_t entryCount = f.getEntryCount();
949 const GCOVBlock &exitBlock = f.getExitBlock();
951 for (const GCOVArc *arc : exitBlock.pred)
952 exitCount += arc->count;
953 for (const GCOVBlock &b : f.blocksRange())
954 if (b.number != 0 && &b != &exitBlock && b.getCount())
955 ++blocksExec;
956
957 os << "function " << f.getName(options.Demangle) << " called " << entryCount
959 << "% blocks executed "
961}
962
963
968 total += arc->count;
970 os << format("branch %2u ", edgeIdx++)
971 << formatBranchInfo(options, arc->count, total) << '\n';
972}
973
974void Context::printSummary(const Summary &summary, raw_ostream &os) const {
975 os << format("Lines executed:%.2f%% of %" PRIu64 "\n",
976 double(summary.linesExec) * 100 / summary.lines, summary.lines);
977 if (options.BranchInfo) {
978 if (summary.branches == 0) {
979 os << "No branches\n";
980 } else {
981 os << format("Branches executed:%.2f%% of %" PRIu64 "\n",
982 double(summary.branchesExec) * 100 / summary.branches,
983 summary.branches);
984 os << format("Taken at least once:%.2f%% of %" PRIu64 "\n",
985 double(summary.branchesTaken) * 100 / summary.branches,
986 summary.branches);
987 }
988 os << "No calls\n";
989 }
990}
991
994 Context fi(options);
995 fi.print(filename, gcno, gcda, file);
996}
arc branch ARC finalize branches
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
bbsections Prepares for basic block by splitting functions into clusters of basic blocks
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Looks at all the uses of the given value Returns the Liveness deduced from the uses of this value Adds all uses that cause the result to be MaybeLive to MaybeLiveRetUses If the result is MaybeLiveUses might be modified but its content should be ignored(since it might not be complete). DeadArgumentEliminationPass
@ GCOV_TAG_PROGRAM_SUMMARY
@ GCOV_TAG_OBJECT_SUMMARY
static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths)
Convert a path to a gcov filename.
static uint32_t formatPercentage(uint64_t dividend, uint64_t divisor)
static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor)
static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT, const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU, OptimizationRemarkEmitter *ORE)
When an instruction is found to only be used outside of the loop, this function moves it to the exit ...
dot regions Print regions of function to dot file(with no function bodies)"
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
unify loop Fixup each natural loop to have a single exit block
Represents either an error or a value T.
std::error_code getError() const
GCOVBlock - Collects block information.
static uint64_t getCyclesCount(const BlockVector &blocks)
SmallVector< uint32_t, 4 > lines
void addDstEdge(GCOVArc *Edge)
void addSrcEdge(GCOVArc *Edge)
void print(raw_ostream &OS) const
collectLineCounts - Collect line counts.
static uint64_t augmentOneCycle(GCOVBlock *src, std::vector< std::pair< GCOVBlock *, size_t > > &stack)
SmallVector< GCOVArc *, 2 > pred
void dump() const
dump - Dump GCOVBlock content to dbgs() for debugging purposes.
SmallVector< GCOVArc *, 2 > succ
GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific read operations.
bool readInt(uint32_t &Val)
DataExtractor::Cursor cursor
bool readInt64(uint64_t &Val)
bool readGCOVVersion(GCOV::GCOVVersion &version)
readGCOVVersion - Read GCOV version.
bool readString(StringRef &str)
bool readGCNOFormat()
readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
bool readGCDAFormat()
readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
GCOVFile - Collects coverage information for one pair of coverage file (.gcno and ....
SmallVector< std::unique_ptr< GCOVFunction >, 16 > functions
void print(raw_ostream &OS) const
GCOV::GCOVVersion version
std::vector< std::string > filenames
GCOV::GCOVVersion getVersion() const
void dump() const
dump - Dump GCOVFile content to dbgs() for debugging purposes.
std::map< uint32_t, GCOVFunction * > identToFunction
StringMap< unsigned > filenameToIdx
bool readGCNO(GCOVBuffer &Buffer)
readGCNO - Read GCNO buffer.
bool readGCDA(GCOVBuffer &Buffer)
readGCDA - Read GCDA buffer.
GCOVFunction - Collects function information.
uint64_t getEntryCount() const
getEntryCount - Get the number of times the function was called by retrieving the entry block's count...
SmallVector< std::unique_ptr< GCOVArc >, 0 > treeArcs
StringRef getName(bool demangle) const
void dump() const
dump - Dump GCOVFunction content to dbgs() for debugging purposes.
void propagateCounts(const GCOVBlock &v, GCOVArc *pred)
SmallVector< std::unique_ptr< GCOVBlock >, 0 > blocks
GCOVBlock & getExitBlock() const
StringRef getFilename() const
DenseSet< const GCOVBlock * > visited
SmallString< 0 > demangled
void print(raw_ostream &OS) const
iterator_range< BlockIterator > blocksRange() const
SmallVector< std::unique_ptr< GCOVArc >, 0 > arcs
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
std::string str() const
str - Get the contents as an std::string.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
bool exists(const basic_file_status &status)
Does file exist?
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
This is an optimization pass for GlobalISel generic memory operations.
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
iterator_range< pointee_iterator< WrappedIteratorT > > make_pointee_range(RangeT &&Range)
char * itaniumDemangle(std::string_view mangled_name, bool ParseParams=true)
Returns a non-NULL pointer to a NUL-terminated C style string that should be explicitly freed,...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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...
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void gcovOneInput(const GCOV::Options &options, StringRef filename, StringRef gcno, StringRef gcda, GCOVFile &file)
std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
A struct for passing gcov options between functions.