LLVM: lib/Transforms/Instrumentation/GCOVProfiling.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

44#include

45#include

46#include

47#include

48

49using namespace llvm;

51

52#define DEBUG_TYPE "insert-gcov-profiling"

53

56

61};

62

66

68 cl::desc("Make counter updates atomic"));

69

70

72

73 return (s.size() / 4) + 2;

74}

75

80 Options.NoRedZone = false;

82

86 }

89}

90

91namespace {

93

94class GCOVProfiler {

95public:

96 GCOVProfiler()

97 : GCOVProfiler(GCOVOptions::getDefault(), *vfs::getRealFileSystem()) {}

99 : Options(Opts), VFS(VFS) {}

100 bool

101 runOnModule(Module &M, function_ref<BlockFrequencyInfo *(Function &F)> GetBFI,

102 function_ref<BranchProbabilityInfo *(Function &F)> GetBPI,

103 std::function<const TargetLibraryInfo &(Function &F)> GetTLI);

104

105 void write(uint32_t i) {

106 char Bytes[4];

108 os->write(Bytes, 4);

109 }

110 void writeString(StringRef s) {

112 os->write(s.data(), s.size());

113 os->write_zeros(4 - s.size() % 4);

114 }

115 void writeBytes(const char *Bytes, int Size) { os->write(Bytes, Size); }

116 vfs::FileSystem &getVirtualFileSystem() const { return VFS; }

117

118private:

119

120 bool

121 emitProfileNotes(NamedMDNode *CUNode, bool HasExecOrFork,

122 function_ref<BlockFrequencyInfo *(Function &F)> GetBFI,

123 function_ref<BranchProbabilityInfo *(Function &F)> GetBPI,

124 function_ref<const TargetLibraryInfo &(Function &F)> GetTLI);

125

126 Function *createInternalFunction(FunctionType *FTy, StringRef Name,

127 StringRef MangledType = "");

128

129 void emitGlobalConstructor(

130 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP);

131 void emitModuleInitFunctionPtrs(

132 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP);

133

134 bool isFunctionInstrumented(const Function &F);

135 std::vector createRegexesFromString(StringRef RegexesStr);

136 static bool doesFilenameMatchARegex(StringRef Filename,

137 std::vector &Regexes);

138

139

140 FunctionCallee getStartFileFunc(const TargetLibraryInfo *TLI);

141 FunctionCallee getEmitFunctionFunc(const TargetLibraryInfo *TLI);

142 FunctionCallee getEmitArcsFunc(const TargetLibraryInfo *TLI);

143 FunctionCallee getSummaryInfoFunc();

144 FunctionCallee getEndFileFunc();

145

146

147

149 insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);

150 Function *insertReset(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);

151

152 bool AddFlushBeforeForkAndExec();

153

154 enum class GCovFileType { GCNO, GCDA };

155 std::string mangleName(const DICompileUnit *CU, GCovFileType FileType);

156

159 raw_ostream *os;

161

162

164

166 std::function<const TargetLibraryInfo &(Function &F)> GetTLI;

167 LLVMContext *Ctx = nullptr;

169 std::vector FilterRe;

170 std::vector ExcludeRe;

171 DenseSet<const BasicBlock *> ExecBlocks;

172 StringMap InstrumentedFiles;

173 vfs::FileSystem &VFS;

174};

175

176struct BBInfo {

177 BBInfo *Group;

179 uint32_t Rank = 0;

180

181 BBInfo(unsigned Index) : Group(this), Index(Index) {}

182 std::string infoString() const {

183 return (Twine("Index=") + Twine(Index)).str();

184 }

185};

186

188

189

192 uint64_t Weight;

194 uint32_t SrcNumber, DstNumber;

195 bool InMST = false;

196 bool Removed = false;

197 bool IsCritical = false;

198

199 Edge(const BasicBlock *Src, const BasicBlock *Dest, uint64_t W = 1)

200 : SrcBB(Src), DestBB(Dest), Weight(W) {}

201

202

203 std::string infoString() const {

204 return (Twine(Removed ? "-" : " ") + (InMST ? " " : "*") +

205 (IsCritical ? "c" : " ") + " W=" + Twine(Weight))

206 .str();

207 }

208};

209}

210

212 if (!SP->getLinkageName().empty())

213 return SP->getLinkageName();

214 return SP->getName();

215}

216

217

218

219

220

221

224 StringRef RelPath = SP->getFilename();

225 if (VFS.exists(RelPath))

226 Path = RelPath;

227 else

229 return Path;

230}

231

