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()) {
617 if (
Function *Callee = CI->getCalledFunction()) {
618 LibFunc LF =
TLI->getLibFunc(*Callee);
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(
645 TLI->getAttrList(Ctx, {},
true,
true));
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,
1062 TLI->getAttrList(Ctx, {1, 2},
false));
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,
1073 TLI->getAttrList(Ctx, {0, 1, 2},
false));
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,
1083 TLI->getAttrList(Ctx, {0},
false));
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));
const TargetLowering & TLI
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.
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.