32#define DEBUG_TYPE "debugify"
39 cl::desc(
"Suppress verbose debugify output"));
42 "debugify-func-limit",
43 cl::desc(
"Set max number of processed functions per pass."),
52 "debugify-level",
cl::desc(
"Kind of debug info to add"),
54 clEnumValN(Level::LocationsAndVariables,
"location+variables",
55 "Locations and Variables")),
56 cl::init(Level::LocationsAndVariables));
61 return Ty->
isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
65 return F.isDeclaration() || !
F.hasExactDefinition();
85 if (
M.getNamedMetadata(
"llvm.dbg.cu")) {
86 dbg() << Banner <<
"Skipping module with debug info\n";
96 auto getCachedDIType = [&](
Type *Ty) ->
DIType * {
100 std::string
Name =
"ty" + utostr(
Size);
106 unsigned NextLine = 1;
107 unsigned NextVar = 1;
114 if (isFunctionSkipped(
F))
117 bool InsertedDbgVal =
false;
121 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;
122 if (
F.hasPrivateLinkage() ||
F.hasInternalLinkage())
123 SPFlags |= DISubprogram::SPFlagLocalToUnit;
125 SPType, NextLine, DINode::FlagZero, SPFlags);
132 std::string
Name = utostr(NextVar++);
135 V = ConstantInt::get(Int32Ty, 0);
138 getCachedDIType(
V->getType()),
147 I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
149 if (DebugifyLevel < Level::LocationsAndVariables)
158 Instruction *LastInst = findTerminatingInstruction(BB);
159 assert(LastInst &&
"Expected basic block with a terminator");
164 assert(InsertPt != BB.end() &&
"Expected to find an insertion point");
168 for (
Instruction *
I = &*BB.begin();
I != LastInst;
I =
I->getNextNode()) {
170 if (
I->getType()->isVoidTy())
175 if (!isa<PHINode>(
I) && !
I->isEHPad())
176 InsertBefore =
I->getNextNode();
178 insertDbgVal(*
I, InsertBefore);
179 InsertedDbgVal =
true;
187 if (DebugifyLevel == Level::LocationsAndVariables && !InsertedDbgVal) {
188 auto *
Term = findTerminatingInstruction(
F.getEntryBlock());
189 insertDbgVal(*Term, Term);
198 NamedMDNode *NMD =
M.getOrInsertNamedMetadata(
"llvm.debugify");
199 auto addDebugifyOperand = [&](
unsigned N) {
203 addDebugifyOperand(NextLine - 1);
204 addDebugifyOperand(NextVar - 1);
206 "llvm.debugify should have exactly 2 operands!");
209 StringRef DIVersionKey =
"Debug Info Version";
210 if (!
M.getModuleFlag(DIVersionKey))
222 auto FuncIt =
F.getIterator();
225 "FunctionDebugify: ",
nullptr);
226 assert(DebugInfoBeforePass);
228 "FunctionDebugify (original debuginfo)",
239 "ModuleDebugify: ",
nullptr);
241 "ModuleDebugify (original debuginfo)",
246 bool Changed =
false;
249 NamedMDNode *DebugifyMD = M.getNamedMetadata(
"llvm.debugify");
251 M.eraseNamedMetadata(DebugifyMD);
255 if (
auto *MIRDebugifyMD = M.getNamedMetadata(
"llvm.mir.debugify")) {
256 M.eraseNamedMetadata(MIRDebugifyMD);
265 Function *DbgValF = M.getFunction(
"llvm.dbg.value");
268 "Not all debug info stripped?");
280 for (
MDNode *Flag : Flags) {
281 auto *Key = cast<MDString>(Flag->getOperand(1));
282 if (Key->getString() ==
"Debug Info Version") {
300 LLVM_DEBUG(
dbgs() << Banner <<
": (before) " << NameOfWrappedPass <<
'\n');
302 if (!M.getNamedMetadata(
"llvm.dbg.cu")) {
303 dbg() << Banner <<
": Skipping module without debug info\n";
314 if (isFunctionSkipped(
F))
318 if (++FunctionsCnt >= DebugifyFunctionsLimit)
321 auto *SP =
F.getSubprogram();
325 for (
const DINode *DN : SP->getRetainedNodes()) {
326 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
340 if (DebugifyLevel > Level::Locations) {
341 auto HandleDbgVariable = [&](
auto *DbgVar) {
345 if (DbgVar->getDebugLoc().getInlinedAt())
348 if (DbgVar->isKillLocation())
351 auto *Var = DbgVar->getVariable();
355 HandleDbgVariable(&DVR);
356 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
357 HandleDbgVariable(DVI);
361 if (isa<DbgInfoIntrinsic>(&
I))
368 bool HasLoc = Loc !=
nullptr;
381 StringRef FileNameFromCU,
bool ShouldWriteIntoJSON,
383 bool Preserved =
true;
384 for (
const auto &
F : DIFunctionsAfter) {
387 auto SPIt = DIFunctionsBefore.
find(
F.first);
388 if (SPIt == DIFunctionsBefore.
end()) {
389 if (ShouldWriteIntoJSON)
391 {
"name",
F.first->getName()},
392 {
"action",
"not-generate"}}));
394 dbg() <<
"ERROR: " << NameOfWrappedPass
395 <<
" did not generate DISubprogram for " <<
F.first->getName()
396 <<
" from " << FileNameFromCU <<
'\n';
399 auto SP = SPIt->second;
404 if (ShouldWriteIntoJSON)
406 {
"name",
F.first->getName()},
407 {
"action",
"drop"}}));
409 dbg() <<
"ERROR: " << NameOfWrappedPass <<
" dropped DISubprogram of "
410 <<
F.first->getName() <<
" from " << FileNameFromCU <<
'\n';
425 bool ShouldWriteIntoJSON,
427 bool Preserved =
true;
428 for (
const auto &L : DILocsAfter) {
431 auto Instr = L.first;
435 auto WeakInstrPtr = InstToDelete.
find(Instr);
436 if (WeakInstrPtr != InstToDelete.
end() && !WeakInstrPtr->second)
439 auto FnName = Instr->getFunction()->getName();
440 auto BB = Instr->getParent();
441 auto BBName = BB->hasName() ? BB->getName() :
"no-name";
444 auto InstrIt = DILocsBefore.
find(Instr);
445 if (InstrIt == DILocsBefore.
end()) {
446 if (ShouldWriteIntoJSON)
448 {
"fn-name", FnName.str()},
449 {
"bb-name", BBName.str()},
451 {
"action",
"not-generate"}}));
453 dbg() <<
"WARNING: " << NameOfWrappedPass
454 <<
" did not generate DILocation for " << *Instr
455 <<
" (BB: " << BBName <<
", Fn: " << FnName
456 <<
", File: " << FileNameFromCU <<
")\n";
459 if (!InstrIt->second)
463 if (ShouldWriteIntoJSON)
465 {
"fn-name", FnName.str()},
466 {
"bb-name", BBName.str()},
468 {
"action",
"drop"}}));
470 dbg() <<
"WARNING: " << NameOfWrappedPass <<
" dropped DILocation of "
471 << *Instr <<
" (BB: " << BBName <<
", Fn: " << FnName
472 <<
", File: " << FileNameFromCU <<
")\n";
485 bool Preserved =
true;
486 for (
const auto &V : DIVarsBefore) {
487 auto VarIt = DIVarsAfter.
find(V.first);
488 if (VarIt == DIVarsAfter.
end())
491 unsigned NumOfDbgValsAfter = VarIt->second;
493 if (V.second > NumOfDbgValsAfter) {
494 if (ShouldWriteIntoJSON)
496 {{
"metadata",
"dbg-var-intrinsic"},
497 {
"name", V.first->getName()},
499 {
"action",
"drop"}}));
501 dbg() <<
"WARNING: " << NameOfWrappedPass
502 <<
" drops dbg.value()/dbg.declare() for " << V.first->getName()
504 <<
"function " << V.first->getScope()->getSubprogram()->getName()
505 <<
" (file " << FileNameFromCU <<
")\n";
521 errs() <<
"Could not open file: " << EC.message() <<
", "
522 << OrigDIVerifyBugsReportFilePath <<
'\n';
526 if (
auto L = OS_FILE.lock()) {
527 OS_FILE <<
"{\"file\":\"" << FileNameFromCU <<
"\", ";
530 NameOfWrappedPass !=
"" ? NameOfWrappedPass :
"no-name";
531 OS_FILE <<
"\"pass\":\"" <<
PassName <<
"\", ";
534 OS_FILE <<
"\"bugs\": " << BugsToPrint;
545 StringRef OrigDIVerifyBugsReportFilePath) {
546 LLVM_DEBUG(
dbgs() << Banner <<
": (after) " << NameOfWrappedPass <<
'\n');
548 if (!M.getNamedMetadata(
"llvm.dbg.cu")) {
549 dbg() << Banner <<
": Skipping module without debug info\n";
558 if (isFunctionSkipped(
F))
566 auto *SP =
F.getSubprogram();
571 for (
const DINode *DN : SP->getRetainedNodes()) {
572 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
586 if (DebugifyLevel > Level::Locations) {
587 auto HandleDbgVariable = [&](
auto *DbgVar) {
591 if (DbgVar->getDebugLoc().getInlinedAt())
594 if (DbgVar->isKillLocation())
597 auto *Var = DbgVar->getVariable();
601 HandleDbgVariable(&DVR);
602 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
603 HandleDbgVariable(DVI);
607 if (isa<DbgInfoIntrinsic>(&
I))
613 bool HasLoc = Loc !=
nullptr;
622 (cast<DICompileUnit>(M.getNamedMetadata(
"llvm.dbg.cu")->getOperand(0)))
625 auto DIFunctionsBefore = DebugInfoBeforePass.
DIFunctions;
626 auto DIFunctionsAfter = DebugInfoAfterPass.
DIFunctions;
628 auto DILocsBefore = DebugInfoBeforePass.
DILocations;
633 auto DIVarsBefore = DebugInfoBeforePass.
DIVariables;
636 bool ShouldWriteIntoJSON = !OrigDIVerifyBugsReportFilePath.
empty();
640 checkFunctions(DIFunctionsBefore, DIFunctionsAfter, NameOfWrappedPass,
641 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
643 DILocsBefore, DILocsAfter, InstToDelete, NameOfWrappedPass,
644 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
646 bool ResultForVars =
checkVars(DIVarsBefore, DIVarsAfter, NameOfWrappedPass,
647 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
649 bool Result = ResultForFunc && ResultForInsts && ResultForVars;
651 StringRef ResultBanner = NameOfWrappedPass !=
"" ? NameOfWrappedPass : Banner;
652 if (ShouldWriteIntoJSON && !Bugs.
empty())
653 writeJSON(OrigDIVerifyBugsReportFilePath, FileNameFromCU, NameOfWrappedPass,
657 dbg() << ResultBanner <<
": PASS\n";
659 dbg() << ResultBanner <<
": FAIL\n";
664 DebugInfoBeforePass = DebugInfoAfterPass;
672template <
typename DbgValTy>
673bool diagnoseMisSizedDbgValue(
Module &M, DbgValTy *DbgVal) {
682 if (DbgVal->getExpression()->getNumElements())
685 Value *V = DbgVal->getVariableLocationOp(0);
689 Type *Ty = V->getType();
690 uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
691 std::optional<uint64_t> DbgVarSize = DbgVal->getFragmentSizeInBits();
692 if (!ValueOperandSize || !DbgVarSize)
695 bool HasBadSize =
false;
697 auto Signedness = DbgVal->getVariable()->getSignedness();
698 if (Signedness && *Signedness == DIBasicType::Signedness::Signed)
699 HasBadSize = ValueOperandSize < *DbgVarSize;
701 HasBadSize = ValueOperandSize != *DbgVarSize;
705 dbg() <<
"ERROR: dbg.value operand has size " << ValueOperandSize
706 <<
", but its variable has size " << *DbgVarSize <<
": ";
707 DbgVal->print(dbg());
713bool checkDebugifyMetadata(
Module &M,
720 dbg() << Banner <<
": Skipping module without debugify metadata\n";
724 auto getDebugifyOperand = [&](
unsigned Idx) ->
unsigned {
729 "llvm.debugify should have exactly 2 operands!");
730 unsigned OriginalNumLines = getDebugifyOperand(0);
731 unsigned OriginalNumVars = getDebugifyOperand(1);
732 bool HasErrors =
false;
736 if (StatsMap && !NameOfWrappedPass.
empty())
737 Stats = &StatsMap->operator[](NameOfWrappedPass);
739 BitVector MissingLines{OriginalNumLines,
true};
740 BitVector MissingVars{OriginalNumVars,
true};
742 if (isFunctionSkipped(
F))
747 if (isa<DbgValueInst>(&
I))
750 auto DL =
I.getDebugLoc();
751 if (
DL &&
DL.getLine() != 0) {
752 MissingLines.reset(
DL.getLine() - 1);
756 if (!isa<PHINode>(&
I) && !
DL) {
757 dbg() <<
"WARNING: Instruction with empty DebugLoc in function ";
758 dbg() <<
F.getName() <<
" --";
765 auto CheckForMisSized = [&](
auto *DbgVal) {
767 (void)to_integer(DbgVal->getVariable()->getName(), Var, 10);
768 assert(Var <= OriginalNumVars &&
"Unexpected name for DILocalVariable");
769 bool HasBadSize = diagnoseMisSizedDbgValue(M, DbgVal);
771 MissingVars.reset(Var - 1);
772 HasErrors |= HasBadSize;
776 if (DVR.isDbgValue() || DVR.isDbgAssign())
777 CheckForMisSized(&DVR);
778 auto *DVI = dyn_cast<DbgValueInst>(&
I);
781 CheckForMisSized(DVI);
786 for (
unsigned Idx : MissingLines.set_bits())
787 dbg() <<
"WARNING: Missing line " <<
Idx + 1 <<
"\n";
789 for (
unsigned Idx : MissingVars.set_bits())
790 dbg() <<
"WARNING: Missing variable " <<
Idx + 1 <<
"\n";
794 Stats->NumDbgLocsExpected += OriginalNumLines;
795 Stats->NumDbgLocsMissing += MissingLines.count();
796 Stats->NumDbgValuesExpected += OriginalNumVars;
797 Stats->NumDbgValuesMissing += MissingVars.count();
801 if (!NameOfWrappedPass.
empty())
802 dbg() <<
" [" << NameOfWrappedPass <<
"]";
803 dbg() <<
": " << (HasErrors ?
"FAIL" :
"PASS") <<
'\n';
815struct DebugifyModulePass :
public ModulePass {
818 applyDebugify(M, Mode, DebugInfoBeforePass, NameOfWrappedPass);
822 DebugifyModulePass(
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
826 DebugInfoBeforePass(DebugInfoBeforePass),
Mode(
Mode) {}
849 DebugifyFunctionPass(
850 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
854 DebugInfoBeforePass(DebugInfoBeforePass),
Mode(
Mode) {}
870struct CheckDebugifyModulePass :
public ModulePass {
873 if (Mode == DebugifyMode::SyntheticDebugInfo)
874 Result = checkDebugifyMetadata(M,
M.functions(), NameOfWrappedPass,
875 "CheckModuleDebugify", Strip, StatsMap);
878 M,
M.functions(), *DebugInfoBeforePass,
879 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,
880 OrigDIVerifyBugsReportFilePath);
885 CheckDebugifyModulePass(
886 bool Strip =
false,
StringRef NameOfWrappedPass =
"",
888 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
890 StringRef OrigDIVerifyBugsReportFilePath =
"")
892 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
893 StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass),
Mode(
Mode),
904 StringRef OrigDIVerifyBugsReportFilePath;
916 auto FuncIt =
F.getIterator();
918 if (Mode == DebugifyMode::SyntheticDebugInfo)
920 NameOfWrappedPass,
"CheckFunctionDebugify",
924 M,
make_range(FuncIt, std::next(FuncIt)), *DebugInfoBeforePass,
925 "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass,
926 OrigDIVerifyBugsReportFilePath);
931 CheckDebugifyFunctionPass(
932 bool Strip =
false,
StringRef NameOfWrappedPass =
"",
934 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
936 StringRef OrigDIVerifyBugsReportFilePath =
"")
938 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
939 StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass),
Mode(
Mode),
950 StringRef OrigDIVerifyBugsReportFilePath;
963 errs() <<
"Could not open file: " << EC.message() <<
", " << Path <<
'\n';
967 OS <<
"Pass Name" <<
',' <<
"# of missing debug values" <<
','
968 <<
"# of missing locations" <<
',' <<
"Missing/Expected value ratio" <<
','
969 <<
"Missing/Expected location ratio" <<
'\n';
970 for (
const auto &Entry : Map) {
974 OS <<
Pass <<
',' <<
Stats.NumDbgValuesMissing <<
','
975 <<
Stats.NumDbgLocsMissing <<
',' <<
Stats.getMissingValueRatio() <<
','
976 <<
Stats.getEmptyLocationRatio() <<
'\n';
984 return new DebugifyModulePass();
986 return new DebugifyModulePass(Mode, NameOfWrappedPass, DebugInfoBeforePass);
994 return new DebugifyFunctionPass();
996 return new DebugifyFunctionPass(Mode, NameOfWrappedPass, DebugInfoBeforePass);
1000 if (Mode == DebugifyMode::SyntheticDebugInfo)
1002 "ModuleDebugify: ",
nullptr);
1005 "ModuleDebugify (original debuginfo)",
1016 StringRef OrigDIVerifyBugsReportFilePath) {
1018 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
1020 return new CheckDebugifyModulePass(
false, NameOfWrappedPass,
nullptr, Mode,
1021 DebugInfoBeforePass,
1022 OrigDIVerifyBugsReportFilePath);
1028 StringRef OrigDIVerifyBugsReportFilePath) {
1030 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
1032 return new CheckDebugifyFunctionPass(
false, NameOfWrappedPass,
nullptr, Mode,
1033 DebugInfoBeforePass,
1034 OrigDIVerifyBugsReportFilePath);
1039 if (Mode == DebugifyMode::SyntheticDebugInfo)
1040 checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
1041 "CheckModuleDebugify", Strip, StatsMap);
1044 M, M.functions(), *DebugInfoBeforePass,
1045 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,
1046 OrigDIVerifyBugsReportFilePath);
1053 "AnalysisManagerProxy",
"PrintFunctionPass",
1054 "PrintModulePass",
"BitcodeWriterPass",
1055 "ThinLTOBitcodeWriterPass",
"VerifierPass"});
1065 if (
const auto **CF = llvm::any_cast<const Function *>(&
IR)) {
1071 }
else if (
const auto **CM = llvm::any_cast<const Module *>(&
IR)) {
1083 if (
const auto **CF = llvm::any_cast<const Function *>(&
IR)) {
1086 auto It =
F.getIterator();
1087 if (Mode == DebugifyMode::SyntheticDebugInfo)
1088 checkDebugifyMetadata(M,
make_range(It, std::next(It)),
P,
1089 "CheckFunctionDebugify",
true,
1093 *DebugInfoBeforePass,
1094 "CheckModuleDebugify (original debuginfo)",
1095 P, OrigDIVerifyBugsReportFilePath);
1099 }
else if (
const auto **CM = llvm::any_cast<const Module *>(&
IR)) {
1101 if (Mode == DebugifyMode::SyntheticDebugInfo)
1102 checkDebugifyMetadata(M, M.functions(),
P,
"CheckModuleDebugify",
1106 "CheckModuleDebugify (original debuginfo)",
1107 P, OrigDIVerifyBugsReportFilePath);
1113char DebugifyModulePass::ID = 0;
1115 "Attach debug info to everything");
1117char CheckDebugifyModulePass::ID = 0;
1119 CDM(
"check-debugify",
"Check debug info from -debugify");
1121char DebugifyFunctionPass::ID = 0;
1123 "Attach debug info to a function");
1125char CheckDebugifyFunctionPass::ID = 0;
1127 CDF(
"check-debugify-function",
"Check debug info from -debugify-function");
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
This file implements the BitVector class.
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static DISubprogram * getSubprogram(bool IsDistinct, Ts &&...Args)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static RegisterPass< CheckDebugifyModulePass > CDM("check-debugify", "Check debug info from -debugify")
ModulePass * createDebugifyModulePass(enum DebugifyMode Mode, llvm::StringRef NameOfWrappedPass, DebugInfoPerPass *DebugInfoBeforePass)
FunctionPass * createDebugifyFunctionPass(enum DebugifyMode Mode, llvm::StringRef NameOfWrappedPass, DebugInfoPerPass *DebugInfoBeforePass)
static bool isIgnoredPass(StringRef PassID)
static bool applyDebugify(Function &F, enum DebugifyMode Mode=DebugifyMode::SyntheticDebugInfo, DebugInfoPerPass *DebugInfoBeforePass=nullptr, 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.
static SmallString< 128 > getFilename(const DISubprogram *SP)
Extract a filename for a DISubprogram.
This file supports working with JSON data.
Legalize the Machine IR a function s Machine IR
block placement Basic Block Placement Stats
Module.h This file contains the declarations for the Module class.
ModuleAnalysisManager MAM
PassInstrumentationCallbacks PIC
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char PassName[]
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM)
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM)
A container for analyses that lazily runs them and caches their results.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
LLVM Basic Block Representation.
const CallInst * getTerminatingDeoptimizeCall() const
Returns the call instruction calling @llvm.experimental.deoptimize prior to the terminating return in...
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
const CallInst * getTerminatingMustTailCall() const
Returns the call instruction marked 'musttail' prior to the terminating return instruction of this ba...
Represents analyses that only rely on functions' control flow.
void finalize()
Construct any deferred debug info descriptors.
DISubroutineType * createSubroutineType(DITypeRefArray ParameterTypes, DINode::DIFlags Flags=DINode::FlagZero, unsigned CC=0)
Create subroutine type.
void finalizeSubprogram(DISubprogram *SP)
Finalize a specific subprogram - no new variables may be added to this subprogram afterwards.
DICompileUnit * createCompileUnit(unsigned 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...
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="")
Create a new descriptor for the specified subprogram.
DIExpression * createExpression(ArrayRef< uint64_t > Addr=std::nullopt)
Create a new descriptor for the specified variable which has a complex address expression for its add...
DIBasicType * createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, DINode::DIFlags Flags=DINode::FlagZero)
Create debugging information entry for a basic type.
DITypeRefArray getOrCreateTypeArray(ArrayRef< Metadata * > Elements)
Get a DITypeRefArray, create one if required.
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.
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.
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.
void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
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)
size_type count(const KeyT &Key) const
iterator find(const KeyT &Key)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
@ Warning
Emits a warning if two values disagree.
void eraseFromParent()
Drop all references and remove the node from parent module.
MDNode * getOperand(unsigned i) const
unsigned getNumOperands() const
void clearOperands()
Drop all references to this node's operands.
iterator_range< op_iterator > operands()
void addOperand(MDNode *M)
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
void registerBeforeNonSkippedPassCallback(CallableT C)
void registerAfterPassCallback(CallableT C, bool ToFront=false)
Pass interface - Implemented by all 'passes'.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
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.
void preserveSet()
Mark an analysis set as preserved.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
static IntegerType * getInt32Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
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.
A Value is an JSON value of unknown type.
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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)
@ 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.
bool applyDebugifyMetadata(Module &M, iterator_range< Module::iterator > Functions, StringRef Banner, std::function< bool(DIBuilder &, Function &)> ApplyToMF)
Add synthesized debug information to a module.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool stripDebugifyMetadata(Module &M)
Strip out all of the metadata and debug info inserted by debugify.
void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map)
bool collectDebugInfoMetadata(Module &M, iterator_range< Module::iterator > Functions, DebugInfoPerPass &DebugInfoBeforePass, StringRef Banner, StringRef NameOfWrappedPass)
Collect original debug information before a pass.
bool checkDebugInfoMetadata(Module &M, iterator_range< Module::iterator > Functions, DebugInfoPerPass &DebugInfoBeforePass, StringRef Banner, StringRef NameOfWrappedPass, StringRef OrigDIVerifyBugsReportFilePath)
Check original debug information after a pass.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
raw_ostream & nulls()
This returns a reference to a raw_ostream which simply discards output.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool StripDebugInfo(Module &M)
Strip debug info in the module if it exists.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
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 ...