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;
120 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;
121 if (
F.hasPrivateLinkage() ||
F.hasInternalLinkage())
122 SPFlags |= DISubprogram::SPFlagLocalToUnit;
124 SPType, NextLine, DINode::FlagZero, SPFlags);
131 std::string
Name = utostr(NextVar++);
134 V = ConstantInt::get(Int32Ty, 0);
137 getCachedDIType(
V->getType()),
146 I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
148 if (DebugifyLevel < Level::LocationsAndVariables)
157 Instruction *LastInst = findTerminatingInstruction(BB);
158 assert(LastInst &&
"Expected basic block with a terminator");
163 assert(InsertPt != BB.end() &&
"Expected to find an insertion point");
167 for (
Instruction *
I = &*BB.begin();
I != LastInst;
I =
I->getNextNode()) {
169 if (
I->getType()->isVoidTy())
174 if (!isa<PHINode>(
I) && !
I->isEHPad())
175 InsertBefore =
I->getNextNode();
177 insertDbgVal(*
I, InsertBefore);
178 InsertedDbgVal =
true;
186 if (DebugifyLevel == Level::LocationsAndVariables && !InsertedDbgVal) {
187 auto *
Term = findTerminatingInstruction(
F.getEntryBlock());
188 insertDbgVal(*Term, Term);
197 NamedMDNode *NMD =
M.getOrInsertNamedMetadata(
"llvm.debugify");
198 auto addDebugifyOperand = [&](
unsigned N) {
202 addDebugifyOperand(NextLine - 1);
203 addDebugifyOperand(NextVar - 1);
205 "llvm.debugify should have exactly 2 operands!");
208 StringRef DIVersionKey =
"Debug Info Version";
209 if (!
M.getModuleFlag(DIVersionKey))
221 auto FuncIt =
F.getIterator();
224 "FunctionDebugify: ",
nullptr);
225 assert(DebugInfoBeforePass);
227 "FunctionDebugify (original debuginfo)",
238 "ModuleDebugify: ",
nullptr);
240 "ModuleDebugify (original debuginfo)",
245 bool Changed =
false;
248 NamedMDNode *DebugifyMD = M.getNamedMetadata(
"llvm.debugify");
250 M.eraseNamedMetadata(DebugifyMD);
254 if (
auto *MIRDebugifyMD = M.getNamedMetadata(
"llvm.mir.debugify")) {
255 M.eraseNamedMetadata(MIRDebugifyMD);
264 Function *DbgValF = M.getFunction(
"llvm.dbg.value");
267 "Not all debug info stripped?");
279 for (
MDNode *Flag : Flags) {
280 auto *Key = cast<MDString>(Flag->getOperand(1));
281 if (Key->getString() ==
"Debug Info Version") {
299 LLVM_DEBUG(
dbgs() << Banner <<
": (before) " << NameOfWrappedPass <<
'\n');
301 if (!M.getNamedMetadata(
"llvm.dbg.cu")) {
302 dbg() << Banner <<
": Skipping module without debug info\n";
313 if (isFunctionSkipped(
F))
317 if (++FunctionsCnt >= DebugifyFunctionsLimit)
320 auto *SP =
F.getSubprogram();
324 for (
const DINode *DN : SP->getRetainedNodes()) {
325 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
339 if (DebugifyLevel > Level::Locations) {
340 auto HandleDbgVariable = [&](
auto *DbgVar) {
344 if (DbgVar->getDebugLoc().getInlinedAt())
347 if (DbgVar->isKillLocation())
350 auto *Var = DbgVar->getVariable();
354 HandleDbgVariable(&DVR);
355 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
356 HandleDbgVariable(DVI);
360 if (isa<DbgInfoIntrinsic>(&
I))
367 bool HasLoc = Loc !=
nullptr;
380 StringRef FileNameFromCU,
bool ShouldWriteIntoJSON,
382 bool Preserved =
true;
383 for (
const auto &
F : DIFunctionsAfter) {
386 auto SPIt = DIFunctionsBefore.
find(
F.first);
387 if (SPIt == DIFunctionsBefore.
end()) {
388 if (ShouldWriteIntoJSON)
390 {
"name",
F.first->getName()},
391 {
"action",
"not-generate"}}));
393 dbg() <<
"ERROR: " << NameOfWrappedPass
394 <<
" did not generate DISubprogram for " <<
F.first->getName()
395 <<
" from " << FileNameFromCU <<
'\n';
398 auto SP = SPIt->second;
403 if (ShouldWriteIntoJSON)
405 {
"name",
F.first->getName()},
406 {
"action",
"drop"}}));
408 dbg() <<
"ERROR: " << NameOfWrappedPass <<
" dropped DISubprogram of "
409 <<
F.first->getName() <<
" from " << FileNameFromCU <<
'\n';
424 bool ShouldWriteIntoJSON,
426 bool Preserved =
true;
427 for (
const auto &L : DILocsAfter) {
430 auto Instr = L.first;
434 auto WeakInstrPtr = InstToDelete.
find(Instr);
435 if (WeakInstrPtr != InstToDelete.
end() && !WeakInstrPtr->second)
438 auto FnName = Instr->getFunction()->getName();
439 auto BB = Instr->getParent();
440 auto BBName = BB->hasName() ? BB->getName() :
"no-name";
443 auto InstrIt = DILocsBefore.
find(Instr);
444 if (InstrIt == DILocsBefore.
end()) {
445 if (ShouldWriteIntoJSON)
447 {
"fn-name", FnName.str()},
448 {
"bb-name", BBName.str()},
450 {
"action",
"not-generate"}}));
452 dbg() <<
"WARNING: " << NameOfWrappedPass
453 <<
" did not generate DILocation for " << *Instr
454 <<
" (BB: " << BBName <<
", Fn: " << FnName
455 <<
", File: " << FileNameFromCU <<
")\n";
458 if (!InstrIt->second)
462 if (ShouldWriteIntoJSON)
464 {
"fn-name", FnName.str()},
465 {
"bb-name", BBName.str()},
467 {
"action",
"drop"}}));
469 dbg() <<
"WARNING: " << NameOfWrappedPass <<
" dropped DILocation of "
470 << *Instr <<
" (BB: " << BBName <<
", Fn: " << FnName
471 <<
", File: " << FileNameFromCU <<
")\n";
484 bool Preserved =
true;
485 for (
const auto &V : DIVarsBefore) {
486 auto VarIt = DIVarsAfter.
find(V.first);
487 if (VarIt == DIVarsAfter.
end())
490 unsigned NumOfDbgValsAfter = VarIt->second;
492 if (V.second > NumOfDbgValsAfter) {
493 if (ShouldWriteIntoJSON)
495 {{
"metadata",
"dbg-var-intrinsic"},
496 {
"name", V.first->getName()},
498 {
"action",
"drop"}}));
500 dbg() <<
"WARNING: " << NameOfWrappedPass
501 <<
" drops dbg.value()/dbg.declare() for " << V.first->getName()
503 <<
"function " << V.first->getScope()->getSubprogram()->getName()
504 <<
" (file " << FileNameFromCU <<
")\n";
520 errs() <<
"Could not open file: " << EC.message() <<
", "
521 << OrigDIVerifyBugsReportFilePath <<
'\n';
525 if (
auto L = OS_FILE.lock()) {
526 OS_FILE <<
"{\"file\":\"" << FileNameFromCU <<
"\", ";
529 NameOfWrappedPass !=
"" ? NameOfWrappedPass :
"no-name";
530 OS_FILE <<
"\"pass\":\"" <<
PassName <<
"\", ";
533 OS_FILE <<
"\"bugs\": " << BugsToPrint;
544 StringRef OrigDIVerifyBugsReportFilePath) {
545 LLVM_DEBUG(
dbgs() << Banner <<
": (after) " << NameOfWrappedPass <<
'\n');
547 if (!M.getNamedMetadata(
"llvm.dbg.cu")) {
548 dbg() << Banner <<
": Skipping module without debug info\n";
557 if (isFunctionSkipped(
F))
565 auto *SP =
F.getSubprogram();
570 for (
const DINode *DN : SP->getRetainedNodes()) {
571 if (
const auto *DV = dyn_cast<DILocalVariable>(DN)) {
585 if (DebugifyLevel > Level::Locations) {
586 auto HandleDbgVariable = [&](
auto *DbgVar) {
590 if (DbgVar->getDebugLoc().getInlinedAt())
593 if (DbgVar->isKillLocation())
596 auto *Var = DbgVar->getVariable();
600 HandleDbgVariable(&DVR);
601 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
602 HandleDbgVariable(DVI);
606 if (isa<DbgInfoIntrinsic>(&
I))
612 bool HasLoc = Loc !=
nullptr;
621 (cast<DICompileUnit>(M.getNamedMetadata(
"llvm.dbg.cu")->getOperand(0)))
624 auto DIFunctionsBefore = DebugInfoBeforePass.
DIFunctions;
625 auto DIFunctionsAfter = DebugInfoAfterPass.
DIFunctions;
627 auto DILocsBefore = DebugInfoBeforePass.
DILocations;
632 auto DIVarsBefore = DebugInfoBeforePass.
DIVariables;
635 bool ShouldWriteIntoJSON = !OrigDIVerifyBugsReportFilePath.
empty();
639 checkFunctions(DIFunctionsBefore, DIFunctionsAfter, NameOfWrappedPass,
640 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
642 DILocsBefore, DILocsAfter, InstToDelete, NameOfWrappedPass,
643 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
645 bool ResultForVars =
checkVars(DIVarsBefore, DIVarsAfter, NameOfWrappedPass,
646 FileNameFromCU, ShouldWriteIntoJSON, Bugs);
648 bool Result = ResultForFunc && ResultForInsts && ResultForVars;
650 StringRef ResultBanner = NameOfWrappedPass !=
"" ? NameOfWrappedPass : Banner;
651 if (ShouldWriteIntoJSON && !Bugs.
empty())
652 writeJSON(OrigDIVerifyBugsReportFilePath, FileNameFromCU, NameOfWrappedPass,
656 dbg() << ResultBanner <<
": PASS\n";
658 dbg() << ResultBanner <<
": FAIL\n";
663 DebugInfoBeforePass = DebugInfoAfterPass;
671template <
typename DbgValTy>
672bool diagnoseMisSizedDbgValue(
Module &M, DbgValTy *DbgVal) {
681 if (DbgVal->getExpression()->getNumElements())
684 Value *V = DbgVal->getVariableLocationOp(0);
688 Type *Ty = V->getType();
689 uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
690 std::optional<uint64_t> DbgVarSize = DbgVal->getFragmentSizeInBits();
691 if (!ValueOperandSize || !DbgVarSize)
694 bool HasBadSize =
false;
696 auto Signedness = DbgVal->getVariable()->getSignedness();
697 if (Signedness && *Signedness == DIBasicType::Signedness::Signed)
698 HasBadSize = ValueOperandSize < *DbgVarSize;
700 HasBadSize = ValueOperandSize != *DbgVarSize;
704 dbg() <<
"ERROR: dbg.value operand has size " << ValueOperandSize
705 <<
", but its variable has size " << *DbgVarSize <<
": ";
706 DbgVal->print(dbg());
712bool checkDebugifyMetadata(
Module &M,
719 dbg() << Banner <<
": Skipping module without debugify metadata\n";
723 auto getDebugifyOperand = [&](
unsigned Idx) ->
unsigned {
728 "llvm.debugify should have exactly 2 operands!");
729 unsigned OriginalNumLines = getDebugifyOperand(0);
730 unsigned OriginalNumVars = getDebugifyOperand(1);
731 bool HasErrors =
false;
735 if (StatsMap && !NameOfWrappedPass.
empty())
736 Stats = &StatsMap->operator[](NameOfWrappedPass);
738 BitVector MissingLines{OriginalNumLines,
true};
739 BitVector MissingVars{OriginalNumVars,
true};
741 if (isFunctionSkipped(
F))
746 if (isa<DbgValueInst>(&
I))
749 auto DL =
I.getDebugLoc();
750 if (
DL &&
DL.getLine() != 0) {
751 MissingLines.reset(
DL.getLine() - 1);
755 if (!isa<PHINode>(&
I) && !
DL) {
756 dbg() <<
"WARNING: Instruction with empty DebugLoc in function ";
757 dbg() <<
F.getName() <<
" --";
764 auto CheckForMisSized = [&](
auto *DbgVal) {
766 (void)to_integer(DbgVal->getVariable()->getName(), Var, 10);
767 assert(Var <= OriginalNumVars &&
"Unexpected name for DILocalVariable");
768 bool HasBadSize = diagnoseMisSizedDbgValue(M, DbgVal);
770 MissingVars.reset(Var - 1);
771 HasErrors |= HasBadSize;
775 if (DVR.isDbgValue() || DVR.isDbgAssign())
776 CheckForMisSized(&DVR);
777 auto *DVI = dyn_cast<DbgValueInst>(&
I);
780 CheckForMisSized(DVI);
785 for (
unsigned Idx : MissingLines.set_bits())
786 dbg() <<
"WARNING: Missing line " <<
Idx + 1 <<
"\n";
788 for (
unsigned Idx : MissingVars.set_bits())
789 dbg() <<
"WARNING: Missing variable " <<
Idx + 1 <<
"\n";
793 Stats->NumDbgLocsExpected += OriginalNumLines;
794 Stats->NumDbgLocsMissing += MissingLines.count();
795 Stats->NumDbgValuesExpected += OriginalNumVars;
796 Stats->NumDbgValuesMissing += MissingVars.count();
800 if (!NameOfWrappedPass.
empty())
801 dbg() <<
" [" << NameOfWrappedPass <<
"]";
802 dbg() <<
": " << (HasErrors ?
"FAIL" :
"PASS") <<
'\n';
814struct DebugifyModulePass :
public ModulePass {
817 applyDebugify(M, Mode, DebugInfoBeforePass, NameOfWrappedPass);
821 DebugifyModulePass(
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
825 DebugInfoBeforePass(DebugInfoBeforePass),
Mode(
Mode) {}
848 DebugifyFunctionPass(
849 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
853 DebugInfoBeforePass(DebugInfoBeforePass),
Mode(
Mode) {}
869struct CheckDebugifyModulePass :
public ModulePass {
872 if (Mode == DebugifyMode::SyntheticDebugInfo)
873 Result = checkDebugifyMetadata(M,
M.functions(), NameOfWrappedPass,
874 "CheckModuleDebugify", Strip, StatsMap);
877 M,
M.functions(), *DebugInfoBeforePass,
878 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,
879 OrigDIVerifyBugsReportFilePath);
884 CheckDebugifyModulePass(
885 bool Strip =
false,
StringRef NameOfWrappedPass =
"",
887 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
889 StringRef OrigDIVerifyBugsReportFilePath =
"")
891 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
892 StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass),
Mode(
Mode),
903 StringRef OrigDIVerifyBugsReportFilePath;
915 auto FuncIt =
F.getIterator();
917 if (Mode == DebugifyMode::SyntheticDebugInfo)
919 NameOfWrappedPass,
"CheckFunctionDebugify",
923 M,
make_range(FuncIt, std::next(FuncIt)), *DebugInfoBeforePass,
924 "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass,
925 OrigDIVerifyBugsReportFilePath);
930 CheckDebugifyFunctionPass(
931 bool Strip =
false,
StringRef NameOfWrappedPass =
"",
933 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
935 StringRef OrigDIVerifyBugsReportFilePath =
"")
937 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
938 StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass),
Mode(
Mode),
949 StringRef OrigDIVerifyBugsReportFilePath;
962 errs() <<
"Could not open file: " << EC.message() <<
", " << Path <<
'\n';
966 OS <<
"Pass Name" <<
',' <<
"# of missing debug values" <<
','
967 <<
"# of missing locations" <<
',' <<
"Missing/Expected value ratio" <<
','
968 <<
"Missing/Expected location ratio" <<
'\n';
969 for (
const auto &Entry : Map) {
973 OS <<
Pass <<
',' <<
Stats.NumDbgValuesMissing <<
','
974 <<
Stats.NumDbgLocsMissing <<
',' <<
Stats.getMissingValueRatio() <<
','
975 <<
Stats.getEmptyLocationRatio() <<
'\n';
983 return new DebugifyModulePass();
985 return new DebugifyModulePass(Mode, NameOfWrappedPass, DebugInfoBeforePass);
993 return new DebugifyFunctionPass();
995 return new DebugifyFunctionPass(Mode, NameOfWrappedPass, DebugInfoBeforePass);
999 if (Mode == DebugifyMode::SyntheticDebugInfo)
1001 "ModuleDebugify: ",
nullptr);
1004 "ModuleDebugify (original debuginfo)",
1015 StringRef OrigDIVerifyBugsReportFilePath) {
1017 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
1019 return new CheckDebugifyModulePass(
false, NameOfWrappedPass,
nullptr, Mode,
1020 DebugInfoBeforePass,
1021 OrigDIVerifyBugsReportFilePath);
1027 StringRef OrigDIVerifyBugsReportFilePath) {
1029 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
1031 return new CheckDebugifyFunctionPass(
false, NameOfWrappedPass,
nullptr, Mode,
1032 DebugInfoBeforePass,
1033 OrigDIVerifyBugsReportFilePath);
1038 if (Mode == DebugifyMode::SyntheticDebugInfo)
1039 checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
1040 "CheckModuleDebugify", Strip, StatsMap);
1043 M, M.functions(), *DebugInfoBeforePass,
1044 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,
1045 OrigDIVerifyBugsReportFilePath);
1052 "AnalysisManagerProxy",
"PrintFunctionPass",
1053 "PrintModulePass",
"BitcodeWriterPass",
1054 "ThinLTOBitcodeWriterPass",
"VerifierPass"});
1064 if (
const auto **CF = llvm::any_cast<const Function *>(&
IR)) {
1070 }
else if (
const auto **CM = llvm::any_cast<const Module *>(&
IR)) {
1082 if (
const auto **CF = llvm::any_cast<const Function *>(&
IR)) {
1085 auto It =
F.getIterator();
1086 if (Mode == DebugifyMode::SyntheticDebugInfo)
1087 checkDebugifyMetadata(M,
make_range(It, std::next(It)),
P,
1088 "CheckFunctionDebugify",
true,
1092 *DebugInfoBeforePass,
1093 "CheckModuleDebugify (original debuginfo)",
1094 P, OrigDIVerifyBugsReportFilePath);
1098 }
else if (
const auto **CM = llvm::any_cast<const Module *>(&
IR)) {
1100 if (Mode == DebugifyMode::SyntheticDebugInfo)
1101 checkDebugifyMetadata(M, M.functions(),
P,
"CheckModuleDebugify",
1105 "CheckModuleDebugify (original debuginfo)",
1106 P, OrigDIVerifyBugsReportFilePath);
1112char DebugifyModulePass::ID = 0;
1114 "Attach debug info to everything");
1116char CheckDebugifyModulePass::ID = 0;
1118 CDM(
"check-debugify",
"Check debug info from -debugify");
1120char DebugifyFunctionPass::ID = 0;
1122 "Attach debug info to a function");
1124char CheckDebugifyFunctionPass::ID = 0;
1126 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.
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
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.
DIBasicType * createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, DINode::DIFlags Flags=DINode::FlagZero, uint32_t NumExtraInhabitants=0)
Create debugging information entry for a basic type.
DITypeRefArray getOrCreateTypeArray(ArrayRef< Metadata * > Elements)
Get a DITypeRefArray, create one if required.
DIExpression * createExpression(ArrayRef< uint64_t > Addr={})
Create a new descriptor for the specified variable which has a complex address expression for its add...
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)
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.
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)
RegisterPass<t> template - This template class is used to notify the system that a Pass is available ...