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)
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);
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) {
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) {
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(
545 this->GetTLI = std::move(GetTLI);
546 Ctx = &M.getContext();
547
548 NamedMDNode *CUNode = M.getNamedMetadata("llvm.dbg.cu");
549 if (!CUNode || (.EmitNotes &&
.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 ()
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 (.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
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 (.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 (->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 ()
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.