232namespace {

233 class GCOVRecord {

234 protected:

235 GCOVProfiler *P;

236

237 GCOVRecord(GCOVProfiler *P) : P(P) {}

238

239 void write(uint32_t i) { P->write(i); }

240 void writeString(StringRef s) { P->writeString(s); }

241 void writeBytes(const char *Bytes, int Size) { P->writeBytes(Bytes, Size); }

242 };

243

246

247

248

249

250 class GCOVLines : public GCOVRecord {

251 public:

253

254 void addLine(uint32_t Line) {

255 assert(Line != 0 && "Line zero is not a valid real line number.");

256 Lines.push_back(Line);

257 }

258

259 uint32_t length() const {

261 }

262

263 void writeOut() {

265 writeString(Filename);

266 for (uint32_t L : Lines)

268 }

269

270 GCOVLines(GCOVProfiler *P, StringRef F)

272

273 private:

276 };

277

278

279

280

281

282 class GCOVBlock : public GCOVRecord {

283 public:

284 GCOVLines &getFile(StringRef Filename) {

285 if (Lines.empty() || Lines.back().getFilename() != Filename)

286 Lines.emplace_back(P, Filename);

287 return Lines.back();

288 }

289

291 OutEdges.emplace_back(&Successor, Flags);

292 }

293

294 void writeOut() {

295 uint32_t Len = 3;

296

297 for (auto &L : Lines)

298 Len += L.length();

299

303

304 for (auto &L : Lines)

305 L.writeOut();

308 }

309

311

312

313

315 assert(OutEdges.empty());

316 }

317

320

321 private:

322 friend class GCOVFunction;

323

326

328 };

329

330

331

332

334 public:

335 GCOVFunction(GCOVProfiler *P, Function *F, const DISubprogram *SP,

336 unsigned EndLine, uint32_t Ident, int Version)

337 : GCOVRecord(P), SP(SP), EndLine(EndLine), Ident(Ident),

340 uint32_t i = 2;

341 for (BasicBlock &BB : *F)

342 Blocks.insert(std::make_pair(&BB, GCOVBlock(P, i++)));

343

344 std::string FunctionNameAndLine;

345 raw_string_ostream FNLOS(FunctionNameAndLine);

347 FuncChecksum = hash_value(FunctionNameAndLine);

348 }

349

350 GCOVBlock &getBlock(const BasicBlock *BB) {

351 return Blocks.find(const_cast<BasicBlock *>(BB))->second;

352 }

353

354 GCOVBlock &getEntryBlock() { return EntryBlock; }

355 GCOVBlock &getReturnBlock() {

356 return ReturnBlock;

357 }

358

359 uint32_t getFuncChecksum() const {

360 return FuncChecksum;

361 }

362

363 void writeOut(uint32_t CfgChecksum) {

368

371 write(FuncChecksum);

372 write(CfgChecksum);

374

375 write(SP->isArtificial());

376 writeString(Filename);

377 write(SP->getLine());

378 write(0);

379

380

382 write(0);

383

384

387 write(Blocks.size() + 2);

388 LLVM_DEBUG(dbgs() << (Blocks.size() + 1) << " blocks\n");

389

390

391 const uint32_t Outgoing = EntryBlock.OutEdges.size();

392 if (Outgoing) {

394 write(Outgoing * 2 + 1);

395 write(EntryBlock.Number);

396 for (const auto &E : EntryBlock.OutEdges) {

397 write(E.first->Number);

399 }

400 }

401 for (auto &It : Blocks) {

402 const GCOVBlock &Block = It.second;

403 if (Block.OutEdges.empty()) continue;

404

406 write(Block.OutEdges.size() * 2 + 1);

408 for (const auto &E : Block.OutEdges) {

409 write(E.first->Number);

411 }

412 }

413

414

415 for (auto &It : Blocks)

416 It.second.writeOut();

417 }

418

419 public:

420 const DISubprogram *SP;

421 unsigned EndLine;

422 uint32_t Ident;

423 uint32_t FuncChecksum;

425 MapVector<BasicBlock *, GCOVBlock> Blocks;

426 GCOVBlock EntryBlock;

427 GCOVBlock ReturnBlock;

428 };

429}

430

431

432

433std::vector GCOVProfiler::createRegexesFromString(StringRef RegexesStr) {

434 std::vector Regexes;

435 while (!RegexesStr.empty()) {

436 std::pair<StringRef, StringRef> HeadTail = RegexesStr.split(';');

437 if (!HeadTail.first.empty()) {

438 Regex Re(HeadTail.first);

439 std::string Err;

440 if (!Re.isValid(Err)) {

441 Ctx->emitError(Twine("Regex ") + HeadTail.first +

442 " is not valid: " + Err);

443 }

444 Regexes.emplace_back(std::move(Re));

445 }

446 RegexesStr = HeadTail.second;

447 }

448 return Regexes;

449}

450

451bool GCOVProfiler::doesFilenameMatchARegex(StringRef Filename,

452 std::vector &Regexes) {

453 for (Regex &Re : Regexes)

454 if (Re.match(Filename))

455 return true;

456 return false;

457}

458

459bool GCOVProfiler::isFunctionInstrumented(const Function &F) {

460 if (FilterRe.empty() && ExcludeRe.empty()) {

461 return true;

462 }

464 auto It = InstrumentedFiles.find(Filename);

465 if (It != InstrumentedFiles.end()) {

466 return It->second;

467 }

468

471

472

473

474

475 if (VFS.getRealPath(Filename, RealPath)) {

476

478 } else {

479 RealFilename = RealPath;

480 }

481

482 bool ShouldInstrument;

483 if (FilterRe.empty()) {

484 ShouldInstrument = !doesFilenameMatchARegex(RealFilename, ExcludeRe);

485 } else if (ExcludeRe.empty()) {

486 ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe);

487 } else {

488 ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe) &&

489 !doesFilenameMatchARegex(RealFilename, ExcludeRe);

490 }

491 InstrumentedFiles[Filename] = ShouldInstrument;

