1 //===- Debugify.cpp - Check debug info preservation in optimizations ------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 /// \file In the `synthetic` mode, the `-debugify` attaches synthetic debug info
10 /// to everything. It can be used to create targeted tests for debug info
11 /// preservation. In addition, when using the `original` mode, it can check
12 /// original debug info preservation. The `synthetic` mode is default one.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/Transforms/Utils/Debugify.h"
17 #include "llvm/ADT/BitVector.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/IR/DIBuilder.h"
20 #include "llvm/IR/DebugInfo.h"
21 #include "llvm/IR/InstIterator.h"
22 #include "llvm/IR/Instructions.h"
23 #include "llvm/IR/IntrinsicInst.h"
24 #include "llvm/IR/Module.h"
25 #include "llvm/IR/PassInstrumentation.h"
26 #include "llvm/Pass.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/FileSystem.h"
29 #include "llvm/Support/JSON.h"
32 #define DEBUG_TYPE "debugify"
38 cl::opt
<bool> Quiet("debugify-quiet",
39 cl::desc("Suppress verbose debugify output"));
41 cl::opt
<uint64_t> DebugifyFunctionsLimit(
42 "debugify-func-limit",
43 cl::desc("Set max number of processed functions per pass."),
51 cl::opt
<Level
> DebugifyLevel(
52 "debugify-level", cl::desc("Kind of debug info to add"),
53 cl::values(clEnumValN(Level::Locations
, "locations", "Locations only"),
54 clEnumValN(Level::LocationsAndVariables
, "location+variables",
55 "Locations and Variables")),
56 cl::init(Level::LocationsAndVariables
));
58 raw_ostream
&dbg() { return Quiet
? nulls() : errs(); }
60 uint64_t getAllocSizeInBits(Module
&M
, Type
*Ty
) {
61 return Ty
->isSized() ? M
.getDataLayout().getTypeAllocSizeInBits(Ty
) : 0;
64 bool isFunctionSkipped(Function
&F
) {
65 return F
.isDeclaration() || !F
.hasExactDefinition();
68 /// Find the basic block's terminating instruction.
70 /// Special care is needed to handle musttail and deopt calls, as these behave
71 /// like (but are in fact not) terminators.
72 Instruction
*findTerminatingInstruction(BasicBlock
&BB
) {
73 if (auto *I
= BB
.getTerminatingMustTailCall())
75 if (auto *I
= BB
.getTerminatingDeoptimizeCall())
77 return BB
.getTerminator();
79 } // end anonymous namespace
81 bool llvm::applyDebugifyMetadata(
82 Module
&M
, iterator_range
<Module::iterator
> Functions
, StringRef Banner
,
83 std::function
<bool(DIBuilder
&DIB
, Function
&F
)> ApplyToMF
) {
84 // Skip modules with debug info.
85 if (M
.getNamedMetadata("llvm.dbg.cu")) {
86 dbg() << Banner
<< "Skipping module with debug info\n";
91 LLVMContext
&Ctx
= M
.getContext();
92 auto *Int32Ty
= Type::getInt32Ty(Ctx
);
94 // Get a DIType which corresponds to Ty.
95 DenseMap
<uint64_t, DIType
*> TypeCache
;
96 auto getCachedDIType
= [&](Type
*Ty
) -> DIType
* {
97 uint64_t Size
= getAllocSizeInBits(M
, Ty
);
98 DIType
*&DTy
= TypeCache
[Size
];
100 std::string Name
= "ty" + utostr(Size
);
101 DTy
= DIB
.createBasicType(Name
, Size
, dwarf::DW_ATE_unsigned
);
106 unsigned NextLine
= 1;
107 unsigned NextVar
= 1;
108 auto File
= DIB
.createFile(M
.getName(), "/");
109 auto CU
= DIB
.createCompileUnit(dwarf::DW_LANG_C
, File
, "debugify",
110 /*isOptimized=*/true, "", 0);
112 // Visit each instruction.
113 for (Function
&F
: Functions
) {
114 if (isFunctionSkipped(F
))
117 bool InsertedDbgVal
= false;
119 DIB
.createSubroutineType(DIB
.getOrCreateTypeArray(std::nullopt
));
120 DISubprogram::DISPFlags SPFlags
=
121 DISubprogram::SPFlagDefinition
| DISubprogram::SPFlagOptimized
;
122 if (F
.hasPrivateLinkage() || F
.hasInternalLinkage())
123 SPFlags
|= DISubprogram::SPFlagLocalToUnit
;
124 auto SP
= DIB
.createFunction(CU
, F
.getName(), F
.getName(), File
, NextLine
,
125 SPType
, NextLine
, DINode::FlagZero
, SPFlags
);
128 // Helper that inserts a dbg.value before \p InsertBefore, copying the
129 // location (and possibly the type, if it's non-void) from \p TemplateInst.
130 auto insertDbgVal
= [&](Instruction
&TemplateInst
,
131 Instruction
*InsertBefore
) {
132 std::string Name
= utostr(NextVar
++);
133 Value
*V
= &TemplateInst
;
134 if (TemplateInst
.getType()->isVoidTy())
135 V
= ConstantInt::get(Int32Ty
, 0);
136 const DILocation
*Loc
= TemplateInst
.getDebugLoc().get();
137 auto LocalVar
= DIB
.createAutoVariable(SP
, Name
, File
, Loc
->getLine(),
138 getCachedDIType(V
->getType()),
139 /*AlwaysPreserve=*/true);
140 DIB
.insertDbgValueIntrinsic(V
, LocalVar
, DIB
.createExpression(), Loc
,
144 for (BasicBlock
&BB
: F
) {
145 // Attach debug locations.
146 for (Instruction
&I
: BB
)
147 I
.setDebugLoc(DILocation::get(Ctx
, NextLine
++, 1, SP
));
149 if (DebugifyLevel
< Level::LocationsAndVariables
)
152 // Inserting debug values into EH pads can break IR invariants.
156 // Find the terminating instruction, after which no debug values are
158 Instruction
*LastInst
= findTerminatingInstruction(BB
);
159 assert(LastInst
&& "Expected basic block with a terminator");
161 // Maintain an insertion point which can't be invalidated when updates
163 BasicBlock::iterator InsertPt
= BB
.getFirstInsertionPt();
164 assert(InsertPt
!= BB
.end() && "Expected to find an insertion point");
165 Instruction
*InsertBefore
= &*InsertPt
;
167 // Attach debug values.
168 for (Instruction
*I
= &*BB
.begin(); I
!= LastInst
; I
= I
->getNextNode()) {
169 // Skip void-valued instructions.
170 if (I
->getType()->isVoidTy())
173 // Phis and EH pads must be grouped at the beginning of the block.
174 // Only advance the insertion point when we finish visiting these.
175 if (!isa
<PHINode
>(I
) && !I
->isEHPad())
176 InsertBefore
= I
->getNextNode();
178 insertDbgVal(*I
, InsertBefore
);
179 InsertedDbgVal
= true;
182 // Make sure we emit at least one dbg.value, otherwise MachineDebugify may
183 // not have anything to work with as it goes about inserting DBG_VALUEs.
184 // (It's common for MIR tests to be written containing skeletal IR with
185 // empty functions -- we're still interested in debugifying the MIR within
186 // those tests, and this helps with that.)
187 if (DebugifyLevel
== Level::LocationsAndVariables
&& !InsertedDbgVal
) {
188 auto *Term
= findTerminatingInstruction(F
.getEntryBlock());
189 insertDbgVal(*Term
, Term
);
193 DIB
.finalizeSubprogram(SP
);
197 // Track the number of distinct lines and variables.
198 NamedMDNode
*NMD
= M
.getOrInsertNamedMetadata("llvm.debugify");
199 auto addDebugifyOperand
= [&](unsigned N
) {
200 NMD
->addOperand(MDNode::get(
201 Ctx
, ValueAsMetadata::getConstant(ConstantInt::get(Int32Ty
, N
))));
203 addDebugifyOperand(NextLine
- 1); // Original number of lines.
204 addDebugifyOperand(NextVar
- 1); // Original number of variables.
205 assert(NMD
->getNumOperands() == 2 &&
206 "llvm.debugify should have exactly 2 operands!");
208 // Claim that this synthetic debug info is valid.
209 StringRef DIVersionKey
= "Debug Info Version";
210 if (!M
.getModuleFlag(DIVersionKey
))
211 M
.addModuleFlag(Module::Warning
, DIVersionKey
, DEBUG_METADATA_VERSION
);
217 applyDebugify(Function
&F
,
218 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
219 DebugInfoPerPass
*DebugInfoBeforePass
= nullptr,
220 StringRef NameOfWrappedPass
= "") {
221 Module
&M
= *F
.getParent();
222 auto FuncIt
= F
.getIterator();
223 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
224 return applyDebugifyMetadata(M
, make_range(FuncIt
, std::next(FuncIt
)),
225 "FunctionDebugify: ", /*ApplyToMF*/ nullptr);
226 assert(DebugInfoBeforePass
);
227 return collectDebugInfoMetadata(M
, M
.functions(), *DebugInfoBeforePass
,
228 "FunctionDebugify (original debuginfo)",
233 applyDebugify(Module
&M
,
234 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
235 DebugInfoPerPass
*DebugInfoBeforePass
= nullptr,
236 StringRef NameOfWrappedPass
= "") {
237 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
238 return applyDebugifyMetadata(M
, M
.functions(),
239 "ModuleDebugify: ", /*ApplyToMF*/ nullptr);
240 return collectDebugInfoMetadata(M
, M
.functions(), *DebugInfoBeforePass
,
241 "ModuleDebugify (original debuginfo)",
245 bool llvm::stripDebugifyMetadata(Module
&M
) {
246 bool Changed
= false;
248 // Remove the llvm.debugify and llvm.mir.debugify module-level named metadata.
249 NamedMDNode
*DebugifyMD
= M
.getNamedMetadata("llvm.debugify");
251 M
.eraseNamedMetadata(DebugifyMD
);
255 if (auto *MIRDebugifyMD
= M
.getNamedMetadata("llvm.mir.debugify")) {
256 M
.eraseNamedMetadata(MIRDebugifyMD
);
260 // Strip out all debug intrinsics and supporting metadata (subprograms, types,
262 Changed
|= StripDebugInfo(M
);
264 // Strip out the dead dbg.value prototype.
265 Function
*DbgValF
= M
.getFunction("llvm.dbg.value");
267 assert(DbgValF
->isDeclaration() && DbgValF
->use_empty() &&
268 "Not all debug info stripped?");
269 DbgValF
->eraseFromParent();
273 // Strip out the module-level Debug Info Version metadata.
274 // FIXME: There must be an easier way to remove an operand from a NamedMDNode.
275 NamedMDNode
*NMD
= M
.getModuleFlagsMetadata();
278 SmallVector
<MDNode
*, 4> Flags(NMD
->operands());
279 NMD
->clearOperands();
280 for (MDNode
*Flag
: Flags
) {
281 auto *Key
= cast
<MDString
>(Flag
->getOperand(1));
282 if (Key
->getString() == "Debug Info Version") {
286 NMD
->addOperand(Flag
);
288 // If we left it empty we might as well remove it.
289 if (NMD
->getNumOperands() == 0)
290 NMD
->eraseFromParent();
295 bool llvm::collectDebugInfoMetadata(Module
&M
,
296 iterator_range
<Module::iterator
> Functions
,
297 DebugInfoPerPass
&DebugInfoBeforePass
,
299 StringRef NameOfWrappedPass
) {
300 LLVM_DEBUG(dbgs() << Banner
<< ": (before) " << NameOfWrappedPass
<< '\n');
302 if (!M
.getNamedMetadata("llvm.dbg.cu")) {
303 dbg() << Banner
<< ": Skipping module without debug info\n";
307 uint64_t FunctionsCnt
= DebugInfoBeforePass
.DIFunctions
.size();
308 // Visit each instruction.
309 for (Function
&F
: Functions
) {
310 // Use DI collected after previous Pass (when -debugify-each is used).
311 if (DebugInfoBeforePass
.DIFunctions
.count(&F
))
314 if (isFunctionSkipped(F
))
317 // Stop collecting DI if the Functions number reached the limit.
318 if (++FunctionsCnt
>= DebugifyFunctionsLimit
)
320 // Collect the DISubprogram.
321 auto *SP
= F
.getSubprogram();
322 DebugInfoBeforePass
.DIFunctions
.insert({&F
, SP
});
324 LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP
<< '\n');
325 for (const DINode
*DN
: SP
->getRetainedNodes()) {
326 if (const auto *DV
= dyn_cast
<DILocalVariable
>(DN
)) {
327 DebugInfoBeforePass
.DIVariables
[DV
] = 0;
332 for (BasicBlock
&BB
: F
) {
333 // Collect debug locations (!dbg) and debug variable intrinsics.
334 for (Instruction
&I
: BB
) {
339 // Cllect dbg.values and dbg.declare.
340 if (DebugifyLevel
> Level::Locations
) {
341 if (auto *DVI
= dyn_cast
<DbgVariableIntrinsic
>(&I
)) {
344 // Skip inlined variables.
345 if (I
.getDebugLoc().getInlinedAt())
347 // Skip undef values.
348 if (DVI
->isKillLocation())
351 auto *Var
= DVI
->getVariable();
352 DebugInfoBeforePass
.DIVariables
[Var
]++;
357 // Skip debug instructions other than dbg.value and dbg.declare.
358 if (isa
<DbgInfoIntrinsic
>(&I
))
361 LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I
<< '\n');
362 DebugInfoBeforePass
.InstToDelete
.insert({&I
, &I
});
364 const DILocation
*Loc
= I
.getDebugLoc().get();
365 bool HasLoc
= Loc
!= nullptr;
366 DebugInfoBeforePass
.DILocations
.insert({&I
, HasLoc
});
374 // This checks the preservation of original debug info attached to functions.
375 static bool checkFunctions(const DebugFnMap
&DIFunctionsBefore
,
376 const DebugFnMap
&DIFunctionsAfter
,
377 StringRef NameOfWrappedPass
,
378 StringRef FileNameFromCU
, bool ShouldWriteIntoJSON
,
379 llvm::json::Array
&Bugs
) {
380 bool Preserved
= true;
381 for (const auto &F
: DIFunctionsAfter
) {
384 auto SPIt
= DIFunctionsBefore
.find(F
.first
);
385 if (SPIt
== DIFunctionsBefore
.end()) {
386 if (ShouldWriteIntoJSON
)
387 Bugs
.push_back(llvm::json::Object({{"metadata", "DISubprogram"},
388 {"name", F
.first
->getName()},
389 {"action", "not-generate"}}));
391 dbg() << "ERROR: " << NameOfWrappedPass
392 << " did not generate DISubprogram for " << F
.first
->getName()
393 << " from " << FileNameFromCU
<< '\n';
396 auto SP
= SPIt
->second
;
399 // If the function had the SP attached before the pass, consider it as
401 if (ShouldWriteIntoJSON
)
402 Bugs
.push_back(llvm::json::Object({{"metadata", "DISubprogram"},
403 {"name", F
.first
->getName()},
404 {"action", "drop"}}));
406 dbg() << "ERROR: " << NameOfWrappedPass
<< " dropped DISubprogram of "
407 << F
.first
->getName() << " from " << FileNameFromCU
<< '\n';
415 // This checks the preservation of the original debug info attached to
417 static bool checkInstructions(const DebugInstMap
&DILocsBefore
,
418 const DebugInstMap
&DILocsAfter
,
419 const WeakInstValueMap
&InstToDelete
,
420 StringRef NameOfWrappedPass
,
421 StringRef FileNameFromCU
,
422 bool ShouldWriteIntoJSON
,
423 llvm::json::Array
&Bugs
) {
424 bool Preserved
= true;
425 for (const auto &L
: DILocsAfter
) {
428 auto Instr
= L
.first
;
430 // In order to avoid pointer reuse/recycling, skip the values that might
431 // have been deleted during a pass.
432 auto WeakInstrPtr
= InstToDelete
.find(Instr
);
433 if (WeakInstrPtr
!= InstToDelete
.end() && !WeakInstrPtr
->second
)
436 auto FnName
= Instr
->getFunction()->getName();
437 auto BB
= Instr
->getParent();
438 auto BBName
= BB
->hasName() ? BB
->getName() : "no-name";
439 auto InstName
= Instruction::getOpcodeName(Instr
->getOpcode());
441 auto InstrIt
= DILocsBefore
.find(Instr
);
442 if (InstrIt
== DILocsBefore
.end()) {
443 if (ShouldWriteIntoJSON
)
444 Bugs
.push_back(llvm::json::Object({{"metadata", "DILocation"},
445 {"fn-name", FnName
.str()},
446 {"bb-name", BBName
.str()},
448 {"action", "not-generate"}}));
450 dbg() << "WARNING: " << NameOfWrappedPass
451 << " did not generate DILocation for " << *Instr
452 << " (BB: " << BBName
<< ", Fn: " << FnName
453 << ", File: " << FileNameFromCU
<< ")\n";
456 if (!InstrIt
->second
)
458 // If the instr had the !dbg attached before the pass, consider it as
459 // a debug info issue.
460 if (ShouldWriteIntoJSON
)
461 Bugs
.push_back(llvm::json::Object({{"metadata", "DILocation"},
462 {"fn-name", FnName
.str()},
463 {"bb-name", BBName
.str()},
465 {"action", "drop"}}));
467 dbg() << "WARNING: " << NameOfWrappedPass
<< " dropped DILocation of "
468 << *Instr
<< " (BB: " << BBName
<< ", Fn: " << FnName
469 << ", File: " << FileNameFromCU
<< ")\n";
477 // This checks the preservation of original debug variable intrinsics.
478 static bool checkVars(const DebugVarMap
&DIVarsBefore
,
479 const DebugVarMap
&DIVarsAfter
,
480 StringRef NameOfWrappedPass
, StringRef FileNameFromCU
,
481 bool ShouldWriteIntoJSON
, llvm::json::Array
&Bugs
) {
482 bool Preserved
= true;
483 for (const auto &V
: DIVarsBefore
) {
484 auto VarIt
= DIVarsAfter
.find(V
.first
);
485 if (VarIt
== DIVarsAfter
.end())
488 unsigned NumOfDbgValsAfter
= VarIt
->second
;
490 if (V
.second
> NumOfDbgValsAfter
) {
491 if (ShouldWriteIntoJSON
)
492 Bugs
.push_back(llvm::json::Object(
493 {{"metadata", "dbg-var-intrinsic"},
494 {"name", V
.first
->getName()},
495 {"fn-name", V
.first
->getScope()->getSubprogram()->getName()},
496 {"action", "drop"}}));
498 dbg() << "WARNING: " << NameOfWrappedPass
499 << " drops dbg.value()/dbg.declare() for " << V
.first
->getName()
501 << "function " << V
.first
->getScope()->getSubprogram()->getName()
502 << " (file " << FileNameFromCU
<< ")\n";
510 // Write the json data into the specifed file.
511 static void writeJSON(StringRef OrigDIVerifyBugsReportFilePath
,
512 StringRef FileNameFromCU
, StringRef NameOfWrappedPass
,
513 llvm::json::Array
&Bugs
) {
515 raw_fd_ostream OS_FILE
{OrigDIVerifyBugsReportFilePath
, EC
,
516 sys::fs::OF_Append
| sys::fs::OF_TextWithCRLF
};
518 errs() << "Could not open file: " << EC
.message() << ", "
519 << OrigDIVerifyBugsReportFilePath
<< '\n';
523 if (auto L
= OS_FILE
.lock()) {
524 OS_FILE
<< "{\"file\":\"" << FileNameFromCU
<< "\", ";
527 NameOfWrappedPass
!= "" ? NameOfWrappedPass
: "no-name";
528 OS_FILE
<< "\"pass\":\"" << PassName
<< "\", ";
530 llvm::json::Value BugsToPrint
{std::move(Bugs
)};
531 OS_FILE
<< "\"bugs\": " << BugsToPrint
;
538 bool llvm::checkDebugInfoMetadata(Module
&M
,
539 iterator_range
<Module::iterator
> Functions
,
540 DebugInfoPerPass
&DebugInfoBeforePass
,
541 StringRef Banner
, StringRef NameOfWrappedPass
,
542 StringRef OrigDIVerifyBugsReportFilePath
) {
543 LLVM_DEBUG(dbgs() << Banner
<< ": (after) " << NameOfWrappedPass
<< '\n');
545 if (!M
.getNamedMetadata("llvm.dbg.cu")) {
546 dbg() << Banner
<< ": Skipping module without debug info\n";
550 // Map the debug info holding DIs after a pass.
551 DebugInfoPerPass DebugInfoAfterPass
;
553 // Visit each instruction.
554 for (Function
&F
: Functions
) {
555 if (isFunctionSkipped(F
))
558 // Don't process functions without DI collected before the Pass.
559 if (!DebugInfoBeforePass
.DIFunctions
.count(&F
))
561 // TODO: Collect metadata other than DISubprograms.
562 // Collect the DISubprogram.
563 auto *SP
= F
.getSubprogram();
564 DebugInfoAfterPass
.DIFunctions
.insert({&F
, SP
});
567 LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP
<< '\n');
568 for (const DINode
*DN
: SP
->getRetainedNodes()) {
569 if (const auto *DV
= dyn_cast
<DILocalVariable
>(DN
)) {
570 DebugInfoAfterPass
.DIVariables
[DV
] = 0;
575 for (BasicBlock
&BB
: F
) {
576 // Collect debug locations (!dbg) and debug variable intrinsics.
577 for (Instruction
&I
: BB
) {
582 // Collect dbg.values and dbg.declares.
583 if (DebugifyLevel
> Level::Locations
) {
584 if (auto *DVI
= dyn_cast
<DbgVariableIntrinsic
>(&I
)) {
587 // Skip inlined variables.
588 if (I
.getDebugLoc().getInlinedAt())
590 // Skip undef values.
591 if (DVI
->isKillLocation())
594 auto *Var
= DVI
->getVariable();
595 DebugInfoAfterPass
.DIVariables
[Var
]++;
600 // Skip debug instructions other than dbg.value and dbg.declare.
601 if (isa
<DbgInfoIntrinsic
>(&I
))
604 LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I
<< '\n');
606 const DILocation
*Loc
= I
.getDebugLoc().get();
607 bool HasLoc
= Loc
!= nullptr;
609 DebugInfoAfterPass
.DILocations
.insert({&I
, HasLoc
});
614 // TODO: The name of the module could be read better?
615 StringRef FileNameFromCU
=
616 (cast
<DICompileUnit
>(M
.getNamedMetadata("llvm.dbg.cu")->getOperand(0)))
619 auto DIFunctionsBefore
= DebugInfoBeforePass
.DIFunctions
;
620 auto DIFunctionsAfter
= DebugInfoAfterPass
.DIFunctions
;
622 auto DILocsBefore
= DebugInfoBeforePass
.DILocations
;
623 auto DILocsAfter
= DebugInfoAfterPass
.DILocations
;
625 auto InstToDelete
= DebugInfoBeforePass
.InstToDelete
;
627 auto DIVarsBefore
= DebugInfoBeforePass
.DIVariables
;
628 auto DIVarsAfter
= DebugInfoAfterPass
.DIVariables
;
630 bool ShouldWriteIntoJSON
= !OrigDIVerifyBugsReportFilePath
.empty();
631 llvm::json::Array Bugs
;
634 checkFunctions(DIFunctionsBefore
, DIFunctionsAfter
, NameOfWrappedPass
,
635 FileNameFromCU
, ShouldWriteIntoJSON
, Bugs
);
636 bool ResultForInsts
= checkInstructions(
637 DILocsBefore
, DILocsAfter
, InstToDelete
, NameOfWrappedPass
,
638 FileNameFromCU
, ShouldWriteIntoJSON
, Bugs
);
640 bool ResultForVars
= checkVars(DIVarsBefore
, DIVarsAfter
, NameOfWrappedPass
,
641 FileNameFromCU
, ShouldWriteIntoJSON
, Bugs
);
643 bool Result
= ResultForFunc
&& ResultForInsts
&& ResultForVars
;
645 StringRef ResultBanner
= NameOfWrappedPass
!= "" ? NameOfWrappedPass
: Banner
;
646 if (ShouldWriteIntoJSON
&& !Bugs
.empty())
647 writeJSON(OrigDIVerifyBugsReportFilePath
, FileNameFromCU
, NameOfWrappedPass
,
651 dbg() << ResultBanner
<< ": PASS\n";
653 dbg() << ResultBanner
<< ": FAIL\n";
655 // In the case of the `debugify-each`, no need to go over all the instructions
656 // again in the collectDebugInfoMetadata(), since as an input we can use
657 // the debugging information from the previous pass.
658 DebugInfoBeforePass
= DebugInfoAfterPass
;
660 LLVM_DEBUG(dbgs() << "\n\n");
665 /// Return true if a mis-sized diagnostic is issued for \p DVI.
666 bool diagnoseMisSizedDbgValue(Module
&M
, DbgValueInst
*DVI
) {
667 // The size of a dbg.value's value operand should match the size of the
668 // variable it corresponds to.
670 // TODO: This, along with a check for non-null value operands, should be
671 // promoted to verifier failures.
673 // For now, don't try to interpret anything more complicated than an empty
674 // DIExpression. Eventually we should try to handle OP_deref and fragments.
675 if (DVI
->getExpression()->getNumElements())
678 Value
*V
= DVI
->getVariableLocationOp(0);
682 Type
*Ty
= V
->getType();
683 uint64_t ValueOperandSize
= getAllocSizeInBits(M
, Ty
);
684 std::optional
<uint64_t> DbgVarSize
= DVI
->getFragmentSizeInBits();
685 if (!ValueOperandSize
|| !DbgVarSize
)
688 bool HasBadSize
= false;
689 if (Ty
->isIntegerTy()) {
690 auto Signedness
= DVI
->getVariable()->getSignedness();
691 if (Signedness
&& *Signedness
== DIBasicType::Signedness::Signed
)
692 HasBadSize
= ValueOperandSize
< *DbgVarSize
;
694 HasBadSize
= ValueOperandSize
!= *DbgVarSize
;
698 dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
699 << ", but its variable has size " << *DbgVarSize
<< ": ";
706 bool checkDebugifyMetadata(Module
&M
,
707 iterator_range
<Module::iterator
> Functions
,
708 StringRef NameOfWrappedPass
, StringRef Banner
,
709 bool Strip
, DebugifyStatsMap
*StatsMap
) {
710 // Skip modules without debugify metadata.
711 NamedMDNode
*NMD
= M
.getNamedMetadata("llvm.debugify");
713 dbg() << Banner
<< ": Skipping module without debugify metadata\n";
717 auto getDebugifyOperand
= [&](unsigned Idx
) -> unsigned {
718 return mdconst::extract
<ConstantInt
>(NMD
->getOperand(Idx
)->getOperand(0))
721 assert(NMD
->getNumOperands() == 2 &&
722 "llvm.debugify should have exactly 2 operands!");
723 unsigned OriginalNumLines
= getDebugifyOperand(0);
724 unsigned OriginalNumVars
= getDebugifyOperand(1);
725 bool HasErrors
= false;
727 // Track debug info loss statistics if able.
728 DebugifyStatistics
*Stats
= nullptr;
729 if (StatsMap
&& !NameOfWrappedPass
.empty())
730 Stats
= &StatsMap
->operator[](NameOfWrappedPass
);
732 BitVector MissingLines
{OriginalNumLines
, true};
733 BitVector MissingVars
{OriginalNumVars
, true};
734 for (Function
&F
: Functions
) {
735 if (isFunctionSkipped(F
))
738 // Find missing lines.
739 for (Instruction
&I
: instructions(F
)) {
740 if (isa
<DbgValueInst
>(&I
))
743 auto DL
= I
.getDebugLoc();
744 if (DL
&& DL
.getLine() != 0) {
745 MissingLines
.reset(DL
.getLine() - 1);
749 if (!isa
<PHINode
>(&I
) && !DL
) {
750 dbg() << "WARNING: Instruction with empty DebugLoc in function ";
751 dbg() << F
.getName() << " --";
757 // Find missing variables and mis-sized debug values.
758 for (Instruction
&I
: instructions(F
)) {
759 auto *DVI
= dyn_cast
<DbgValueInst
>(&I
);
764 (void)to_integer(DVI
->getVariable()->getName(), Var
, 10);
765 assert(Var
<= OriginalNumVars
&& "Unexpected name for DILocalVariable");
766 bool HasBadSize
= diagnoseMisSizedDbgValue(M
, DVI
);
768 MissingVars
.reset(Var
- 1);
769 HasErrors
|= HasBadSize
;
773 // Print the results.
774 for (unsigned Idx
: MissingLines
.set_bits())
775 dbg() << "WARNING: Missing line " << Idx
+ 1 << "\n";
777 for (unsigned Idx
: MissingVars
.set_bits())
778 dbg() << "WARNING: Missing variable " << Idx
+ 1 << "\n";
780 // Update DI loss statistics.
782 Stats
->NumDbgLocsExpected
+= OriginalNumLines
;
783 Stats
->NumDbgLocsMissing
+= MissingLines
.count();
784 Stats
->NumDbgValuesExpected
+= OriginalNumVars
;
785 Stats
->NumDbgValuesMissing
+= MissingVars
.count();
789 if (!NameOfWrappedPass
.empty())
790 dbg() << " [" << NameOfWrappedPass
<< "]";
791 dbg() << ": " << (HasErrors
? "FAIL" : "PASS") << '\n';
793 // Strip debugify metadata if required.
795 return stripDebugifyMetadata(M
);
800 /// ModulePass for attaching synthetic debug info to everything, used with the
801 /// legacy module pass manager.
802 struct DebugifyModulePass
: public ModulePass
{
803 bool runOnModule(Module
&M
) override
{
804 bool NewDebugMode
= M
.IsNewDbgInfoFormat
;
806 M
.convertFromNewDbgValues();
808 bool Result
= applyDebugify(M
, Mode
, DebugInfoBeforePass
, NameOfWrappedPass
);
811 M
.convertToNewDbgValues();
815 DebugifyModulePass(enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
816 StringRef NameOfWrappedPass
= "",
817 DebugInfoPerPass
*DebugInfoBeforePass
= nullptr)
818 : ModulePass(ID
), NameOfWrappedPass(NameOfWrappedPass
),
819 DebugInfoBeforePass(DebugInfoBeforePass
), Mode(Mode
) {}
821 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
822 AU
.setPreservesAll();
825 static char ID
; // Pass identification.
828 StringRef NameOfWrappedPass
;
829 DebugInfoPerPass
*DebugInfoBeforePass
;
830 enum DebugifyMode Mode
;
833 /// FunctionPass for attaching synthetic debug info to instructions within a
834 /// single function, used with the legacy module pass manager.
835 struct DebugifyFunctionPass
: public FunctionPass
{
836 bool runOnFunction(Function
&F
) override
{
837 bool NewDebugMode
= F
.IsNewDbgInfoFormat
;
839 F
.convertFromNewDbgValues();
841 bool Result
= applyDebugify(F
, Mode
, DebugInfoBeforePass
, NameOfWrappedPass
);
844 F
.convertToNewDbgValues();
848 DebugifyFunctionPass(
849 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
850 StringRef NameOfWrappedPass
= "",
851 DebugInfoPerPass
*DebugInfoBeforePass
= nullptr)
852 : FunctionPass(ID
), NameOfWrappedPass(NameOfWrappedPass
),
853 DebugInfoBeforePass(DebugInfoBeforePass
), Mode(Mode
) {}
855 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
856 AU
.setPreservesAll();
859 static char ID
; // Pass identification.
862 StringRef NameOfWrappedPass
;
863 DebugInfoPerPass
*DebugInfoBeforePass
;
864 enum DebugifyMode Mode
;
867 /// ModulePass for checking debug info inserted by -debugify, used with the
868 /// legacy module pass manager.
869 struct CheckDebugifyModulePass
: public ModulePass
{
870 bool runOnModule(Module
&M
) override
{
871 bool NewDebugMode
= M
.IsNewDbgInfoFormat
;
873 M
.convertFromNewDbgValues();
876 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
877 Result
= checkDebugifyMetadata(M
, M
.functions(), NameOfWrappedPass
,
878 "CheckModuleDebugify", Strip
, StatsMap
);
880 Result
= checkDebugInfoMetadata(
881 M
, M
.functions(), *DebugInfoBeforePass
,
882 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass
,
883 OrigDIVerifyBugsReportFilePath
);
886 M
.convertToNewDbgValues();
891 CheckDebugifyModulePass(
892 bool Strip
= false, StringRef NameOfWrappedPass
= "",
893 DebugifyStatsMap
*StatsMap
= nullptr,
894 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
895 DebugInfoPerPass
*DebugInfoBeforePass
= nullptr,
896 StringRef OrigDIVerifyBugsReportFilePath
= "")
897 : ModulePass(ID
), NameOfWrappedPass(NameOfWrappedPass
),
898 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath
),
899 StatsMap(StatsMap
), DebugInfoBeforePass(DebugInfoBeforePass
), Mode(Mode
),
902 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
903 AU
.setPreservesAll();
906 static char ID
; // Pass identification.
909 StringRef NameOfWrappedPass
;
910 StringRef OrigDIVerifyBugsReportFilePath
;
911 DebugifyStatsMap
*StatsMap
;
912 DebugInfoPerPass
*DebugInfoBeforePass
;
913 enum DebugifyMode Mode
;
917 /// FunctionPass for checking debug info inserted by -debugify-function, used
918 /// with the legacy module pass manager.
919 struct CheckDebugifyFunctionPass
: public FunctionPass
{
920 bool runOnFunction(Function
&F
) override
{
921 bool NewDebugMode
= F
.IsNewDbgInfoFormat
;
923 F
.convertFromNewDbgValues();
925 Module
&M
= *F
.getParent();
926 auto FuncIt
= F
.getIterator();
928 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
929 Result
= checkDebugifyMetadata(M
, make_range(FuncIt
, std::next(FuncIt
)),
930 NameOfWrappedPass
, "CheckFunctionDebugify",
933 Result
= checkDebugInfoMetadata(
934 M
, make_range(FuncIt
, std::next(FuncIt
)), *DebugInfoBeforePass
,
935 "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass
,
936 OrigDIVerifyBugsReportFilePath
);
939 F
.convertToNewDbgValues();
943 CheckDebugifyFunctionPass(
944 bool Strip
= false, StringRef NameOfWrappedPass
= "",
945 DebugifyStatsMap
*StatsMap
= nullptr,
946 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
947 DebugInfoPerPass
*DebugInfoBeforePass
= nullptr,
948 StringRef OrigDIVerifyBugsReportFilePath
= "")
949 : FunctionPass(ID
), NameOfWrappedPass(NameOfWrappedPass
),
950 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath
),
951 StatsMap(StatsMap
), DebugInfoBeforePass(DebugInfoBeforePass
), Mode(Mode
),
954 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
955 AU
.setPreservesAll();
958 static char ID
; // Pass identification.
961 StringRef NameOfWrappedPass
;
962 StringRef OrigDIVerifyBugsReportFilePath
;
963 DebugifyStatsMap
*StatsMap
;
964 DebugInfoPerPass
*DebugInfoBeforePass
;
965 enum DebugifyMode Mode
;
969 } // end anonymous namespace
971 void llvm::exportDebugifyStats(StringRef Path
, const DebugifyStatsMap
&Map
) {
973 raw_fd_ostream OS
{Path
, EC
};
975 errs() << "Could not open file: " << EC
.message() << ", " << Path
<< '\n';
979 OS
<< "Pass Name" << ',' << "# of missing debug values" << ','
980 << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
981 << "Missing/Expected location ratio" << '\n';
982 for (const auto &Entry
: Map
) {
983 StringRef Pass
= Entry
.first
;
984 DebugifyStatistics Stats
= Entry
.second
;
986 OS
<< Pass
<< ',' << Stats
.NumDbgValuesMissing
<< ','
987 << Stats
.NumDbgLocsMissing
<< ',' << Stats
.getMissingValueRatio() << ','
988 << Stats
.getEmptyLocationRatio() << '\n';
992 ModulePass
*createDebugifyModulePass(enum DebugifyMode Mode
,
993 llvm::StringRef NameOfWrappedPass
,
994 DebugInfoPerPass
*DebugInfoBeforePass
) {
995 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
996 return new DebugifyModulePass();
997 assert(Mode
== DebugifyMode::OriginalDebugInfo
&& "Must be original mode");
998 return new DebugifyModulePass(Mode
, NameOfWrappedPass
, DebugInfoBeforePass
);
1002 createDebugifyFunctionPass(enum DebugifyMode Mode
,
1003 llvm::StringRef NameOfWrappedPass
,
1004 DebugInfoPerPass
*DebugInfoBeforePass
) {
1005 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
1006 return new DebugifyFunctionPass();
1007 assert(Mode
== DebugifyMode::OriginalDebugInfo
&& "Must be original mode");
1008 return new DebugifyFunctionPass(Mode
, NameOfWrappedPass
, DebugInfoBeforePass
);
1011 PreservedAnalyses
NewPMDebugifyPass::run(Module
&M
, ModuleAnalysisManager
&) {
1012 bool NewDebugMode
= M
.IsNewDbgInfoFormat
;
1014 M
.convertFromNewDbgValues();
1016 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
1017 applyDebugifyMetadata(M
, M
.functions(),
1018 "ModuleDebugify: ", /*ApplyToMF*/ nullptr);
1020 collectDebugInfoMetadata(M
, M
.functions(), *DebugInfoBeforePass
,
1021 "ModuleDebugify (original debuginfo)",
1025 M
.convertToNewDbgValues();
1027 PreservedAnalyses PA
;
1028 PA
.preserveSet
<CFGAnalyses
>();
1032 ModulePass
*createCheckDebugifyModulePass(
1033 bool Strip
, StringRef NameOfWrappedPass
, DebugifyStatsMap
*StatsMap
,
1034 enum DebugifyMode Mode
, DebugInfoPerPass
*DebugInfoBeforePass
,
1035 StringRef OrigDIVerifyBugsReportFilePath
) {
1036 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
1037 return new CheckDebugifyModulePass(Strip
, NameOfWrappedPass
, StatsMap
);
1038 assert(Mode
== DebugifyMode::OriginalDebugInfo
&& "Must be original mode");
1039 return new CheckDebugifyModulePass(false, NameOfWrappedPass
, nullptr, Mode
,
1040 DebugInfoBeforePass
,
1041 OrigDIVerifyBugsReportFilePath
);
1044 FunctionPass
*createCheckDebugifyFunctionPass(
1045 bool Strip
, StringRef NameOfWrappedPass
, DebugifyStatsMap
*StatsMap
,
1046 enum DebugifyMode Mode
, DebugInfoPerPass
*DebugInfoBeforePass
,
1047 StringRef OrigDIVerifyBugsReportFilePath
) {
1048 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
1049 return new CheckDebugifyFunctionPass(Strip
, NameOfWrappedPass
, StatsMap
);
1050 assert(Mode
== DebugifyMode::OriginalDebugInfo
&& "Must be original mode");
1051 return new CheckDebugifyFunctionPass(false, NameOfWrappedPass
, nullptr, Mode
,
1052 DebugInfoBeforePass
,
1053 OrigDIVerifyBugsReportFilePath
);
1056 PreservedAnalyses
NewPMCheckDebugifyPass::run(Module
&M
,
1057 ModuleAnalysisManager
&) {
1058 bool NewDebugMode
= M
.IsNewDbgInfoFormat
;
1060 M
.convertFromNewDbgValues();
1062 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
1063 checkDebugifyMetadata(M
, M
.functions(), NameOfWrappedPass
,
1064 "CheckModuleDebugify", Strip
, StatsMap
);
1066 checkDebugInfoMetadata(
1067 M
, M
.functions(), *DebugInfoBeforePass
,
1068 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass
,
1069 OrigDIVerifyBugsReportFilePath
);
1072 M
.convertToNewDbgValues();
1074 return PreservedAnalyses::all();
1077 static bool isIgnoredPass(StringRef PassID
) {
1078 return isSpecialPass(PassID
, {"PassManager", "PassAdaptor",
1079 "AnalysisManagerProxy", "PrintFunctionPass",
1080 "PrintModulePass", "BitcodeWriterPass",
1081 "ThinLTOBitcodeWriterPass", "VerifierPass"});
1084 void DebugifyEachInstrumentation::registerCallbacks(
1085 PassInstrumentationCallbacks
&PIC
, ModuleAnalysisManager
&MAM
) {
1086 PIC
.registerBeforeNonSkippedPassCallback([this, &MAM
](StringRef P
, Any IR
) {
1087 if (isIgnoredPass(P
))
1089 PreservedAnalyses PA
;
1090 PA
.preserveSet
<CFGAnalyses
>();
1091 if (const auto **CF
= llvm::any_cast
<const Function
*>(&IR
)) {
1092 Function
&F
= *const_cast<Function
*>(*CF
);
1093 applyDebugify(F
, Mode
, DebugInfoBeforePass
, P
);
1094 MAM
.getResult
<FunctionAnalysisManagerModuleProxy
>(*F
.getParent())
1097 } else if (const auto **CM
= llvm::any_cast
<const Module
*>(&IR
)) {
1098 Module
&M
= *const_cast<Module
*>(*CM
);
1099 applyDebugify(M
, Mode
, DebugInfoBeforePass
, P
);
1100 MAM
.invalidate(M
, PA
);
1103 PIC
.registerAfterPassCallback(
1104 [this, &MAM
](StringRef P
, Any IR
, const PreservedAnalyses
&PassPA
) {
1105 if (isIgnoredPass(P
))
1107 PreservedAnalyses PA
;
1108 PA
.preserveSet
<CFGAnalyses
>();
1109 if (const auto **CF
= llvm::any_cast
<const Function
*>(&IR
)) {
1110 auto &F
= *const_cast<Function
*>(*CF
);
1111 Module
&M
= *F
.getParent();
1112 auto It
= F
.getIterator();
1113 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
1114 checkDebugifyMetadata(M
, make_range(It
, std::next(It
)), P
,
1115 "CheckFunctionDebugify", /*Strip=*/true,
1118 checkDebugInfoMetadata(M
, make_range(It
, std::next(It
)),
1119 *DebugInfoBeforePass
,
1120 "CheckModuleDebugify (original debuginfo)",
1121 P
, OrigDIVerifyBugsReportFilePath
);
1122 MAM
.getResult
<FunctionAnalysisManagerModuleProxy
>(*F
.getParent())
1125 } else if (const auto **CM
= llvm::any_cast
<const Module
*>(&IR
)) {
1126 Module
&M
= *const_cast<Module
*>(*CM
);
1127 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
1128 checkDebugifyMetadata(M
, M
.functions(), P
, "CheckModuleDebugify",
1129 /*Strip=*/true, DIStatsMap
);
1131 checkDebugInfoMetadata(M
, M
.functions(), *DebugInfoBeforePass
,
1132 "CheckModuleDebugify (original debuginfo)",
1133 P
, OrigDIVerifyBugsReportFilePath
);
1134 MAM
.invalidate(M
, PA
);
1139 char DebugifyModulePass::ID
= 0;
1140 static RegisterPass
<DebugifyModulePass
> DM("debugify",
1141 "Attach debug info to everything");
1143 char CheckDebugifyModulePass::ID
= 0;
1144 static RegisterPass
<CheckDebugifyModulePass
>
1145 CDM("check-debugify", "Check debug info from -debugify");
1147 char DebugifyFunctionPass::ID
= 0;
1148 static RegisterPass
<DebugifyFunctionPass
> DF("debugify-function",
1149 "Attach debug info to a function");
1151 char CheckDebugifyFunctionPass::ID
= 0;
1152 static RegisterPass
<CheckDebugifyFunctionPass
>
1153 CDF("check-debugify-function", "Check debug info from -debugify-function");