52#define DEBUG_TYPE "insert-gcov-profiling"
66 return (s.
size() / 4) + 2;
72 Options.UseAbsolutePathsInNotes =
false;
75 Options.Atomic = Opts.gcov_atomic_counter;
77 if (Opts.default_gcov_version.size() != 4) {
79 Opts.default_gcov_version);
81 memcpy(
Options.Version, Opts.default_gcov_version.data(), 4);
90 GCOVProfiler(
const GCOVOptions &Opts, vfs::FileSystem &VFS)
93 runOnModule(
Module &M, function_ref<BlockFrequencyInfo *(
Function &
F)> GetBFI,
94 function_ref<BranchProbabilityInfo *(
Function &
F)> GetBPI,
95 std::function<
const TargetLibraryInfo &(
Function &
F)> GetTLI);
97 void write(uint32_t i) {
105 os->write_zeros(4 - s.
size() % 4);
107 void writeBytes(
const char *Bytes,
int Size) { os->write(Bytes,
Size); }
108 SmallString<128> getFilename(
const DIScope *SP);
113 emitProfileNotes(NamedMDNode *CUNode,
bool HasExecOrFork,
114 function_ref<BlockFrequencyInfo *(
Function &
F)> GetBFI,
115 function_ref<BranchProbabilityInfo *(
Function &
F)> GetBPI,
116 function_ref<
const TargetLibraryInfo &(
Function &
F)> GetTLI);
118 Function *createInternalFunction(FunctionType *FTy, StringRef Name,
119 StringRef MangledType =
"");
121 void emitGlobalConstructor(
122 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP);
123 void emitModuleInitFunctionPtrs(
124 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP);
126 bool isFunctionInstrumented(
const Function &
F);
127 std::vector<Regex> createRegexesFromString(StringRef RegexesStr);
128 static bool doesFilenameMatchARegex(StringRef
Filename,
129 std::vector<Regex> &Regexes);
132 FunctionCallee getStartFileFunc(
const TargetLibraryInfo *TLI);
133 FunctionCallee getEmitFunctionFunc(
const TargetLibraryInfo *TLI);
134 FunctionCallee getEmitArcsFunc(
const TargetLibraryInfo *TLI);
135 FunctionCallee getSummaryInfoFunc();
136 FunctionCallee getEndFileFunc();
141 insertCounterWriteout(
ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
144 bool AddFlushBeforeForkAndExec();
146 enum class GCovFileType { GCNO, GCDA };
147 std::string mangleName(
const DICompileUnit *CU, GCovFileType FileType);
158 std::function<
const TargetLibraryInfo &(
Function &
F)> GetTLI;
159 LLVMContext *Ctx =
nullptr;
161 std::vector<Regex> FilterRe;
162 std::vector<Regex> ExcludeRe;
163 DenseSet<const BasicBlock *> ExecBlocks;
164 StringMap<bool> InstrumentedFiles;
165 vfs::FileSystem &VFS;
173 BBInfo(
unsigned Index) : Group(this),
Index(
Index) {}
174 std::string infoString()
const {
175 return (Twine(
"Index=") + Twine(Index)).str();
186 uint32_t SrcNumber, DstNumber;
188 bool Removed =
false;
189 bool IsCritical =
false;
191 Edge(
const BasicBlock *Src,
const BasicBlock *Dest,
uint64_t W = 1)
192 : SrcBB(Src), DestBB(Dest), Weight(
W) {}
195 std::string infoString()
const {
196 return (Twine(Removed ?
"-" :
" ") + (InMST ?
" " :
"*") +
197 (IsCritical ?
"c" :
" ") +
" W=" + Twine(Weight))
204 if (!SP->getLinkageName().empty())
205 return SP->getLinkageName();
206 return SP->getName();
216 SmallString<128>
Path;
217 StringRef RelPath =
SP->getFilename();
218 if (VFS.
exists(RelPath)) {
220 if (
Options.UseAbsolutePathsInNotes) {
235 GCOVRecord(GCOVProfiler *
P) :
P(
P) {}
237 void write(uint32_t i) {
P->write(i); }
239 void writeBytes(
const char *Bytes,
int Size) {
P->writeBytes(Bytes,
Size); }
248 class GCOVLines :
public GCOVRecord {
250 StringRef getFilename() {
return Filename; }
252 void addLine(uint32_t Line) {
253 assert(Line != 0 &&
"Line zero is not a valid real line number.");
257 uint32_t length()
const {
264 for (uint32_t L : Lines)
268 GCOVLines(GCOVProfiler *
P, StringRef
F)
273 SmallVector<uint32_t, 32> Lines;
280 class GCOVBlock :
public GCOVRecord {
282 GCOVLines &getFile(StringRef
Filename) {
283 if (Lines.empty() || Lines.back().getFilename() !=
Filename)
289 OutEdges.emplace_back(&
Successor, Flags);
295 for (
auto &L : Lines)
302 for (
auto &L : Lines)
320 friend class GCOVFunction;
322 GCOVBlock(GCOVProfiler *
P, uint32_t
Number)
331 class GCOVFunction :
public GCOVRecord {
333 GCOVFunction(GCOVProfiler *
P,
Function *
F,
const DISubprogram *SP,
334 unsigned EndLine, uint32_t Ident,
int Version)
335 : GCOVRecord(
P),
SP(
SP), EndLine(EndLine), Ident(Ident),
339 for (BasicBlock &BB : *
F)
340 Blocks.insert(std::make_pair(&BB, GCOVBlock(
P, i++)));
342 std::string FunctionNameAndLine;
343 raw_string_ostream FNLOS(FunctionNameAndLine);
345 FuncChecksum =
hash_value(FunctionNameAndLine);
348 GCOVBlock &getBlock(
const BasicBlock *BB) {
349 return Blocks.find(
const_cast<BasicBlock *
>(BB))->second;
352 GCOVBlock &getEntryBlock() {
return EntryBlock; }
353 GCOVBlock &getReturnBlock() {
357 uint32_t getFuncChecksum()
const {
361 void writeOut(uint32_t CfgChecksum) {
363 SmallString<128>
Filename =
P->getFilename(SP);
385 write(Blocks.size() + 2);
389 const uint32_t Outgoing = EntryBlock.OutEdges.size();
392 write(Outgoing * 2 + 1);
393 write(EntryBlock.Number);
394 for (
const auto &
E : EntryBlock.OutEdges) {
399 for (
auto &It : Blocks) {
400 const GCOVBlock &
Block = It.second;
401 if (
Block.OutEdges.empty())
continue;
406 for (
const auto &
E :
Block.OutEdges) {
413 for (
auto &It : Blocks)
414 It.second.writeOut();
418 const DISubprogram *
SP;
421 uint32_t FuncChecksum;
423 MapVector<BasicBlock *, GCOVBlock> Blocks;
424 GCOVBlock EntryBlock;
425 GCOVBlock ReturnBlock;
431std::vector<Regex> GCOVProfiler::createRegexesFromString(StringRef RegexesStr) {
432 std::vector<Regex> Regexes;
433 while (!RegexesStr.
empty()) {
434 std::pair<StringRef, StringRef> HeadTail = RegexesStr.
split(
';');
435 if (!HeadTail.first.empty()) {
436 Regex Re(HeadTail.first);
438 if (!Re.isValid(Err)) {
439 Ctx->
emitError(Twine(
"Regex ") + HeadTail.first +
440 " is not valid: " + Err);
442 Regexes.emplace_back(std::move(Re));
444 RegexesStr = HeadTail.second;
449bool GCOVProfiler::doesFilenameMatchARegex(StringRef
Filename,
450 std::vector<Regex> &Regexes) {
451 for (Regex &Re : Regexes)
457bool GCOVProfiler::isFunctionInstrumented(
const Function &
F) {
458 if (FilterRe.empty() && ExcludeRe.empty()) {
461 SmallString<128>
Filename = getFilename(
F.getSubprogram());
463 if (It != InstrumentedFiles.
end()) {
467 SmallString<256> RealPath;
468 StringRef RealFilename;
477 RealFilename = RealPath;
480 bool ShouldInstrument;
481 if (FilterRe.empty()) {
482 ShouldInstrument = !doesFilenameMatchARegex(RealFilename, ExcludeRe);
483 }
else if (ExcludeRe.empty()) {
484 ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe);
486 ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe) &&
487 !doesFilenameMatchARegex(RealFilename, ExcludeRe);
489 InstrumentedFiles[
Filename] = ShouldInstrument;
490 return ShouldInstrument;
493std::string GCOVProfiler::mangleName(
const DICompileUnit *CU,
494 GCovFileType OutputType) {
495 bool Notes = OutputType == GCovFileType::GCNO;
497 if (NamedMDNode *GCov =
M->getNamedMetadata(
"llvm.gcov")) {
498 for (
int i = 0, e = GCov->getNumOperands(); i != e; ++i) {
499 MDNode *
N = GCov->getOperand(i);
500 bool ThreeElement =
N->getNumOperands() == 3;
501 if (!ThreeElement &&
N->getNumOperands() != 2)
511 if (!NotesFile || !DataFile)
513 return std::string(Notes ? NotesFile->
getString()
532 return std::string(FName);
533 SmallString<128> CurPath{*CWD};
535 return std::string(CurPath);
538bool GCOVProfiler::runOnModule(
540 function_ref<BranchProbabilityInfo *(
Function &
F)> GetBPI,
541 std::function<
const TargetLibraryInfo &(
Function &
F)> GetTLI) {
543 this->GetTLI = std::move(GetTLI);
544 Ctx = &
M.getContext();
546 NamedMDNode *CUNode =
M.getNamedMetadata(
"llvm.dbg.cu");
550 bool HasExecOrFork = AddFlushBeforeForkAndExec();
552 FilterRe = createRegexesFromString(
Options.Filter);
553 ExcludeRe = createRegexesFromString(
Options.Exclude);
554 emitProfileNotes(CUNode, HasExecOrFork, GetBFI, GetBPI, this->GetTLI);
576 if (!Profiler.runOnModule(M, GetBFI, GetBPI, GetTLI))
586 for (
const auto &BB :
F) {
587 for (
const auto &
I : BB) {
593 if (
Loc.getLine() == 0)
continue;
594 EndLine = std::max(EndLine,
Loc.getLine());
603 if (!
F.hasPersonalityFn())
return false;
609bool GCOVProfiler::AddFlushBeforeForkAndExec() {
610 const TargetLibraryInfo *TLI =
nullptr;
613 for (
auto &
F :
M->functions()) {
614 TLI = TLI ==
nullptr ? &GetTLI(
F) : TLI;
617 if (
Function *Callee = CI->getCalledFunction()) {
619 if (LF != NotLibFunc) {
620 if (LF == LibFunc_fork) {
624 }
else if (LF == LibFunc_execl || LF == LibFunc_execle ||
625 LF == LibFunc_execlp || LF == LibFunc_execv ||
626 LF == LibFunc_execvp || LF == LibFunc_execve ||
627 LF == LibFunc_execvpe || LF == LibFunc_execvP) {
636 for (
auto *
F : Forks) {
639 auto NextInst = ++
F->getIterator();
642 FunctionType *FTy = FunctionType::get(Builder.getInt32Ty(), {},
false);
643 FunctionCallee GCOVFork =
M->getOrInsertFunction(
646 F->setCalledFunction(GCOVFork);
663 for (
auto *
E : Execs) {
670 FunctionType *FTy = FunctionType::get(Builder.getVoidTy(), {},
false);
671 FunctionCallee WriteoutF =
672 M->getOrInsertFunction(
"llvm_writeout_files", FTy);
673 Builder.CreateCall(WriteoutF);
676 Builder.SetInsertPoint(&*NextInst);
679 FunctionCallee ResetF =
M->getOrInsertFunction(
"llvm_reset_counters", FTy);
680 Builder.CreateCall(ResetF)->setDebugLoc(Loc);
681 ExecBlocks.insert(Parent);
686 return !Forks.empty() || !Execs.empty();
691 if (
E.InMST ||
E.Removed)
697 if (SrcBB ==
nullptr)
699 if (DestBB ==
nullptr)
714 return CanInstrument(SrcBB);
716 return CanInstrument(DestBB);
726 MST.
addEdge(SrcBB, InstrBB, 0);
727 MST.
addEdge(InstrBB, DestBB, 0).InMST =
true;
730 return CanInstrument(InstrBB);
737 GCOVBlock &Src =
E.SrcBB ? GF.getBlock(
E.SrcBB) : GF.getEntryBlock();
738 GCOVBlock &Dst =
E.DestBB ? GF.getBlock(
E.DestBB) : GF.getReturnBlock();
739 dbgs() <<
" Edge " << ID++ <<
": " << Src.Number <<
"->" << Dst.Number
740 <<
E.infoString() <<
"\n";
745bool GCOVProfiler::emitProfileNotes(
746 NamedMDNode *CUNode,
bool HasExecOrFork,
747 function_ref<BlockFrequencyInfo *(
Function &
F)> GetBFI,
748 function_ref<BranchProbabilityInfo *(
Function &
F)> GetBPI,
749 function_ref<
const TargetLibraryInfo &(
Function &
F)> GetTLI) {
751 uint8_t c3 =
Options.Version[0];
752 uint8_t c2 =
Options.Version[1];
753 uint8_t c1 =
Options.Version[2];
754 Version = c3 >=
'A' ? (c3 -
'A') * 100 + (c2 -
'0') * 10 + c1 -
'0'
755 : (c3 -
'0') * 10 + c1 -
'0';
760 memcpy(
Options.Version,
"B11*", 4);
763 bool EmitGCDA =
Options.EmitData;
775 std::vector<uint8_t> EdgeDestinations;
780 unsigned FunctionIdent = 0;
781 for (
auto &
F :
M->functions()) {
782 DISubprogram *
SP =
F.getSubprogram();
789 if (
F.hasFnAttribute(llvm::Attribute::NoProfile))
791 if (
F.hasFnAttribute(llvm::Attribute::SkipProfile))
796 uint32_t
Line =
SP->getLine();
799 BranchProbabilityInfo *BPI = GetBPI(
F);
800 BlockFrequencyInfo *BFI = GetBFI(
F);
807 CFGMST<Edge, BBInfo> MST(
F,
false,
812 auto &
E = *MST.allEdges()[
I];
821 Funcs.push_back(std::make_unique<GCOVFunction>(
this, &
F, SP, EndLine,
823 GCOVFunction &
Func = *Funcs.back();
828 return E->Removed || (!E->InMST && !E->Place);
830 const size_t Measured =
831 std::stable_partition(
832 MST.allEdges().begin(), MST.allEdges().end(),
833 [](std::unique_ptr<Edge> &
E) { return E->Place; }) -
834 MST.allEdges().begin();
836 Edge &
E = *MST.allEdges()[
I];
838 E.SrcBB ?
Func.getBlock(
E.SrcBB) :
Func.getEntryBlock();
840 E.DestBB ?
Func.getBlock(
E.DestBB) :
Func.getReturnBlock();
841 E.SrcNumber = Src.Number;
842 E.DstNumber = Dst.Number;
845 MST.allEdges().begin(), MST.allEdges().begin() + Measured,
846 [](
const std::unique_ptr<Edge> &L,
const std::unique_ptr<Edge> &R) {
847 return L->SrcNumber != R->SrcNumber ? L->SrcNumber < R->SrcNumber
848 : L->DstNumber < R->DstNumber;
853 E.SrcBB ?
Func.getBlock(
E.SrcBB) :
Func.getEntryBlock();
855 E.DestBB ?
Func.getBlock(
E.DestBB) :
Func.getReturnBlock();
860 if (!
SP->isArtificial())
861 Func.getBlock(&EntryBlock).getFile(
Filename).addLine(Line);
865 for (
auto &GB :
Func.Blocks) {
867 auto &
Block = GB.second;
868 for (
auto Succ :
Block.OutEdges) {
869 uint32_t
Idx = Succ.first->Number;
870 do EdgeDestinations.push_back(Idx & 255);
871 while ((Idx >>= 8) > 0);
874 for (
const auto &
I : BB) {
883 if (Line == Loc.
getLine())
continue;
889 GCOVLines &
Lines =
Block.getFile(getFilename(Loc->getScope()));
895 DISubprogram *
SP =
F.getSubprogram();
896 ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(*Ctx), Measured);
897 GlobalVariable *
Counters =
new GlobalVariable(
900 const llvm::Triple &Triple =
M->getTargetTriple();
902 Counters->setSection(
"__llvm_gcov_ctr_section");
906 const Edge &
E = *MST.allEdges()[
I];
908 Value *
V = Builder.CreateConstInBoundsGEP2_64(
915 Builder.getInt64(1), MaybeAlign(),
916 AtomicOrdering::Monotonic);
919 Builder.CreateLoad(Builder.getInt64Ty(), V,
"gcov_ctr");
921 Value *NewCount = Builder.CreateAdd(OldCount, Builder.getInt64(1));
922 Inst = Builder.CreateStore(NewCount, V);
931 JC.
update(EdgeDestinations);
932 uint32_t Stamp = JC.
getCRC();
937 raw_fd_ostream out(mangleName(CU, GCovFileType::GCNO), EC,
941 Twine(
"failed to open coverage notes file for writing: ") +
947 out.write(
"gcno", 4);
950 out.write(
"oncg", 4);
958 for (
auto &Func : Funcs)
959 Func->writeOut(Stamp);
967 const llvm::Triple &Triple =
M->getTargetTriple();
969 emitModuleInitFunctionPtrs(CountersBySP);
971 emitGlobalConstructor(CountersBySP);
978Function *GCOVProfiler::createInternalFunction(FunctionType *FTy,
980 StringRef MangledType ) {
983 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
984 F->addFnAttr(Attribute::NoUnwind);
986 F->addFnAttr(Attribute::NoRedZone);
987 if (!MangledType.
empty())
992void GCOVProfiler::emitGlobalConstructor(
993 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) {
994 Function *WriteoutF = insertCounterWriteout(CountersBySP);
995 Function *ResetF = insertReset(CountersBySP);
1000 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
false);
1001 Function *
F = createInternalFunction(FTy,
"__llvm_gcov_init",
"_ZTSFvvE");
1002 F->addFnAttr(Attribute::NoInline);
1007 FTy = FunctionType::get(Type::getVoidTy(*Ctx),
false);
1008 auto *PFTy = PointerType::get(*Ctx, 0);
1009 FTy = FunctionType::get(Builder.getVoidTy(), {PFTy, PFTy},
false);
1013 FunctionCallee GCOVInit =
M->getOrInsertFunction(
"llvm_gcov_init", FTy);
1014 Builder.CreateCall(GCOVInit, {WriteoutF, ResetF});
1015 Builder.CreateRetVoid();
1020void GCOVProfiler::emitModuleInitFunctionPtrs(
1021 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) {
1022 Function *WriteoutF = insertCounterWriteout(CountersBySP);
1023 Function *ResetF = insertReset(CountersBySP);
1029 auto &Ctx =
M->getContext();
1031 Type *InitFuncDataTy[] = {
1032#define COVINIT_FUNC(Type, LLVMType, Name, Init) LLVMType,
1039#define COVINIT_FUNC(Type, LLVMType, Name, Init) Init,
1045 "__llvm_covinit_functions");
1047 CovInitGV->setVisibility(GlobalValue::VisibilityTypes::DefaultVisibility);
1049 IPSK_covinit,
M->getTargetTriple().getObjectFormat()));
1051 CovInitGV->setConstant(
true);
1054FunctionCallee GCOVProfiler::getStartFileFunc(
const TargetLibraryInfo *TLI) {
1056 PointerType::getUnqual(*Ctx),
1057 Type::getInt32Ty(*Ctx),
1058 Type::getInt32Ty(*Ctx),
1060 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args,
false);
1061 return M->getOrInsertFunction(
"llvm_gcda_start_file", FTy,
1065FunctionCallee GCOVProfiler::getEmitFunctionFunc(
const TargetLibraryInfo *TLI) {
1067 Type::getInt32Ty(*Ctx),
1068 Type::getInt32Ty(*Ctx),
1069 Type::getInt32Ty(*Ctx),
1071 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args,
false);
1072 return M->getOrInsertFunction(
"llvm_gcda_emit_function", FTy,
1076FunctionCallee GCOVProfiler::getEmitArcsFunc(
const TargetLibraryInfo *TLI) {
1078 Type::getInt32Ty(*Ctx),
1079 PointerType::getUnqual(*Ctx),
1081 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args,
false);
1082 return M->getOrInsertFunction(
"llvm_gcda_emit_arcs", FTy,
1086FunctionCallee GCOVProfiler::getSummaryInfoFunc() {
1087 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
false);
1088 return M->getOrInsertFunction(
"llvm_gcda_summary_info", FTy);
1091FunctionCallee GCOVProfiler::getEndFileFunc() {
1092 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
false);
1093 return M->getOrInsertFunction(
"llvm_gcda_end_file", FTy);
1096Function *GCOVProfiler::insertCounterWriteout(
1097 ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
1098 FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx),
false);
1099 Function *WriteoutF =
M->getFunction(
"__llvm_gcov_writeout");
1102 createInternalFunction(WriteoutFTy,
"__llvm_gcov_writeout",
"_ZTSFvvE");
1103 WriteoutF->
addFnAttr(Attribute::NoInline);
1108 auto *TLI = &GetTLI(*WriteoutF);
1110 FunctionCallee StartFile = getStartFileFunc(TLI);
1111 FunctionCallee EmitFunction = getEmitFunctionFunc(TLI);
1112 FunctionCallee EmitArcs = getEmitArcsFunc(TLI);
1113 FunctionCallee SummaryInfo = getSummaryInfoFunc();
1114 FunctionCallee EndFile = getEndFileFunc();
1116 NamedMDNode *CUNodes =
M->getNamedMetadata(
"llvm.dbg.cu");
1118 Builder.CreateRetVoid();
1125 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getInt32Ty()},
1126 "start_file_args_ty");
1128 {Builder.getInt32Ty(), Builder.getInt32Ty(), Builder.getInt32Ty()},
1129 "emit_function_args_ty");
1130 auto *PtrTy = Builder.getPtrTy();
1131 StructType *EmitArcsCallArgsTy =
1134 {StartFileCallArgsTy, Builder.
getInt32Ty(), PtrTy, PtrTy},
"file_info");
1144 std::string FilenameGcda = mangleName(CU, GCovFileType::GCDA);
1145 uint32_t CfgChecksum = FileChecksums.
empty() ? 0 : FileChecksums[i];
1147 StartFileCallArgsTy,
1148 {Builder.CreateGlobalString(FilenameGcda),
1150 Builder.getInt32(CfgChecksum)});
1155 uint32_t FuncChecksum = Funcs.empty() ? 0 : Funcs[
j]->getFuncChecksum();
1157 EmitFunctionCallArgsTy,
1158 {Builder.getInt32(j),
1159 Builder.getInt32(FuncChecksum),
1160 Builder.getInt32(CfgChecksum)}));
1162 GlobalVariable *GV = CountersBySP[
j].first;
1165 EmitArcsCallArgsTy, {Builder.getInt32(Arcs), GV}));
1168 int CountersSize = CountersBySP.
size();
1169 assert(CountersSize == (
int)EmitFunctionCallArgsArray.size() &&
1170 "Mismatched array size!");
1171 assert(CountersSize == (
int)EmitArcsCallArgsArray.
size() &&
1172 "Mismatched array size!");
1173 auto *EmitFunctionCallArgsArrayTy =
1174 ArrayType::get(EmitFunctionCallArgsTy, CountersSize);
1175 auto *EmitFunctionCallArgsArrayGV =
new GlobalVariable(
1176 *M, EmitFunctionCallArgsArrayTy,
true,
1179 EmitFunctionCallArgsArray),
1180 Twine(
"__llvm_internal_gcov_emit_function_args.") + Twine(i));
1181 auto *EmitArcsCallArgsArrayTy =
1182 ArrayType::get(EmitArcsCallArgsTy, CountersSize);
1183 EmitFunctionCallArgsArrayGV->setUnnamedAddr(
1184 GlobalValue::UnnamedAddr::Global);
1185 auto *EmitArcsCallArgsArrayGV =
new GlobalVariable(
1186 *M, EmitArcsCallArgsArrayTy,
true,
1189 Twine(
"__llvm_internal_gcov_emit_arcs_args.") + Twine(i));
1190 EmitArcsCallArgsArrayGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
1193 FileInfoTy, {StartFileCallArgs, Builder.getInt32(CountersSize),
1194 EmitFunctionCallArgsArrayGV, EmitArcsCallArgsArrayGV}));
1198 if (FileInfos.empty()) {
1199 Builder.CreateRetVoid();
1208 if ((int64_t)FileInfos.size() > (int64_t)INT_MAX)
1209 FileInfos.resize(INT_MAX);
1213 auto *FileInfoArrayTy = ArrayType::get(FileInfoTy, FileInfos.size());
1214 auto *FileInfoArrayGV =
new GlobalVariable(
1217 "__llvm_internal_gcov_emit_file_info");
1218 FileInfoArrayGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
1221 auto *FileLoopHeader =
1223 auto *CounterLoopHeader =
1229 Builder.CreateBr(FileLoopHeader);
1232 Builder.SetInsertPoint(FileLoopHeader);
1233 PHINode *
IV = Builder.CreatePHI(Builder.getInt32Ty(), 2,
1235 IV->addIncoming(Builder.getInt32(0), BB);
1236 auto *FileInfoPtr = Builder.CreateInBoundsGEP(
1237 FileInfoArrayTy, FileInfoArrayGV, {Builder.getInt32(0),
IV});
1238 auto *StartFileCallArgsPtr =
1239 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 0,
"start_file_args");
1240 auto *StartFileCall = Builder.CreateCall(
1243 Builder.CreateStructGEP(StartFileCallArgsTy,
1244 StartFileCallArgsPtr, 0),
1247 Builder.CreateStructGEP(StartFileCallArgsTy,
1248 StartFileCallArgsPtr, 1),
1251 Builder.CreateStructGEP(StartFileCallArgsTy,
1252 StartFileCallArgsPtr, 2),
1254 if (
auto AK = TLI->getExtAttrForI32Param(
false))
1255 StartFileCall->addParamAttr(2, AK);
1256 auto *NumCounters = Builder.CreateLoad(
1257 FileInfoTy->getElementType(1),
1258 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 1),
"num_ctrs");
1259 auto *EmitFunctionCallArgsArray =
1260 Builder.CreateLoad(FileInfoTy->getElementType(2),
1261 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 2),
1262 "emit_function_args");
1263 auto *EmitArcsCallArgsArray = Builder.CreateLoad(
1264 FileInfoTy->getElementType(3),
1265 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 3),
"emit_arcs_args");
1266 auto *EnterCounterLoopCond =
1267 Builder.CreateICmpSLT(Builder.getInt32(0), NumCounters);
1268 Builder.CreateCondBr(EnterCounterLoopCond, CounterLoopHeader, FileLoopLatch);
1270 Builder.SetInsertPoint(CounterLoopHeader);
1271 auto *JV = Builder.CreatePHI(Builder.getInt32Ty(), 2,
1273 JV->addIncoming(Builder.getInt32(0), FileLoopHeader);
1274 auto *EmitFunctionCallArgsPtr = Builder.CreateInBoundsGEP(
1275 EmitFunctionCallArgsTy, EmitFunctionCallArgsArray, JV);
1276 auto *EmitFunctionCall = Builder.CreateCall(
1278 {Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(0),
1279 Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1280 EmitFunctionCallArgsPtr, 0),
1282 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(1),
1283 Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1284 EmitFunctionCallArgsPtr, 1),
1286 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(2),
1287 Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1288 EmitFunctionCallArgsPtr, 2),
1290 if (
auto AK = TLI->getExtAttrForI32Param(
false)) {
1291 EmitFunctionCall->addParamAttr(0, AK);
1292 EmitFunctionCall->addParamAttr(1, AK);
1293 EmitFunctionCall->addParamAttr(2, AK);
1295 auto *EmitArcsCallArgsPtr =
1296 Builder.CreateInBoundsGEP(EmitArcsCallArgsTy, EmitArcsCallArgsArray, JV);
1297 auto *EmitArcsCall = Builder.CreateCall(
1299 {Builder.CreateLoad(
1301 Builder.CreateStructGEP(EmitArcsCallArgsTy, EmitArcsCallArgsPtr, 0),
1305 Builder.CreateStructGEP(EmitArcsCallArgsTy, EmitArcsCallArgsPtr, 1),
1307 if (
auto AK = TLI->getExtAttrForI32Param(
false))
1308 EmitArcsCall->addParamAttr(0, AK);
1309 auto *NextJV = Builder.CreateAdd(JV, Builder.getInt32(1));
1310 auto *CounterLoopCond = Builder.CreateICmpSLT(NextJV, NumCounters);
1311 Builder.CreateCondBr(CounterLoopCond, CounterLoopHeader, FileLoopLatch);
1312 JV->addIncoming(NextJV, CounterLoopHeader);
1314 Builder.SetInsertPoint(FileLoopLatch);
1315 Builder.CreateCall(SummaryInfo, {});
1316 Builder.CreateCall(EndFile, {});
1317 auto *NextIV = Builder.CreateAdd(
IV, Builder.getInt32(1),
"next_file_idx");
1318 auto *FileLoopCond =
1319 Builder.CreateICmpSLT(NextIV, Builder.getInt32(FileInfos.size()));
1320 Builder.CreateCondBr(FileLoopCond, FileLoopHeader, ExitBB);
1321 IV->addIncoming(NextIV, FileLoopLatch);
1323 Builder.SetInsertPoint(ExitBB);
1324 Builder.CreateRetVoid();
1329Function *GCOVProfiler::insertReset(
1330 ArrayRef<std::pair<GlobalVariable *, MDNode *>> CountersBySP) {
1331 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
false);
1332 Function *ResetF =
M->getFunction(
"__llvm_gcov_reset");
1334 ResetF = createInternalFunction(FTy,
"__llvm_gcov_reset",
"_ZTSFvvE");
1339 LLVMContext &
C =
Entry->getContext();
1342 for (
const auto &
I : CountersBySP) {
1343 GlobalVariable *GV =
I.first;
1346 GVTy->getNumElements() *
1347 GVTy->getElementType()->getScalarSizeInBits() / 8,
1353 Builder.CreateRetVoid();
1356 Builder.CreateRet(ConstantInt::get(RetTy, 0));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
Expand Atomic instructions
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static void writeString(raw_ostream &OS, StringRef S)
This file provides the interface for the GCOV style profiler pass.
static GCOVOptions getDefaultOptions(const InstrumentationOptions &Opts)
static unsigned wordsOfString(StringRef s)
static bool functionHasLines(const Function &F, unsigned &EndLine)
static bool isUsingScopeBasedEH(Function &F)
static void dumpEdges(CFGMST< Edge, BBInfo > &MST, GCOVFunction &GF)
static BasicBlock * getInstrBB(CFGMST< Edge, BBInfo > &MST, Edge &E, const DenseSet< const BasicBlock * > &ExecBlocks)
static StringRef getFunctionName(const DISubprogram *SP)
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.
static constexpr StringLiteral Filename
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.
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...
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
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.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Analysis pass which computes BlockFrequencyInfo.
Analysis pass which computes BranchProbabilityInfo.
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
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
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.
LLVM_ABI unsigned getLine() const
LLVM_ABI MDNode * getScope() const
LLVM_ABI bool isImplicitCode() const
Check if the DebugLoc corresponds to an implicit code.
Implements a dense probed hash-table based set.
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.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
@ 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.
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)
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
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
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...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
iterator find(StringRef Key)
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
Check if the string is empty.
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
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
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
virtual bool exists(const Twine &Path)
Check whether Path exists.
virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output)
Gets real path of Path e.g.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ BasicBlock
Various leaf nodes.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
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 bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
Remove '.
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.
const InstrumentationOptions & getInstrumentationOptions(const LLVMContext &C)
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<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool SplitIndirectBrCriticalEdges(Function &F, bool IgnoreBlocksWithoutPHI, BranchProbabilityInfo *BPI=nullptr, BlockFrequencyInfo *BFI=nullptr, DomTreeUpdater *DTU=nullptr)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
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,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
iterator_range< pointee_iterator< WrappedIteratorT > > make_pointee_range(RangeT &&Range)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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<X> - 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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI Error write(DWPWriter &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue, raw_pwrite_stream *OS=nullptr)
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.