492 return ShouldInstrument;

493}

494

495std::string GCOVProfiler::mangleName(const DICompileUnit *CU,

496 GCovFileType OutputType) {

497 bool Notes = OutputType == GCovFileType::GCNO;

498

499 if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) {

500 for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) {

502 bool ThreeElement = N->getNumOperands() == 3;

503 if (!ThreeElement && N->getNumOperands() != 2)

504 continue;

506 continue;

507

508 if (ThreeElement) {

509

510

513 if (!NotesFile || !DataFile)

514 continue;

515 return std::string(Notes ? NotesFile->getString()

517 }

518

520 if (!GCovFile)

521 continue;

522

525 return std::string(Filename);

526 }

527 }

528

533 if (!CWD)

534 return std::string(FName);

537 return std::string(CurPath);

538}

539

540bool GCOVProfiler::runOnModule(

544 this->M = &M;

545 this->GetTLI = std::move(GetTLI);

546 Ctx = &M.getContext();

547

548 NamedMDNode *CUNode = M.getNamedMetadata("llvm.dbg.cu");

549 if (!CUNode || (Options.EmitNotes && Options.EmitData))

550 return false;

551

552 bool HasExecOrFork = AddFlushBeforeForkAndExec();

553

554 FilterRe = createRegexesFromString(Options.Filter);

555 ExcludeRe = createRegexesFromString(Options.Exclude);

556 emitProfileNotes(CUNode, HasExecOrFork, GetBFI, GetBPI, this->GetTLI);

557 return true;

558}

559

562

563 GCOVProfiler Profiler(GCOVOpts, *VFS);

566

569 };

572 };

575 };

576

577 if (!Profiler.runOnModule(M, GetBFI, GetBPI, GetTLI))

579

581}

582

584

585

586 EndLine = 0;

587 for (const auto &BB : F) {

588 for (const auto &I : BB) {

590 if (Loc)

591 continue;

592

593

594 if (Loc.getLine() == 0) continue;

595 EndLine = std::max(EndLine, Loc.getLine());

596

597 return true;

598 }

599 }

600 return false;

601}

602

604 if (F.hasPersonalityFn()) return false;

605

608}

609

610bool GCOVProfiler::AddFlushBeforeForkAndExec() {

614 for (auto &F : M->functions()) {

615 TLI = TLI == nullptr ? &GetTLI(F) : TLI;

618 if (Function *Callee = CI->getCalledFunction()) {

619 LibFunc LF;

621 if (LF == LibFunc_fork) {

622#if !defined(_WIN32)

624#endif

625 } else if (LF == LibFunc_execl || LF == LibFunc_execle ||

626 LF == LibFunc_execlp || LF == LibFunc_execv ||

627 LF == LibFunc_execvp || LF == LibFunc_execve ||

628 LF == LibFunc_execvpe || LF == LibFunc_execvP) {

630 }

631 }

632 }

633 }

634 }

635 }

636

637 for (auto *F : Forks) {

641

642

645 "__gcov_fork", FTy,

646 TLI->getAttrList(Ctx, {}, true, true));

647 F->setCalledFunction(GCOVFork);

648

649

650

651

652

653

654

656

657

658

659

662 }

663

664 for (auto *E : Execs) {

668

669

670

673 M->getOrInsertFunction("llvm_writeout_files", FTy);

674 Builder.CreateCall(WriteoutF);

675

677 Builder.SetInsertPoint(&*NextInst);

678

679

680 FunctionCallee ResetF = M->getOrInsertFunction("llvm_reset_counters", FTy);

681 Builder.CreateCall(ResetF)->setDebugLoc(Loc);

682 ExecBlocks.insert(Parent);

685 }

686

687 return !Forks.empty() || !Execs.empty();

688}

689

692 if (E.InMST || E.Removed)

693 return nullptr;

694

697

698 if (SrcBB == nullptr)

699 return DestBB;

700 if (DestBB == nullptr)

701 return SrcBB;

702

704

705

707 return nullptr;

708 return BB;

709 };

710

711

712

715 return CanInstrument(SrcBB);

716 if (E.IsCritical)

717 return CanInstrument(DestBB);

718

719

720

724 if (!InstrBB)

725 return nullptr;

726

727 MST.addEdge(SrcBB, InstrBB, 0);

728 MST.addEdge(InstrBB, DestBB, 0).InMST = true;

729 E.Removed = true;

730

731 return CanInstrument(InstrBB);

732}

733

734#ifndef NDEBUG

736 size_t ID = 0;

738 GCOVBlock &Src = E.SrcBB ? GF.getBlock(E.SrcBB) : GF.getEntryBlock();

739 GCOVBlock &Dst = E.DestBB ? GF.getBlock(E.DestBB) : GF.getReturnBlock();

740 dbgs() << " Edge " << ID++ << ": " << Src.Number << "->" << Dst.Number

741 << E.infoString() << "\n";

742 }

743}

744#endif

745

746bool GCOVProfiler::emitProfileNotes(

751 {

752 uint8_t c3 = Options.Version[0];

753 uint8_t c2 = Options.Version[1];

754 uint8_t c1 = Options.Version[2];

755 Version = c3 >= 'A' ? (c3 - 'A') * 100 + (c2 - '0') * 10 + c1 - '0'

756 : (c3 - '0') * 10 + c1 - '0';

757 }

758

761 memcpy(Options.Version, "B11*", 4);

762 }

