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 && visited.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 (pred.empty()) {

445 OS << "\tSource Edges : ";

447 OS << Edge->src.number << " (" << Edge->count << "), ";

448 OS << "\n";

449 }

450 if (succ.empty()) {

451 OS << "\tDestination Edges : ";

454 OS << '*';

455 OS << Edge->dst.number << " (" << Edge->count << "), ";

456 }

457 OS << "\n";

458 }

460 OS << "\tLines : ";

462 OS << (N) << ",";

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 || succ->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 (options.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 (options.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 (options.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.