19#include "llvm/Config/llvm-config.h"
33#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
41#define DEBUG_TYPE "debugify"
50 cl::desc(
"Suppress verbose debugify output"));
53 "debugify-func-limit",
54 cl::desc(
"Set max number of processed functions per pass."),
63 "debugify-level",
cl::desc(
"Kind of debug info to add"),
65 clEnumValN(Level::LocationsAndVariables,
"location+variables",
66 "Locations and Variables")),
67 cl::init(Level::LocationsAndVariables));
71#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
73 "enable-origin-stacktraces",
74 cl::desc(
"Collect DebugLoc origin stacktraces; a comma-separated list of "
75 "passes may be given, in which case stacktraces will be collected "
76 "in those passes only"),
84 llvm::DebugLocOriginCollectionEnabled =
false;
87 if (EnableOriginStacktraces.
size() == 1 &&
88 EnableOriginStacktraces[0].
empty()) {
89 llvm::DebugLocOriginCollectionEnabled =
true;
92 llvm::DebugLocOriginCollectionEnabled =
95static void unsetDebugLocOriginCollection() {
96 llvm::DebugLocOriginCollectionEnabled =
false;
101static SymbolizedAddressMap SymbolizedAddrs;
102static AddressSet UnsymbolizedAddrs;
107 if (!UnsymbolizedAddrs.empty()) {
108 sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);
109 UnsymbolizedAddrs.clear();
111 const DbgLocOrigin::StackTracesTy &OriginStackTraces =
112 I->getDebugLoc().getOriginStackTraces();
115 for (
size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {
117 OS <<
"========================================\n";
118 auto &[
Depth, StackTrace] = OriginStackTraces[TraceIdx];
119 unsigned VirtualFrameNo = 0;
120 for (
int Frame = 0; Frame <
Depth; ++Frame) {
121 assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&
122 "Expected each address to have been symbolized.");
123 for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {
125 std::log10(
Depth) + 2)
126 <<
' ' << SymbolizedFrame <<
'\n';
133 auto &OriginStackTraces =
I.getDebugLoc().getOriginStackTraces();
134 for (
auto &[
Depth, StackTrace] : OriginStackTraces) {
135 for (
int Frame = 0; Frame <
Depth; ++Frame) {
136 void *Addr = StackTrace[Frame];
137 if (!SymbolizedAddrs.contains(Addr))
138 UnsymbolizedAddrs.insert(Addr);
146static void unsetDebugLocOriginCollection() {}
149 "enable-origin-stacktraces",
150 cl::desc(
"Collect DebugLoc origin stacktraces; requires "
151 "LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING=COVERAGE_AND_ORIGIN"),
155 "without LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING="
156 "COVERAGE_AND_ORIGIN\n";
163 return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
167 return F.isDeclaration() || !
F.hasExactDefinition();
187 if (M.getNamedMetadata(
"llvm.dbg.cu")) {
188 dbg() << Banner <<
"Skipping module with debug info\n";
198 auto getCachedDIType = [&](
Type *Ty) ->
DIType * {
208 unsigned NextLine = 1;
209 unsigned NextVar = 1;
212 "debugify",
true,
"", 0);
216 if (isFunctionSkipped(
F))
219 bool InsertedDbgVal =
false;
222 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;
223 if (
F.hasPrivateLinkage() ||
F.hasInternalLinkage())
224 SPFlags |= DISubprogram::SPFlagLocalToUnit;
226 SPType, NextLine, DINode::FlagZero, SPFlags,
227 nullptr,
nullptr,
nullptr,
nullptr,
"",
236 Value *V = &TemplateInst;
238 V = ConstantInt::get(Int32Ty, 0);
241 getCachedDIType(V->getType()),
250 uint64_t AtomGroup = ApplyAtomGroups ? NextLine : 0;
251 uint8_t AtomRank = ApplyAtomGroups ? 1 : 0;
254 AtomGroup, AtomRank));
257 if (DebugifyLevel < Level::LocationsAndVariables)
266 Instruction *LastInst = findTerminatingInstruction(BB);
267 assert(LastInst &&
"Expected basic block with a terminator");
272 assert(InsertPt != BB.end() &&
"Expected to find an insertion point");
275 InsertPt.setHeadBit(
false);
278 for (
Instruction *
I = &*BB.begin();
I != LastInst;
I =
I->getNextNode()) {
280 if (
I->getType()->isVoidTy())
286 InsertPt = std::next(
I->getIterator());
288 insertDbgVal(*
I, InsertPt);
289 InsertedDbgVal =
true;
297 if (DebugifyLevel == Level::LocationsAndVariables && !InsertedDbgVal) {
298 auto *
Term = findTerminatingInstruction(
F.getEntryBlock());
299 insertDbgVal(*Term,
Term->getIterator());
307 NamedMDNode *NMD = M.getOrInsertNamedMetadata(
"llvm.debugify");
308 auto addDebugifyOperand = [&](
unsigned N) {
312 addDebugifyOperand(NextLine - 1);
313 addDebugifyOperand(NextVar - 1);
315 "llvm.debugify should have exactly 2 operands!");
318 StringRef DIVersionKey =
"Debug Info Version";
319 if (!M.getModuleFlag(DIVersionKey))
328 setDebugLocOriginCollectionForPass(NameOfWrappedPass);
330 auto FuncIt =
F.getIterator();
333 "FunctionDebugify: ",
nullptr);
334 assert(DebugInfoBeforePass &&
"Missing debug info metadata");
336 "FunctionDebugify (original debuginfo)",
343 setDebugLocOriginCollectionForPass(NameOfWrappedPass);
346 "ModuleDebugify: ",
nullptr);
347 assert(DebugInfoBeforePass &&
"Missing debug info metadata");
349 "ModuleDebugify (original debuginfo)",
357 NamedMDNode *DebugifyMD = M.getNamedMetadata(
"llvm.debugify");
359 M.eraseNamedMetadata(DebugifyMD);
363 if (
auto *MIRDebugifyMD = M.getNamedMetadata(
"llvm.mir.debugify")) {
364 M.eraseNamedMetadata(MIRDebugifyMD);
376 "Not all debug info stripped?");
388 for (
MDNode *Flag : Flags) {
390 if (
Key->getString() ==
"Debug Info Version") {
405#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
406 DebugLocKind Kind =
I.getDebugLoc().getKind();
407 return Loc || Kind != DebugLocKind::Normal;
418 LLVM_DEBUG(
dbgs() << Banner <<
": (before) " << NameOfWrappedPass <<
'\n');
420 if (!M.getNamedMetadata(
"llvm.dbg.cu")) {
421 dbg() << Banner <<
": Skipping module without debug info\n";
432 if (isFunctionSkipped(
F))
436 if (++FunctionsCnt >= DebugifyFunctionsLimit)
439 auto *SP =
F.getSubprogram();
443 for (
const DINode *DN : SP->getRetainedNodes()) {
458 if (DebugifyLevel > Level::Locations) {
463 if (DbgVar->getDebugLoc().getInlinedAt())
466 if (DbgVar->isKillLocation())
469 auto *Var = DbgVar->getVariable();
473 HandleDbgVariable(&DVR);
480 collectStackAddresses(
I);
493 StringRef FileNameFromCU,
bool ShouldWriteIntoJSON,
495 bool Preserved =
true;
496 for (
const auto &
F : DIFunctionsAfter) {
499 auto SPIt = DIFunctionsBefore.
find(
F.first);
500 if (SPIt == DIFunctionsBefore.
end()) {
501 if (ShouldWriteIntoJSON)
503 {
"name",
F.first->getName()},
504 {
"action",
"not-generate"}}));
506 dbg() <<
"ERROR: " << NameOfWrappedPass
507 <<
" did not generate DISubprogram for " <<
F.first->getName()
508 <<
" from " << FileNameFromCU <<
'\n';
511 auto SP = SPIt->second;
516 if (ShouldWriteIntoJSON)
518 {
"name",
F.first->getName()},
519 {
"action",
"drop"}}));
521 dbg() <<
"ERROR: " << NameOfWrappedPass <<
" dropped DISubprogram of "
522 <<
F.first->getName() <<
" from " << FileNameFromCU <<
'\n';
537 bool ShouldWriteIntoJSON,
539 bool Preserved =
true;
540 for (
const auto &L : DILocsAfter) {
543 auto Instr = L.first;
547 auto WeakInstrPtr = InstToDelete.
find(Instr);
548 if (WeakInstrPtr != InstToDelete.
end() && !WeakInstrPtr->second)
551 auto FnName = Instr->getFunction()->getName();
552 auto BB = Instr->getParent();
553 auto BBName = BB->hasName() ? BB->getName() :
"no-name";
556 auto CreateJSONBugEntry = [&](
const char *Action) {
558 {
"metadata",
"DILocation"},
559 {
"fn-name", FnName.str()},
560 {
"bb-name", BBName.str()},
564#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
565 if (!Instr->getDebugLoc().getOriginStackTraces().empty())
566 BugEntry.
insert({
"origin", symbolizeStackTrace(Instr)});
571 auto InstrIt = DILocsBefore.
find(Instr);
572 if (InstrIt == DILocsBefore.
end()) {
573 if (ShouldWriteIntoJSON)
574 CreateJSONBugEntry(
"not-generate");
576 dbg() <<
"WARNING: " << NameOfWrappedPass
577 <<
" did not generate DILocation for " << *Instr
578 <<
" (BB: " << BBName <<
", Fn: " << FnName
579 <<
", File: " << FileNameFromCU <<
")\n";
582 if (!InstrIt->second)
586 if (ShouldWriteIntoJSON)
587 CreateJSONBugEntry(
"drop");
589 dbg() <<
"WARNING: " << NameOfWrappedPass <<
" dropped DILocation of "
590 << *Instr <<
" (BB: " << BBName <<
", Fn: " << FnName
591 <<
", File: " << FileNameFromCU <<
")\n";
604 bool Preserved =
true;
605 for (
const auto &V : DIVarsBefore) {
606 auto VarIt = DIVarsAfter.
find(V.first);
607 if (VarIt == DIVarsAfter.
end())
610 unsigned NumOfDbgValsAfter = VarIt->second;
612 if (V.second > NumOfDbgValsAfter) {
613 if (ShouldWriteIntoJSON)
615 {{
"metadata",
"dbg-var-intrinsic"},
616 {
"name", V.first->getName()},
617 {
"fn-name", V.first->getScope()->getSubprogram()->getName()},
618 {
"action",
"drop"}}));
620 dbg() <<
"WARNING: " << NameOfWrappedPass
621 <<
" drops dbg.value()/dbg.declare() for " << V.first->getName()
623 <<
"function " << V.first->getScope()->getSubprogram()->getName()
624 <<
" (file " << FileNameFromCU <<
")\n";
640 errs() <<
"Could not open file: " << EC.message() <<
", "
641 << OrigDIVerifyBugsReportFilePath <<
'\n';
645 if (
auto L = OS_FILE.
lock()) {
646 OS_FILE <<
"{\"file\":\"" << FileNameFromCU <<
"\", ";
649 NameOfWrappedPass !=
"" ? NameOfWrappedPass :
"no-name";
650 OS_FILE <<
"\"pass\":\"" <<
PassName <<
"\", ";
653 OS_FILE <<
"\"bugs\": " << BugsToPrint;
664 StringRef OrigDIVerifyBugsReportFilePath) {
665 LLVM_DEBUG(
dbgs() << Banner <<
": (after) " << NameOfWrappedPass <<
'\n');
666 unsetDebugLocOriginCollection();
668 if (!M.getNamedMetadata(
"llvm.dbg.cu")) {
669 dbg() << Banner <<
": Skipping module without debug info\n";
678 if (isFunctionSkipped(
F))
686 auto *SP =
F.getSubprogram();
691 for (
const DINode *DN : SP->getRetainedNodes()) {
706 if (DebugifyLevel > Level::Locations) {
711 if (DbgVar->getDebugLoc().getInlinedAt())
714 if (DbgVar->isKillLocation())
717 auto *Var = DbgVar->getVariable();
721 HandleDbgVariable(&DVR);
727 collectStackAddresses(
I);
738 auto DIFunctionsBefore = DebugInfoBeforePass.
DIFunctions;
739 auto DIFunctionsAfter = DebugInfoAfterPass.
DIFunctions;
741 auto DILocsBefore = DebugInfoBeforePass.
DILocations;
746 auto DIVarsBefore = DebugInfoBeforePass.
DIVariables;
749 bool ShouldWriteIntoJSON = !OrigDIVerifyBugsReportFilePath.
empty();
753 checkFunctions(DIFunctionsBefore, DIFunctionsAfter, NameOfWrappedPass,
754 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
756 DILocsBefore, DILocsAfter, InstToDelete, NameOfWrappedPass,
757 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
759#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
763 for (
auto &L : DILocsAfter)
768 bool ResultForVars =
checkVars(DIVarsBefore, DIVarsAfter, NameOfWrappedPass,
769 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
771 bool Result = ResultForFunc && ResultForInsts && ResultForVars;
773 StringRef ResultBanner = NameOfWrappedPass !=
"" ? NameOfWrappedPass : Banner;
774 if (ShouldWriteIntoJSON && !Bugs.
empty())
775 writeJSON(OrigDIVerifyBugsReportFilePath, FileNameFromCU, NameOfWrappedPass,
779 dbg() << ResultBanner <<
": PASS\n";
781 dbg() << ResultBanner <<
": FAIL\n";
786 DebugInfoBeforePass = DebugInfoAfterPass;
794template <
typename DbgValTy>
795bool diagnoseMisSizedDbgValue(
Module &M, DbgValTy *DbgVal) {
804 if (DbgVal->getExpression()->getNumElements())
807 Value *V = DbgVal->getVariableLocationOp(0);
811 Type *Ty = V->getType();
812 uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
813 std::optional<uint64_t> DbgVarSize = DbgVal->getFragmentSizeInBits();
814 if (!ValueOperandSize || !DbgVarSize)
817 bool HasBadSize =
false;
818 if (Ty->isIntegerTy()) {
819 auto Signedness = DbgVal->getVariable()->getSignedness();
821 HasBadSize = ValueOperandSize < *DbgVarSize;
823 HasBadSize = ValueOperandSize != *DbgVarSize;
827 dbg() <<
"ERROR: dbg.value operand has size " << ValueOperandSize
828 <<
", but its variable has size " << *DbgVarSize <<
": ";
829 DbgVal->print(dbg());
835bool checkDebugifyMetadata(
Module &M,
840 NamedMDNode *NMD = M.getNamedMetadata(
"llvm.debugify");
841 unsetDebugLocOriginCollection();
843 dbg() << Banner <<
": Skipping module without debugify metadata\n";
847 auto getDebugifyOperand = [&](
unsigned Idx) ->
unsigned {
852 "llvm.debugify should have exactly 2 operands!");
853 unsigned OriginalNumLines = getDebugifyOperand(0);
854 unsigned OriginalNumVars = getDebugifyOperand(1);
855 bool HasErrors =
false;
859 if (StatsMap && !NameOfWrappedPass.
empty())
860 Stats = &StatsMap->operator[](NameOfWrappedPass);
862 BitVector MissingLines{OriginalNumLines,
true};
863 BitVector MissingVars{OriginalNumVars,
true};
865 if (isFunctionSkipped(
F))
870 auto DL =
I.getDebugLoc();
871 if (
DL &&
DL.getLine() != 0) {
872 MissingLines.
reset(
DL.getLine() - 1);
877 dbg() <<
"WARNING: Instruction with empty DebugLoc in function ";
878 dbg() <<
F.getName() <<
" --";
885 auto CheckForMisSized = [&](
auto *DbgVal) {
887 (void)
to_integer(DbgVal->getVariable()->getName(), Var, 10);
888 assert(Var <= OriginalNumVars &&
"Unexpected name for DILocalVariable");
889 bool HasBadSize = diagnoseMisSizedDbgValue(M, DbgVal);
891 MissingVars.
reset(Var - 1);
892 HasErrors |= HasBadSize;
896 if (DVR.isDbgValue() || DVR.isDbgAssign())
897 CheckForMisSized(&DVR);
902 for (
unsigned Idx : MissingLines.
set_bits())
903 dbg() <<
"WARNING: Missing line " << Idx + 1 <<
"\n";
905 for (
unsigned Idx : MissingVars.
set_bits())
906 dbg() <<
"WARNING: Missing variable " << Idx + 1 <<
"\n";
910 Stats->NumDbgLocsExpected += OriginalNumLines;
911 Stats->NumDbgLocsMissing += MissingLines.
count();
912 Stats->NumDbgValuesExpected += OriginalNumVars;
913 Stats->NumDbgValuesMissing += MissingVars.
count();
917 if (!NameOfWrappedPass.
empty())
918 dbg() <<
" [" << NameOfWrappedPass <<
"]";
919 dbg() <<
": " << (HasErrors ?
"FAIL" :
"PASS") <<
'\n';
931struct DebugifyModulePass :
public ModulePass {
932 bool runOnModule(
Module &M)
override {
934 applyDebugify(M, Mode, DebugInfoBeforePass, NameOfWrappedPass);
939 StringRef NameOfWrappedPass =
"",
940 DebugInfoPerPass *DebugInfoBeforePass =
nullptr)
941 : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),
942 DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}
944 void getAnalysisUsage(AnalysisUsage &AU)
const override {
951 StringRef NameOfWrappedPass;
952 DebugInfoPerPass *DebugInfoBeforePass;
965 DebugifyFunctionPass(
967 StringRef NameOfWrappedPass =
"",
968 DebugInfoPerPass *DebugInfoBeforePass =
nullptr)
969 : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),
970 DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}
972 void getAnalysisUsage(AnalysisUsage &AU)
const override {
979 StringRef NameOfWrappedPass;
980 DebugInfoPerPass *DebugInfoBeforePass;
986struct CheckDebugifyModulePass :
public ModulePass {
987 bool runOnModule(
Module &M)
override {
990 Result = checkDebugifyMetadata(M,
M.functions(), NameOfWrappedPass,
991 "CheckModuleDebugify", Strip, StatsMap);
994 M,
M.functions(), *DebugInfoBeforePass,
995 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,
996 OrigDIVerifyBugsReportFilePath);
1001 CheckDebugifyModulePass(
1002 bool Strip =
false, StringRef NameOfWrappedPass =
"",
1005 DebugInfoPerPass *DebugInfoBeforePass =
nullptr,
1006 StringRef OrigDIVerifyBugsReportFilePath =
"")
1007 : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),
1008 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
1009 StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),
1012 void getAnalysisUsage(AnalysisUsage &AU)
const override {
1019 StringRef NameOfWrappedPass;
1020 StringRef OrigDIVerifyBugsReportFilePath;
1022 DebugInfoPerPass *DebugInfoBeforePass;
1029struct CheckDebugifyFunctionPass :
public FunctionPass {
1032 auto FuncIt =
F.getIterator();
1036 NameOfWrappedPass,
"CheckFunctionDebugify",
1040 M,
make_range(FuncIt, std::next(FuncIt)), *DebugInfoBeforePass,
1041 "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass,
1042 OrigDIVerifyBugsReportFilePath);
1047 CheckDebugifyFunctionPass(
1048 bool Strip =
false, StringRef NameOfWrappedPass =
"",
1051 DebugInfoPerPass *DebugInfoBeforePass =
nullptr,
1052 StringRef OrigDIVerifyBugsReportFilePath =
"")
1053 : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),
1054 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
1055 StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),
1058 void getAnalysisUsage(AnalysisUsage &AU)
const override {
1065 StringRef NameOfWrappedPass;
1066 StringRef OrigDIVerifyBugsReportFilePath;
1068 DebugInfoPerPass *DebugInfoBeforePass;
1079 errs() <<
"Could not open file: " << EC.message() <<
", " << Path <<
'\n';
1083 OS <<
"Pass Name" <<
',' <<
"# of missing debug values" <<
','
1084 <<
"# of missing locations" <<
',' <<
"Missing/Expected value ratio" <<
','
1085 <<
"Missing/Expected location ratio" <<
'\n';
1086 for (
const auto &Entry : Map) {
1090 OS <<
Pass <<
',' <<
Stats.NumDbgValuesMissing <<
','
1091 <<
Stats.NumDbgLocsMissing <<
',' <<
Stats.getMissingValueRatio() <<
','
1092 <<
Stats.getEmptyLocationRatio() <<
'\n';
1100 return new DebugifyModulePass();
1102 return new DebugifyModulePass(
Mode, NameOfWrappedPass, DebugInfoBeforePass);
1110 return new DebugifyFunctionPass();
1112 return new DebugifyFunctionPass(
Mode, NameOfWrappedPass, DebugInfoBeforePass);
1119 return ApplyToMF(DIB,
F, AM);
1122 "ModuleDebugify: ", ApplyToMFWrapper);
1128 "ModuleDebugify (original debuginfo)",
1142 StringRef OrigDIVerifyBugsReportFilePath) {
1144 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
1146 return new CheckDebugifyModulePass(
false, NameOfWrappedPass,
nullptr,
Mode,
1147 DebugInfoBeforePass,
1148 OrigDIVerifyBugsReportFilePath);
1154 StringRef OrigDIVerifyBugsReportFilePath) {
1156 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
1158 return new CheckDebugifyFunctionPass(
false, NameOfWrappedPass,
nullptr,
Mode,
1159 DebugInfoBeforePass,
1160 OrigDIVerifyBugsReportFilePath);
1166 checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
1167 "CheckModuleDebugify", Strip, StatsMap);
1170 M, M.functions(), *DebugInfoBeforePass,
1171 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,
1172 OrigDIVerifyBugsReportFilePath);
1179 "AnalysisManagerProxy",
"PrintFunctionPass",
1180 "PrintModulePass",
"BitcodeWriterPass",
1181 "ThinLTOBitcodeWriterPass",
"VerifierPass"});
1200 MAM.invalidate(M, PA);
1203 PIC.registerAfterPassCallback(
1212 auto It =
F.getIterator();
1214 checkDebugifyMetadata(M,
make_range(It, std::next(It)),
P,
1215 "CheckFunctionDebugify",
true,
1219 *DebugInfoBeforePass,
1220 "CheckModuleDebugify (original debuginfo)",
1221 P, OrigDIVerifyBugsReportFilePath);
1228 checkDebugifyMetadata(M, M.functions(),
P,
"CheckModuleDebugify",
1232 "CheckModuleDebugify (original debuginfo)",
1233 P, OrigDIVerifyBugsReportFilePath);
1234 MAM.invalidate(M, PA);
1239char DebugifyModulePass::ID = 0;
1241 "Attach debug info to everything");
1243char CheckDebugifyModulePass::ID = 0;
1245 CDM(
"check-debugify",
"Check debug info from -debugify");
1247char DebugifyFunctionPass::ID = 0;
1249 "Attach debug info to a function");
1251char CheckDebugifyFunctionPass::ID = 0;
1253 CDF(
"check-debugify-function",
"Check debug info from -debugify-function");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
This file implements the BitVector class.
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static RegisterPass< CheckDebugifyModulePass > CDM("check-debugify", "Check debug info from -debugify")
ModulePass * createDebugifyModulePass(enum DebugifyMode Mode, llvm::StringRef NameOfWrappedPass, DebugInfoPerPass *DebugInfoBeforePass)
bool hasLoc(const Instruction &I)
FunctionPass * createDebugifyFunctionPass(enum DebugifyMode Mode, llvm::StringRef NameOfWrappedPass, DebugInfoPerPass *DebugInfoBeforePass)
static bool isIgnoredPass(StringRef PassID)
static bool applyDebugify(Function &F, enum DebugifyMode Mode, DebugInfoPerPass *DebugInfoBeforePass, StringRef NameOfWrappedPass="")
ModulePass * createCheckDebugifyModulePass(bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap, enum DebugifyMode Mode, DebugInfoPerPass *DebugInfoBeforePass, StringRef OrigDIVerifyBugsReportFilePath)
static void writeJSON(StringRef OrigDIVerifyBugsReportFilePath, StringRef FileNameFromCU, StringRef NameOfWrappedPass, llvm::json::Array &Bugs)
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
static bool checkFunctions(const DebugFnMap &DIFunctionsBefore, const DebugFnMap &DIFunctionsAfter, StringRef NameOfWrappedPass, StringRef FileNameFromCU, bool ShouldWriteIntoJSON, llvm::json::Array &Bugs)
static RegisterPass< CheckDebugifyFunctionPass > CDF("check-debugify-function", "Check debug info from -debugify-function")
FunctionPass * createCheckDebugifyFunctionPass(bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap, enum DebugifyMode Mode, DebugInfoPerPass *DebugInfoBeforePass, StringRef OrigDIVerifyBugsReportFilePath)
static bool checkVars(const DebugVarMap &DIVarsBefore, const DebugVarMap &DIVarsAfter, StringRef NameOfWrappedPass, StringRef FileNameFromCU, bool ShouldWriteIntoJSON, llvm::json::Array &Bugs)
static bool checkInstructions(const DebugInstMap &DILocsBefore, const DebugInstMap &DILocsAfter, const WeakInstValueMap &InstToDelete, StringRef NameOfWrappedPass, StringRef FileNameFromCU, bool ShouldWriteIntoJSON, llvm::json::Array &Bugs)
DebugifyMode
Used to check whether we track synthetic or original debug info.
llvm::MapVector< const llvm::Function *, const llvm::DISubprogram * > DebugFnMap
llvm::MapVector< llvm::StringRef, DebugifyStatistics > DebugifyStatsMap
Map pass names to a per-pass DebugifyStatistics instance.
llvm::MapVector< const llvm::Instruction *, bool > DebugInstMap
llvm::MapVector< const llvm::Instruction *, llvm::WeakVH > WeakInstValueMap
llvm::MapVector< const llvm::DILocalVariable *, unsigned > DebugVarMap
static bool runOnFunction(Function &F, bool PostInlining)
static SmallString< 128 > getFilename(const DIScope *SP, vfs::FileSystem &VFS)
Extract a filename for a DIScope.
Module.h This file contains the declarations for the Module class.
This file supports working with JSON data.
Legalize the Machine IR a function s Machine IR
block placement Basic Block Placement Stats
Machine Check Debug Module
ModuleAnalysisManager MAM
PassInstrumentationCallbacks PIC
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static const char PassName[]
LLVM_ABI llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM)
LLVM_ABI llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM)
void setPreservesAll()
Set by analyses that do not transform their input at all.
LLVM Basic Block Representation.
LLVM_ABI const CallInst * getTerminatingDeoptimizeCall() const
Returns the call instruction calling @llvm.experimental.deoptimize prior to the terminating return in...
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI const CallInst * getTerminatingMustTailCall() const
Returns the call instruction marked 'musttail' prior to the terminating return instruction of this ba...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BitVector & reset()
Reset all bits in the bitvector.
size_type count() const
Returns the number of bits which are set.
iterator_range< const_set_bits_iterator > set_bits() const
Represents analyses that only rely on functions' control flow.
LLVM_ABI void finalize()
Construct any deferred debug info descriptors.
LLVM_ABI DISubroutineType * createSubroutineType(DITypeArray ParameterTypes, DINode::DIFlags Flags=DINode::FlagZero, unsigned CC=0)
Create subroutine type.
LLVM_ABI DISubprogram * createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags=DINode::FlagZero, DISubprogram::DISPFlags SPFlags=DISubprogram::SPFlagZero, DITemplateParameterArray TParams=nullptr, DISubprogram *Decl=nullptr, DITypeArray ThrownTypes=nullptr, DINodeArray Annotations=nullptr, StringRef TargetFuncName="", bool UseKeyInstructions=false)
Create a new descriptor for the specified subprogram.
LLVM_ABI DbgInstPtr insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, InsertPosition InsertPt)
Insert a new llvm.dbg.value intrinsic call.
LLVM_ABI DITypeArray getOrCreateTypeArray(ArrayRef< Metadata * > Elements)
Get a DITypeArray, create one if required.
LLVM_ABI DIBasicType * createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, DINode::DIFlags Flags=DINode::FlagZero, uint32_t NumExtraInhabitants=0, uint32_t DataSizeInBits=0)
Create debugging information entry for a basic type.
LLVM_ABI DICompileUnit * createCompileUnit(DISourceLanguageName Lang, DIFile *File, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName=StringRef(), DICompileUnit::DebugEmissionKind Kind=DICompileUnit::DebugEmissionKind::FullDebug, uint64_t DWOId=0, bool SplitDebugInlining=true, bool DebugInfoForProfiling=false, DICompileUnit::DebugNameTableKind NameTableKind=DICompileUnit::DebugNameTableKind::Default, bool RangesBaseAddress=false, StringRef SysRoot={}, StringRef SDK={})
A CompileUnit provides an anchor for all debugging information generated during this instance of comp...
LLVM_ABI DIExpression * createExpression(ArrayRef< uint64_t > Addr={})
Create a new descriptor for the specified variable which has a complex address expression for its add...
LLVM_ABI DILocalVariable * createAutoVariable(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, DIType *Ty, bool AlwaysPreserve=false, DINode::DIFlags Flags=DINode::FlagZero, uint32_t AlignInBits=0)
Create a new descriptor for an auto variable.
LLVM_ABI DIFile * createFile(StringRef Filename, StringRef Directory, std::optional< DIFile::ChecksumInfo< StringRef > > Checksum=std::nullopt, std::optional< StringRef > Source=std::nullopt)
Create a file descriptor to hold debugging information for a file.
Tagged DWARF-like metadata node.
Wrapper structure that holds source language identity metadata that includes language name,...
DISPFlags
Debug info subprogram flags.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
DILocation * get() const
Get the underlying DILocation.
static DebugLoc getUnknown()
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)
FunctionPass class - This class is used to implement most global optimizations.
const Function & getFunction() const
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const char * getOpcodeName() const
This is an important class for using LLVM in a threaded context.
const MDOperand & getOperand(unsigned I) const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
iterator find(const KeyT &Key)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
size_type count(const KeyT &Key) const
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
@ Warning
Emits a warning if two values disagree.
LLVM_ABI void eraseFromParent()
Drop all references and remove the node from parent module.
LLVM_ABI MDNode * getOperand(unsigned i) const
LLVM_ABI unsigned getNumOperands() const
LLVM_ABI void clearOperands()
Drop all references to this node's operands.
iterator_range< op_iterator > operands()
LLVM_ABI void addOperand(MDNode *M)
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
int getNumOccurrences() const
A range adaptor for a pair of iterators.
An Array is a JSON array, which contains heterogeneous JSON values.
void push_back(const Value &E)
An Object is a JSON object, which maps strings to heterogenous JSON values.
std::pair< iterator, bool > insert(KV E)
A Value is an JSON value of unknown type.
A raw_ostream that writes to a file descriptor.
void close()
Manually flush the stream and close the file.
Expected< sys::fs::FileLocker > lock()
Locks the underlying file.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
@ OF_Append
The file should be opened in append mode.
This is an optimization pass for GlobalISel generic memory operations.
T any_cast(const Any &Value)
FormattedString right_justify(StringRef Str, unsigned Width)
right_justify - add spaces before string so total output is Width characters.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
std::string utostr(uint64_t X, bool isNeg=false)
LLVM_ABI bool stripDebugifyMetadata(Module &M)
Strip out all of the metadata and debug info inserted by debugify.
LLVM_ABI void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map)
LLVM_ABI bool applyDebugifyMetadata(Module &M, iterator_range< Module::iterator > Functions, StringRef Banner, std::function< bool(DIBuilder &, Function &)> ApplyToMF)
Add synthesized debug information to a module.
LLVM_ABI bool collectDebugInfoMetadata(Module &M, iterator_range< Module::iterator > Functions, DebugInfoPerPass &DebugInfoBeforePass, StringRef Banner, StringRef NameOfWrappedPass)
Collect original debug information before a pass.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI bool checkDebugInfoMetadata(Module &M, iterator_range< Module::iterator > Functions, DebugInfoPerPass &DebugInfoBeforePass, StringRef Banner, StringRef NameOfWrappedPass, StringRef OrigDIVerifyBugsReportFilePath)
Check original debug information after a pass.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
LLVM_ABI raw_ostream & nulls()
This returns a reference to a raw_ostream which simply discards output.
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_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI bool StripDebugInfo(Module &M)
Strip debug info in the module if it exists.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
bool to_integer(StringRef S, N &Num, unsigned Base=0)
Convert the string S to an integer of the specified type using the radix Base. If Base is 0,...
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Used to track the Debug Info Metadata information.
WeakInstValueMap InstToDelete
Track how much debugify information (in the synthetic mode only) has been lost.
RegisterPass<t> template - This template class is used to notify the system that a Pass is available ...