763

764 bool EmitGCDA = Options.EmitData;

765 for (unsigned i = 0, e = CUNode->getNumOperands(); i != e; ++i) {

766

767

768

769

771

772

774 continue;

775

776 std::vector<uint8_t> EdgeDestinations;

778

781 unsigned FunctionIdent = 0;

782 for (auto &F : M->functions()) {

784 unsigned EndLine;

785 if (!SP) continue;

787 continue;

788

790 if (F.hasFnAttribute(llvm::Attribute::NoProfile))

791 continue;

792 if (F.hasFnAttribute(llvm::Attribute::SkipProfile))

793 continue;

794

795

796

797 uint32_t Line = SP->getLine();

799

802

803

804

806 BFI);

807

809 false, BPI, BFI);

810

811

813 auto &E = *MST.allEdges()[I];

814

815

816 if (HasExecOrFork)

817 E.InMST = false;

819 }

820

821 BasicBlock &EntryBlock = F.getEntryBlock();

822 Funcs.push_back(std::make_unique(this, &F, SP, EndLine,

823 FunctionIdent++, Version));

825

826

827

828 llvm::erase_if(MST.allEdges(), [](std::unique_ptr &E) {

829 return E->Removed || (!E->InMST && !E->Place);

830 });

831 const size_t Measured =

832 std::stable_partition(

833 MST.allEdges().begin(), MST.allEdges().end(),

834 [](std::unique_ptr &E) { return E->Place; }) -

835 MST.allEdges().begin();

837 Edge &E = *MST.allEdges()[I];

839 E.SrcBB ? Func.getBlock(E.SrcBB) : Func.getEntryBlock();

841 E.DestBB ? Func.getBlock(E.DestBB) : Func.getReturnBlock();

842 E.SrcNumber = Src.Number;

843 E.DstNumber = Dst.Number;

844 }

845 std::stable_sort(

846 MST.allEdges().begin(), MST.allEdges().begin() + Measured,

847 [](const std::unique_ptr &L, const std::unique_ptr &R) {

848 return L->SrcNumber != R->SrcNumber ? L->SrcNumber < R->SrcNumber

849 : L->DstNumber < R->DstNumber;

850 });

851

854 E.SrcBB ? Func.getBlock(E.SrcBB) : Func.getEntryBlock();

856 E.DestBB ? Func.getBlock(E.DestBB) : Func.getReturnBlock();

858 }

859

860

861 if (SP->isArtificial())

862 Func.getBlock(&EntryBlock).getFile(Filename).addLine(Line);

863

865

866 for (auto &GB : Func.Blocks) {

868 auto &Block = GB.second;

869 for (auto Succ : Block.OutEdges) {

870 uint32_t Idx = Succ.first->Number;

871 do EdgeDestinations.push_back(Idx & 255);

872 while ((Idx >>= 8) > 0);

873 }

874

875 for (const auto &I : BB) {

877 if (Loc)

878 continue;

879

880

881 if (Loc.getLine() == 0 || Loc.isImplicitCode())

882 continue;

883

884 if (Line == Loc.getLine()) continue;

888 continue;

889

891 Lines.addLine(Loc.getLine());

892 }

894 }

895 if (EmitGCDA) {

903 Counters->setSection("__llvm_gcov_ctr_section");

905

907 const Edge &E = *MST.allEdges()[I];

908 IRBuilder<> Builder(E.Place, E.Place->getFirstInsertionPt());

909 Value *V = Builder.CreateConstInBoundsGEP2_64(

911

912

918 } else {

920 Builder.CreateLoad(Builder.getInt64Ty(), V, "gcov_ctr");

922 Value *NewCount = Builder.CreateAdd(OldCount, Builder.getInt64(1));

923 Inst = Builder.CreateStore(NewCount, V);

924 }

926 }

927 }

928 }

929

930 char Tmp[4];

932 JC.update(EdgeDestinations);

933 uint32_t Stamp = JC.getCRC();

935

937 std::error_code EC;

938 raw_fd_ostream out(mangleName(CU, GCovFileType::GCNO), EC,

940 if (EC) {

941 Ctx->emitError(

942 Twine("failed to open coverage notes file for writing: ") +

943 EC.message());

944 continue;

945 }

946 os = &out;

948 out.write("gcno", 4);

949 out.write(Options.Version, 4);

950 } else {

951 out.write("oncg", 4);

952 std::reverse_copy(Options.Version, Options.Version + 4, Tmp);

953 out.write(Tmp, 4);

954 }

956 writeString(".");

957 write(0);

958

959 for (auto &Func : Funcs)

960 Func->writeOut(Stamp);

961

964 out.close();

965 }

966

967 if (EmitGCDA) {

970 emitModuleInitFunctionPtrs(CountersBySP);

971 else

972 emitGlobalConstructor(CountersBySP);

973 EmitGCDA = false;

974 }

975 }

976 return true;

977}

978

985 F->addFnAttr(Attribute::NoUnwind);

987 F->addFnAttr(Attribute::NoRedZone);

988 if (!MangledType.empty())

990 return F;

991}

992

993void GCOVProfiler::emitGlobalConstructor(

994 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) {

995 Function *WriteoutF = insertCounterWriteout(CountersBySP);

996 Function *ResetF = insertReset(CountersBySP);

997

998

999

1000

1002 Function *F = createInternalFunction(FTy, "__llvm_gcov_init", "_ZTSFvvE");

1003 F->addFnAttr(Attribute::NoInline);

1004

1007

1010 FTy = FunctionType::get(Builder.getVoidTy(), {PFTy, PFTy}, false);

1011

1012

1013

1014 FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy);

1015 Builder.CreateCall(GCOVInit, {WriteoutF, ResetF});

1016 Builder.CreateRetVoid();

1017

1019}

1020

1021void GCOVProfiler::emitModuleInitFunctionPtrs(

1022 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) {

1023 Function *WriteoutF = insertCounterWriteout(CountersBySP);

1024 Function *ResetF = insertReset(CountersBySP);

1025

1026

1027

1028

1029

1030 auto &Ctx = M->getContext();

1031

1032 Type *InitFuncDataTy[] = {

1033#define COVINIT_FUNC(Type, LLVMType, Name, Init) LLVMType,

1035 };

1036

1038

1039 Constant *InitFuncPtrs[] = {

1040#define COVINIT_FUNC(Type, LLVMType, Name, Init) Init,

1042 };

1043

1044 auto *CovInitGV =

1046 "__llvm_covinit_functions");

1050 IPSK_covinit, M->getTargetTriple().getObjectFormat()));

1052 CovInitGV->setConstant(true);

1053}

1054

1060 };

1062 return M->getOrInsertFunction("llvm_gcda_start_file", FTy,

1063 TLI->getAttrList(Ctx, {1, 2}, false));

1064}

1065

1071 };

1073 return M->getOrInsertFunction("llvm_gcda_emit_function", FTy,

1074 TLI->getAttrList(Ctx, {0, 1, 2}, false));

1075}

1076

1081 };

1083 return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy,

1084 TLI->getAttrList(Ctx, {0}, false));

1085}

1086

1089 return M->getOrInsertFunction("llvm_gcda_summary_info", FTy);

1090}

1091

1094 return M->getOrInsertFunction("llvm_gcda_end_file", FTy);

1095}

1096

1097Function *GCOVProfiler::insertCounterWriteout(

1098 ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {

1100 Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");

1101 if (!WriteoutF)

1102 WriteoutF =

1103 createInternalFunction(WriteoutFTy, "__llvm_gcov_writeout", "_ZTSFvvE");

1104 WriteoutF->addFnAttr(Attribute::NoInline);

1105

1108

1109 auto *TLI = &GetTLI(*WriteoutF);

1110

1112 FunctionCallee EmitFunction = getEmitFunctionFunc(TLI);

1116

1117 NamedMDNode *CUNodes = M->getNamedMetadata("llvm.dbg.cu");

1118 if (!CUNodes) {

1119 Builder.CreateRetVoid();

1120 return WriteoutF;

1121 }

1122

1123

1124

1126 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getInt32Ty()},

1127 "start_file_args_ty");

1129 {Builder.getInt32Ty(), Builder.getInt32Ty(), Builder.getInt32Ty()},

1130 "emit_function_args_ty");

1131 auto *PtrTy = Builder.getPtrTy();

1133 StructType::create({Builder.getInt32Ty(), PtrTy}, "emit_arcs_args_ty");

1135 {StartFileCallArgsTy, Builder.getInt32Ty(), PtrTy, PtrTy}, "file_info");

1136

1137 Constant *Zero32 = Builder.getInt32(0);

1138

1139 Constant *TwoZero32s[] = {Zero32, Zero32};

1140

1144

1145

1147 continue;

1148

1149 std::string FilenameGcda = mangleName(CU, GCovFileType::GCDA);

1152 StartFileCallArgsTy,

1153 {Builder.CreateGlobalString(FilenameGcda),

1155 Builder.getInt32(CfgChecksum)});

1156

1160 uint32_t FuncChecksum = Funcs.empty() ? 0 : Funcs[j]->getFuncChecksum();

1162 EmitFunctionCallArgsTy,

1163 {Builder.getInt32(j),

1164 Builder.getInt32(FuncChecksum),

1165 Builder.getInt32(CfgChecksum)}));

1166

1170 EmitArcsCallArgsTy,

1173 }

1174

1175 int CountersSize = CountersBySP.size();

1176 assert(CountersSize == (int)EmitFunctionCallArgsArray.size() &&

1177 "Mismatched array size!");

1178 assert(CountersSize == (int)EmitArcsCallArgsArray.size() &&

1179 "Mismatched array size!");

1180 auto *EmitFunctionCallArgsArrayTy =

1181 ArrayType::get(EmitFunctionCallArgsTy, CountersSize);

1182 auto *EmitFunctionCallArgsArrayGV = new GlobalVariable(

1183 *M, EmitFunctionCallArgsArrayTy, true,

1186 EmitFunctionCallArgsArray),

1187 Twine("__llvm_internal_gcov_emit_function_args.") + Twine(i));

1188 auto *EmitArcsCallArgsArrayTy =

1190 EmitFunctionCallArgsArrayGV->setUnnamedAddr(

1193 *M, EmitArcsCallArgsArrayTy, true,

1196 Twine("__llvm_internal_gcov_emit_arcs_args.") + Twine(i));

1198

1200 FileInfoTy,

1201 {StartFileCallArgs, Builder.getInt32(CountersSize),

1203 EmitFunctionCallArgsArrayGV,

1204 TwoZero32s),

1206 EmitArcsCallArgsArrayTy, EmitArcsCallArgsArrayGV, TwoZero32s)}));

1207 }

1208

1209

1210 if (FileInfos.empty()) {

1211 Builder.CreateRetVoid();

1212 return WriteoutF;

1213 }

1214

1215

1216

1217

1218

1219

1220 if ((int64_t)FileInfos.size() > (int64_t)INT_MAX)

1221 FileInfos.resize(INT_MAX);

1222

1223

1224

1225 auto *FileInfoArrayTy = ArrayType::get(FileInfoTy, FileInfos.size());

1229 "__llvm_internal_gcov_emit_file_info");

1231

1232

1233 auto *FileLoopHeader =

1235 auto *CounterLoopHeader =

1237 auto *FileLoopLatch = BasicBlock::Create(*Ctx, "file.loop.latch", WriteoutF);

1239

1240

1241 Builder.CreateBr(FileLoopHeader);

1242

1243

1244 Builder.SetInsertPoint(FileLoopHeader);

1245 PHINode *IV = Builder.CreatePHI(Builder.getInt32Ty(), 2,

1246 "file_idx");

1247 IV->addIncoming(Builder.getInt32(0), BB);

1248 auto *FileInfoPtr = Builder.CreateInBoundsGEP(

1249 FileInfoArrayTy, FileInfoArrayGV, {Builder.getInt32(0), IV});

1250 auto *StartFileCallArgsPtr =

1251 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 0, "start_file_args");

1252 auto *StartFileCall = Builder.CreateCall(

1253 StartFile,

1254 {Builder.CreateLoad(StartFileCallArgsTy->getElementType(0),

1255 Builder.CreateStructGEP(StartFileCallArgsTy,

1256 StartFileCallArgsPtr, 0),

1257 "filename"),

1258 Builder.CreateLoad(StartFileCallArgsTy->getElementType(1),

1259 Builder.CreateStructGEP(StartFileCallArgsTy,

1260 StartFileCallArgsPtr, 1),

1261 "version"),

1262 Builder.CreateLoad(StartFileCallArgsTy->getElementType(2),

1263 Builder.CreateStructGEP(StartFileCallArgsTy,

1264 StartFileCallArgsPtr, 2),

1265 "stamp")});

1266 if (auto AK = TLI->getExtAttrForI32Param(false))

1267 StartFileCall->addParamAttr(2, AK);

1269 FileInfoTy->getElementType(1),

1270 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 1), "num_ctrs");

1271 auto *EmitFunctionCallArgsArray =

1272 Builder.CreateLoad(FileInfoTy->getElementType(2),

1273 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 2),

1274 "emit_function_args");

1275 auto *EmitArcsCallArgsArray = Builder.CreateLoad(

1276 FileInfoTy->getElementType(3),

1277 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 3), "emit_arcs_args");

1278 auto *EnterCounterLoopCond =

1279 Builder.CreateICmpSLT(Builder.getInt32(0), NumCounters);

1280 Builder.CreateCondBr(EnterCounterLoopCond, CounterLoopHeader, FileLoopLatch);

1281

1282 Builder.SetInsertPoint(CounterLoopHeader);

1283 auto *JV = Builder.CreatePHI(Builder.getInt32Ty(), 2,

1284 "ctr_idx");

1285 JV->addIncoming(Builder.getInt32(0), FileLoopHeader);

1286 auto *EmitFunctionCallArgsPtr = Builder.CreateInBoundsGEP(

1287 EmitFunctionCallArgsTy, EmitFunctionCallArgsArray, JV);

1288 auto *EmitFunctionCall = Builder.CreateCall(

1289 EmitFunction,

1290 {Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(0),

1291 Builder.CreateStructGEP(EmitFunctionCallArgsTy,

1292 EmitFunctionCallArgsPtr, 0),

1293 "ident"),

1294 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(1),

1295 Builder.CreateStructGEP(EmitFunctionCallArgsTy,

1296 EmitFunctionCallArgsPtr, 1),

1297 "func_checkssum"),

1298 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(2),

1299 Builder.CreateStructGEP(EmitFunctionCallArgsTy,

1300 EmitFunctionCallArgsPtr, 2),

1301 "cfg_checksum")});

1302 if (auto AK = TLI->getExtAttrForI32Param(false)) {

1303 EmitFunctionCall->addParamAttr(0, AK);

1304 EmitFunctionCall->addParamAttr(1, AK);

1305 EmitFunctionCall->addParamAttr(2, AK);

1306 }

1307 auto *EmitArcsCallArgsPtr =

1308 Builder.CreateInBoundsGEP(EmitArcsCallArgsTy, EmitArcsCallArgsArray, JV);

1309 auto *EmitArcsCall = Builder.CreateCall(

1310 EmitArcs,

1311 {Builder.CreateLoad(

1313 Builder.CreateStructGEP(EmitArcsCallArgsTy, EmitArcsCallArgsPtr, 0),

1314 "num_counters"),

1315 Builder.CreateLoad(

1317 Builder.CreateStructGEP(EmitArcsCallArgsTy, EmitArcsCallArgsPtr, 1),

1318 "counters")});

1319 if (auto AK = TLI->getExtAttrForI32Param(false))

1320 EmitArcsCall->addParamAttr(0, AK);

1321 auto *NextJV = Builder.CreateAdd(JV, Builder.getInt32(1));

1322 auto *CounterLoopCond = Builder.CreateICmpSLT(NextJV, NumCounters);

1323 Builder.CreateCondBr(CounterLoopCond, CounterLoopHeader, FileLoopLatch);

1324 JV->addIncoming(NextJV, CounterLoopHeader);

1325

1326 Builder.SetInsertPoint(FileLoopLatch);

1327 Builder.CreateCall(SummaryInfo, {});

1328 Builder.CreateCall(EndFile, {});

1329 auto *NextIV = Builder.CreateAdd(IV, Builder.getInt32(1), "next_file_idx");

1330 auto *FileLoopCond =

1331 Builder.CreateICmpSLT(NextIV, Builder.getInt32(FileInfos.size()));

1332 Builder.CreateCondBr(FileLoopCond, FileLoopHeader, ExitBB);

1333 IV->addIncoming(NextIV, FileLoopLatch);

1334

1335 Builder.SetInsertPoint(ExitBB);

1336 Builder.CreateRetVoid();

1337

1338 return WriteoutF;

1339}

1340

1341Function *GCOVProfiler::insertReset(

1342 ArrayRef<std::pair<GlobalVariable *, MDNode *>> CountersBySP) {

1344 Function *ResetF = M->getFunction("__llvm_gcov_reset");

1345 if (!ResetF)

1346 ResetF = createInternalFunction(FTy, "__llvm_gcov_reset", "_ZTSFvvE");

1347 ResetF->addFnAttr(Attribute::NoInline);

1348

1352

1353

1354 for (const auto &I : CountersBySP) {

1358 GVTy->getNumElements() *

1359 GVTy->getElementType()->getScalarSizeInBits() / 8,

1361 }

1362

1365 Builder.CreateRetVoid();

1367

1368 Builder.CreateRet(ConstantInt::get(RetTy, 0));

1369 else

1371

1372 return ResetF;

1373}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

This file defines the StringMap class.

Expand Atomic instructions

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

This file provides the interface for the GCOV style profiler pass.

static unsigned wordsOfString(StringRef s)

Definition GCOVProfiling.cpp:71

static bool functionHasLines(const Function &F, unsigned &EndLine)

Definition GCOVProfiling.cpp:583

static bool isUsingScopeBasedEH(Function &F)

Definition GCOVProfiling.cpp:603

static void dumpEdges(CFGMST< Edge, BBInfo > &MST, GCOVFunction &GF)

Definition GCOVProfiling.cpp:735

static BasicBlock * getInstrBB(CFGMST< Edge, BBInfo > &MST, Edge &E, const DenseSet< const BasicBlock * > &ExecBlocks)

Definition GCOVProfiling.cpp:690

static cl::opt< std::string > DefaultGCOVVersion("default-gcov-version", cl::init("0000"), cl::Hidden, cl::ValueRequired)

static SmallString< 128 > getFilename(const DIScope *SP, vfs::FileSystem &VFS)

Extract a filename for a DIScope.

Definition GCOVProfiling.cpp:222

static StringRef getFunctionName(const DISubprogram *SP)

Definition GCOVProfiling.cpp:211

static cl::opt< bool > AtomicCounter("gcov-atomic-counter", cl::Hidden, cl::desc("Make counter updates atomic"))

Module.h This file contains the declarations for the Module class.

#define INSTR_PROF_DATA_ALIGNMENT

static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)

Machine Check Debug Module

This file implements a map that provides insertion order iteration.

FunctionAnalysisManager FAM

std::pair< BasicBlock *, BasicBlock * > Edge

Provides some synthesis utilities to produce sequences of values.

Defines the virtual file system interface vfs::FileSystem.

static const uint32_t IV[8]

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

Class to represent array types.

static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)

This static method is the primary way to construct an ArrayType.

LLVM Basic Block Representation.

LLVM_ABI const_iterator getFirstInsertionPt() const

Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...

const Function * getParent() const

Return the enclosing method, or null if none.

const Instruction & back() const

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)

Split the basic block into two basic blocks at the specified instruction.

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

Analysis pass which computes BlockFrequencyInfo.

BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...

Analysis pass which computes BranchProbabilityInfo.

Analysis providing branch probability information.

An union-find based Minimum Spanning Tree for CFG.

Edge & addEdge(BasicBlock *Src, BasicBlock *Dest, uint64_t W)

const std::vector< std::unique_ptr< Edge > > & allEdges() const

This class represents a function call, abstracting a target machine's calling convention.

static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)

static Constant * getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList)

Create an "inbounds" getelementptr.

static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)

This is an important base class in LLVM.

static LLVM_ABI Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

uint64_t getDWOId() const

Base class for scope-like contexts.

StringRef getFilename() const

Subprogram description. Uses SubclassData1.

Implements a dense probed hash-table based set.

Represents either an error or a value T.

A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...

Class to represent function types.

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

void addFnAttr(Attribute::AttrKind Kind)

Add function attributes to this function.

static Function * createWithDefaultAttr(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)

Creates a function with some attributes recorded in llvm.module.flags and the LLVMContext applied.

Type * getReturnType() const

Returns the type of the ret val.

GCOVBlock - Collects block information.

GCOVFunction - Collects function information.

GCOVFunction(GCOVFile &file)

LLVM_ABI StringRef getFilename() const

LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

Definition GCOVProfiling.cpp:560

@ DefaultVisibility

The GV is visible.

@ PrivateLinkage

Like Internal, but omit from symbol table.

@ InternalLinkage

Rename collisions when linking (static functions).

Type * getValueType() const

MaybeAlign getAlign() const

Returns the alignment of the given variable.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY

Return the number of successors that this instruction has.

LLVM_ABI void setNoSanitizeMetadata()

Sets the nosanitize metadata on this instruction.

void setDebugLoc(DebugLoc Loc)

Set the debug location information for this instruction.

LLVM_ABI void update(ArrayRef< uint8_t > Data)

This is an important class for using LLVM in a threaded context.

An instruction for reading from memory.

const MDOperand & getOperand(unsigned I) const

LLVM_ABI StringRef getString() const

A Module instance is used to store all the information related to an LLVM module.

LLVM_ABI MDNode * getOperand(unsigned i) const

LLVM_ABI unsigned getNumOperands() const

static PointerType * getUnqual(Type *ElementType)

This constructs a pointer to an object of the specified type in the default address space (address sp...

static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)

This constructs a pointer to an object of the specified type in a numbered address space.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses none()

Convenience factory function for the empty preserved set.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

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.

constexpr bool empty() const

empty - Check if the string is empty.

constexpr size_t size() const

size - Get the string size.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

Class to represent struct types.

static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)

This static method is the primary way to create a literal StructType.

static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)

This creates an identified struct.

Type * getElementType(unsigned N) const

Analysis pass providing the TargetLibraryInfo.

Provides information about what library functions are available for the current target.

AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const

bool getLibFunc(StringRef funcName, LibFunc &F) const

Searches for a particular function name.

Triple - Helper class for working with autoconf configuration names.

ObjectFormatType getObjectFormat() const

Get the object format for this triple.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

static LLVM_ABI Type * getVoidTy(LLVMContext &C)

static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)

bool isIntegerTy() const

True if this is an instance of IntegerType.

bool isVoidTy() const

Return true if this is 'void'.

LLVM Value Representation.

size_type count(const_arg_type_t< ValueT > V) const

Return 1 if the specified key is in the set, 0 otherwise.

An efficient, type-erasing, non-owning reference to a callable.

self_iterator getIterator()

A raw_ostream that writes to a file descriptor.

The virtual file system interface.

virtual bool exists(const Twine &Path)

Check whether Path exists.

constexpr char Args[]

Key for Kernel::Metadata::mArgs.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

@ BasicBlock

Various leaf nodes.

initializer< Ty > init(const Ty &Val)

Scope

Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...

NodeAddr< FuncNode * > Func

void write32(void *P, uint32_t V, endianness E)

uint32_t read32be(const void *P)

LLVM_ABI void replace_extension(SmallVectorImpl< char > &path, const Twine &extension, Style style=Style::native)

Replace the file extension of path with extension.

LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get filename.

LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

This is an optimization pass for GlobalISel generic memory operations.

hash_code hash_value(const FixedPointSemantics &Val)

LLVM_ABI unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ)

Search for the specified successor of basic block BB and return its position in the terminator instru...

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy

Provide the FunctionAnalysisManager to Module proxy.

LLVM_ABI bool SplitIndirectBrCriticalEdges(Function &F, bool IgnoreBlocksWithoutPHI, BranchProbabilityInfo *BPI=nullptr, BlockFrequencyInfo *BFI=nullptr)

LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)

Return the name of the profile section corresponding to IPSK.

bool isScopedEHPersonality(EHPersonality Pers)

Returns true if this personality uses scope-style EH IR instructions: catchswitch,...

iterator_range< pointee_iterator< WrappedIteratorT > > make_pointee_range(RangeT &&Range)

FunctionAddr VTableAddr uintptr_t uintptr_t Version

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)

See if the given exception handling personality function is one that we understand.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

LLVM_ABI BasicBlock * SplitCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions(), const Twine &BBName="")

If this edge is a critical edge, insert a new node to split the critical edge.

ArrayRef(const T &OneElt) -> ArrayRef< T >

LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)

Append F to the list of global ctors of module M with the given Priority.

LLVM_ABI void setKCFIType(Module &M, Function &F, StringRef MangledType)

Sets the KCFI type for the function.

LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

void erase_if(Container &C, UnaryPredicate P)

Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...

auto seq(T Begin, T End)

Iterate over an integral type from Begin up to - but not including - End.

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

LLVM_ABI DISubprogram * getDISubprogram(const MDNode *Scope)

Find subprogram that is enclosing this scope.

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

LLVM_ABI void reportFatalUsageError(Error Err)

Report a fatal error that does not indicate a bug in LLVM.

This struct is a compact representation of a valid (non-zero power of two) alignment.

static LLVM_ABI GCOVOptions getDefault()

Definition GCOVProfiling.cpp:76

This struct is a compact representation of a valid (power of two) or undefined (0) alignment.