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"
31 #define DEBUG_TYPE "debugify"
37 cl::opt
<bool> Quiet("debugify-quiet",
38 cl::desc("Suppress verbose debugify output"));
45 // Used for the synthetic mode only.
46 cl::opt
<Level
> DebugifyLevel(
47 "debugify-level", cl::desc("Kind of debug info to add"),
48 cl::values(clEnumValN(Level::Locations
, "locations", "Locations only"),
49 clEnumValN(Level::LocationsAndVariables
, "location+variables",
50 "Locations and Variables")),
51 cl::init(Level::LocationsAndVariables
));
53 raw_ostream
&dbg() { return Quiet
? nulls() : errs(); }
55 uint64_t getAllocSizeInBits(Module
&M
, Type
*Ty
) {
56 return Ty
->isSized() ? M
.getDataLayout().getTypeAllocSizeInBits(Ty
) : 0;
59 bool isFunctionSkipped(Function
&F
) {
60 return F
.isDeclaration() || !F
.hasExactDefinition();
63 /// Find the basic block's terminating instruction.
65 /// Special care is needed to handle musttail and deopt calls, as these behave
66 /// like (but are in fact not) terminators.
67 Instruction
*findTerminatingInstruction(BasicBlock
&BB
) {
68 if (auto *I
= BB
.getTerminatingMustTailCall())
70 if (auto *I
= BB
.getTerminatingDeoptimizeCall())
72 return BB
.getTerminator();
74 } // end anonymous namespace
76 bool llvm::applyDebugifyMetadata(
77 Module
&M
, iterator_range
<Module::iterator
> Functions
, StringRef Banner
,
78 std::function
<bool(DIBuilder
&DIB
, Function
&F
)> ApplyToMF
) {
79 // Skip modules with debug info.
80 if (M
.getNamedMetadata("llvm.dbg.cu")) {
81 dbg() << Banner
<< "Skipping module with debug info\n";
86 LLVMContext
&Ctx
= M
.getContext();
87 auto *Int32Ty
= Type::getInt32Ty(Ctx
);
89 // Get a DIType which corresponds to Ty.
90 DenseMap
<uint64_t, DIType
*> TypeCache
;
91 auto getCachedDIType
= [&](Type
*Ty
) -> DIType
* {
92 uint64_t Size
= getAllocSizeInBits(M
, Ty
);
93 DIType
*&DTy
= TypeCache
[Size
];
95 std::string Name
= "ty" + utostr(Size
);
96 DTy
= DIB
.createBasicType(Name
, Size
, dwarf::DW_ATE_unsigned
);
101 unsigned NextLine
= 1;
102 unsigned NextVar
= 1;
103 auto File
= DIB
.createFile(M
.getName(), "/");
104 auto CU
= DIB
.createCompileUnit(dwarf::DW_LANG_C
, File
, "debugify",
105 /*isOptimized=*/true, "", 0);
107 // Visit each instruction.
108 for (Function
&F
: Functions
) {
109 if (isFunctionSkipped(F
))
112 bool InsertedDbgVal
= false;
113 auto SPType
= DIB
.createSubroutineType(DIB
.getOrCreateTypeArray(None
));
114 DISubprogram::DISPFlags SPFlags
=
115 DISubprogram::SPFlagDefinition
| DISubprogram::SPFlagOptimized
;
116 if (F
.hasPrivateLinkage() || F
.hasInternalLinkage())
117 SPFlags
|= DISubprogram::SPFlagLocalToUnit
;
118 auto SP
= DIB
.createFunction(CU
, F
.getName(), F
.getName(), File
, NextLine
,
119 SPType
, NextLine
, DINode::FlagZero
, SPFlags
);
122 // Helper that inserts a dbg.value before \p InsertBefore, copying the
123 // location (and possibly the type, if it's non-void) from \p TemplateInst.
124 auto insertDbgVal
= [&](Instruction
&TemplateInst
,
125 Instruction
*InsertBefore
) {
126 std::string Name
= utostr(NextVar
++);
127 Value
*V
= &TemplateInst
;
128 if (TemplateInst
.getType()->isVoidTy())
129 V
= ConstantInt::get(Int32Ty
, 0);
130 const DILocation
*Loc
= TemplateInst
.getDebugLoc().get();
131 auto LocalVar
= DIB
.createAutoVariable(SP
, Name
, File
, Loc
->getLine(),
132 getCachedDIType(V
->getType()),
133 /*AlwaysPreserve=*/true);
134 DIB
.insertDbgValueIntrinsic(V
, LocalVar
, DIB
.createExpression(), Loc
,
138 for (BasicBlock
&BB
: F
) {
139 // Attach debug locations.
140 for (Instruction
&I
: BB
)
141 I
.setDebugLoc(DILocation::get(Ctx
, NextLine
++, 1, SP
));
143 if (DebugifyLevel
< Level::LocationsAndVariables
)
146 // Inserting debug values into EH pads can break IR invariants.
150 // Find the terminating instruction, after which no debug values are
152 Instruction
*LastInst
= findTerminatingInstruction(BB
);
153 assert(LastInst
&& "Expected basic block with a terminator");
155 // Maintain an insertion point which can't be invalidated when updates
157 BasicBlock::iterator InsertPt
= BB
.getFirstInsertionPt();
158 assert(InsertPt
!= BB
.end() && "Expected to find an insertion point");
159 Instruction
*InsertBefore
= &*InsertPt
;
161 // Attach debug values.
162 for (Instruction
*I
= &*BB
.begin(); I
!= LastInst
; I
= I
->getNextNode()) {
163 // Skip void-valued instructions.
164 if (I
->getType()->isVoidTy())
167 // Phis and EH pads must be grouped at the beginning of the block.
168 // Only advance the insertion point when we finish visiting these.
169 if (!isa
<PHINode
>(I
) && !I
->isEHPad())
170 InsertBefore
= I
->getNextNode();
172 insertDbgVal(*I
, InsertBefore
);
173 InsertedDbgVal
= true;
176 // Make sure we emit at least one dbg.value, otherwise MachineDebugify may
177 // not have anything to work with as it goes about inserting DBG_VALUEs.
178 // (It's common for MIR tests to be written containing skeletal IR with
179 // empty functions -- we're still interested in debugifying the MIR within
180 // those tests, and this helps with that.)
181 if (DebugifyLevel
== Level::LocationsAndVariables
&& !InsertedDbgVal
) {
182 auto *Term
= findTerminatingInstruction(F
.getEntryBlock());
183 insertDbgVal(*Term
, Term
);
187 DIB
.finalizeSubprogram(SP
);
191 // Track the number of distinct lines and variables.
192 NamedMDNode
*NMD
= M
.getOrInsertNamedMetadata("llvm.debugify");
193 auto addDebugifyOperand
= [&](unsigned N
) {
194 NMD
->addOperand(MDNode::get(
195 Ctx
, ValueAsMetadata::getConstant(ConstantInt::get(Int32Ty
, N
))));
197 addDebugifyOperand(NextLine
- 1); // Original number of lines.
198 addDebugifyOperand(NextVar
- 1); // Original number of variables.
199 assert(NMD
->getNumOperands() == 2 &&
200 "llvm.debugify should have exactly 2 operands!");
202 // Claim that this synthetic debug info is valid.
203 StringRef DIVersionKey
= "Debug Info Version";
204 if (!M
.getModuleFlag(DIVersionKey
))
205 M
.addModuleFlag(Module::Warning
, DIVersionKey
, DEBUG_METADATA_VERSION
);
211 applyDebugify(Function
&F
,
212 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
213 DebugInfoPerPassMap
*DIPreservationMap
= nullptr,
214 StringRef NameOfWrappedPass
= "") {
215 Module
&M
= *F
.getParent();
216 auto FuncIt
= F
.getIterator();
217 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
218 return applyDebugifyMetadata(M
, make_range(FuncIt
, std::next(FuncIt
)),
219 "FunctionDebugify: ", /*ApplyToMF*/ nullptr);
220 assert(DIPreservationMap
);
221 return collectDebugInfoMetadata(M
, M
.functions(), *DIPreservationMap
,
222 "FunctionDebugify (original debuginfo)",
227 applyDebugify(Module
&M
,
228 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
229 DebugInfoPerPassMap
*DIPreservationMap
= nullptr,
230 StringRef NameOfWrappedPass
= "") {
231 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
232 return applyDebugifyMetadata(M
, M
.functions(),
233 "ModuleDebugify: ", /*ApplyToMF*/ nullptr);
234 return collectDebugInfoMetadata(M
, M
.functions(), *DIPreservationMap
,
235 "ModuleDebugify (original debuginfo)",
239 bool llvm::stripDebugifyMetadata(Module
&M
) {
240 bool Changed
= false;
242 // Remove the llvm.debugify module-level named metadata.
243 NamedMDNode
*DebugifyMD
= M
.getNamedMetadata("llvm.debugify");
245 M
.eraseNamedMetadata(DebugifyMD
);
249 // Strip out all debug intrinsics and supporting metadata (subprograms, types,
251 Changed
|= StripDebugInfo(M
);
253 // Strip out the dead dbg.value prototype.
254 Function
*DbgValF
= M
.getFunction("llvm.dbg.value");
256 assert(DbgValF
->isDeclaration() && DbgValF
->use_empty() &&
257 "Not all debug info stripped?");
258 DbgValF
->eraseFromParent();
262 // Strip out the module-level Debug Info Version metadata.
263 // FIXME: There must be an easier way to remove an operand from a NamedMDNode.
264 NamedMDNode
*NMD
= M
.getModuleFlagsMetadata();
267 SmallVector
<MDNode
*, 4> Flags(NMD
->operands());
268 NMD
->clearOperands();
269 for (MDNode
*Flag
: Flags
) {
270 MDString
*Key
= dyn_cast_or_null
<MDString
>(Flag
->getOperand(1));
271 if (Key
->getString() == "Debug Info Version") {
275 NMD
->addOperand(Flag
);
277 // If we left it empty we might as well remove it.
278 if (NMD
->getNumOperands() == 0)
279 NMD
->eraseFromParent();
284 bool llvm::collectDebugInfoMetadata(Module
&M
,
285 iterator_range
<Module::iterator
> Functions
,
286 DebugInfoPerPassMap
&DIPreservationMap
,
288 StringRef NameOfWrappedPass
) {
289 LLVM_DEBUG(dbgs() << Banner
<< ": (before) " << NameOfWrappedPass
<< '\n');
291 // Clear the map with the debug info before every single pass.
292 DIPreservationMap
.clear();
294 if (!M
.getNamedMetadata("llvm.dbg.cu")) {
295 dbg() << Banner
<< ": Skipping module without debug info\n";
299 // Visit each instruction.
300 for (Function
&F
: Functions
) {
301 if (isFunctionSkipped(F
))
304 // Collect the DISubprogram.
305 auto *SP
= F
.getSubprogram();
306 DIPreservationMap
[NameOfWrappedPass
].DIFunctions
.insert({F
.getName(), SP
});
308 LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP
<< '\n');
309 for (const DINode
*DN
: SP
->getRetainedNodes()) {
310 if (const auto *DV
= dyn_cast
<DILocalVariable
>(DN
)) {
311 DIPreservationMap
[NameOfWrappedPass
].DIVariables
[DV
] = 0;
316 for (BasicBlock
&BB
: F
) {
317 // Collect debug locations (!dbg) and debug variable intrinsics.
318 for (Instruction
&I
: BB
) {
323 // Collect dbg.values and dbg.declares.
324 if (auto *DVI
= dyn_cast
<DbgVariableIntrinsic
>(&I
)) {
327 // Skip inlined variables.
328 if (I
.getDebugLoc().getInlinedAt())
330 // Skip undef values.
334 auto *Var
= DVI
->getVariable();
335 DIPreservationMap
[NameOfWrappedPass
].DIVariables
[Var
]++;
339 // Skip debug instructions other than dbg.value and dbg.declare.
340 if (isa
<DbgInfoIntrinsic
>(&I
))
343 LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I
<< '\n');
344 DIPreservationMap
[NameOfWrappedPass
].InstToDelete
.insert({&I
, &I
});
346 const DILocation
*Loc
= I
.getDebugLoc().get();
347 bool HasLoc
= Loc
!= nullptr;
348 DIPreservationMap
[NameOfWrappedPass
].DILocations
.insert({&I
, HasLoc
});
356 // This checks the preservation of original debug info attached to functions.
357 static bool checkFunctions(const DebugFnMap
&DIFunctionsBefore
,
358 const DebugFnMap
&DIFunctionsAfter
,
359 StringRef NameOfWrappedPass
,
360 StringRef FileNameFromCU
, bool ShouldWriteIntoJSON
,
361 llvm::json::Array
&Bugs
) {
362 bool Preserved
= true;
363 for (const auto &F
: DIFunctionsAfter
) {
366 auto SPIt
= DIFunctionsBefore
.find(F
.first
);
367 if (SPIt
== DIFunctionsBefore
.end()) {
368 if (ShouldWriteIntoJSON
)
369 Bugs
.push_back(llvm::json::Object({{"metadata", "DISubprogram"},
371 {"action", "not-generate"}}));
373 dbg() << "ERROR: " << NameOfWrappedPass
374 << " did not generate DISubprogram for " << F
.first
<< " from "
375 << FileNameFromCU
<< '\n';
378 auto SP
= SPIt
->second
;
381 // If the function had the SP attached before the pass, consider it as
383 if (ShouldWriteIntoJSON
)
384 Bugs
.push_back(llvm::json::Object({{"metadata", "DISubprogram"},
386 {"action", "drop"}}));
388 dbg() << "ERROR: " << NameOfWrappedPass
<< " dropped DISubprogram of "
389 << F
.first
<< " from " << FileNameFromCU
<< '\n';
397 // This checks the preservation of the original debug info attached to
399 static bool checkInstructions(const DebugInstMap
&DILocsBefore
,
400 const DebugInstMap
&DILocsAfter
,
401 const WeakInstValueMap
&InstToDelete
,
402 StringRef NameOfWrappedPass
,
403 StringRef FileNameFromCU
,
404 bool ShouldWriteIntoJSON
,
405 llvm::json::Array
&Bugs
) {
406 bool Preserved
= true;
407 for (const auto &L
: DILocsAfter
) {
410 auto Instr
= L
.first
;
412 // In order to avoid pointer reuse/recycling, skip the values that might
413 // have been deleted during a pass.
414 auto WeakInstrPtr
= InstToDelete
.find(Instr
);
415 if (WeakInstrPtr
!= InstToDelete
.end() && !WeakInstrPtr
->second
)
418 auto FnName
= Instr
->getFunction()->getName();
419 auto BB
= Instr
->getParent();
420 auto BBName
= BB
->hasName() ? BB
->getName() : "no-name";
421 auto InstName
= Instruction::getOpcodeName(Instr
->getOpcode());
423 auto InstrIt
= DILocsBefore
.find(Instr
);
424 if (InstrIt
== DILocsBefore
.end()) {
425 if (ShouldWriteIntoJSON
)
426 Bugs
.push_back(llvm::json::Object({{"metadata", "DILocation"},
427 {"fn-name", FnName
.str()},
428 {"bb-name", BBName
.str()},
430 {"action", "not-generate"}}));
432 dbg() << "WARNING: " << NameOfWrappedPass
433 << " did not generate DILocation for " << *Instr
434 << " (BB: " << BBName
<< ", Fn: " << FnName
435 << ", File: " << FileNameFromCU
<< ")\n";
438 if (!InstrIt
->second
)
440 // If the instr had the !dbg attached before the pass, consider it as
441 // a debug info issue.
442 if (ShouldWriteIntoJSON
)
443 Bugs
.push_back(llvm::json::Object({{"metadata", "DILocation"},
444 {"fn-name", FnName
.str()},
445 {"bb-name", BBName
.str()},
447 {"action", "drop"}}));
449 dbg() << "WARNING: " << NameOfWrappedPass
<< " dropped DILocation of "
450 << *Instr
<< " (BB: " << BBName
<< ", Fn: " << FnName
451 << ", File: " << FileNameFromCU
<< ")\n";
459 // This checks the preservation of original debug variable intrinsics.
460 static bool checkVars(const DebugVarMap
&DIFunctionsBefore
,
461 const DebugVarMap
&DIFunctionsAfter
,
462 StringRef NameOfWrappedPass
, StringRef FileNameFromCU
,
463 bool ShouldWriteIntoJSON
, llvm::json::Array
&Bugs
) {
464 bool Preserved
= true;
465 for (const auto &V
: DIFunctionsBefore
) {
466 auto VarIt
= DIFunctionsAfter
.find(V
.first
);
467 if (VarIt
== DIFunctionsAfter
.end())
470 unsigned NumOfDbgValsAfter
= VarIt
->second
;
472 if (V
.second
> NumOfDbgValsAfter
) {
473 if (ShouldWriteIntoJSON
)
474 Bugs
.push_back(llvm::json::Object(
475 {{"metadata", "dbg-var-intrinsic"},
476 {"name", V
.first
->getName()},
477 {"fn-name", V
.first
->getScope()->getSubprogram()->getName()},
478 {"action", "drop"}}));
480 dbg() << "WARNING: " << NameOfWrappedPass
481 << " drops dbg.value()/dbg.declare() for " << V
.first
->getName()
483 << "function " << V
.first
->getScope()->getSubprogram()->getName()
484 << " (file " << FileNameFromCU
<< ")\n";
492 // Write the json data into the specifed file.
493 static void writeJSON(StringRef OrigDIVerifyBugsReportFilePath
,
494 StringRef FileNameFromCU
, StringRef NameOfWrappedPass
,
495 llvm::json::Array
&Bugs
) {
497 raw_fd_ostream OS_FILE
{OrigDIVerifyBugsReportFilePath
, EC
,
498 sys::fs::OF_Append
| sys::fs::OF_TextWithCRLF
};
500 errs() << "Could not open file: " << EC
.message() << ", "
501 << OrigDIVerifyBugsReportFilePath
<< '\n';
505 OS_FILE
<< "{\"file\":\"" << FileNameFromCU
<< "\", ";
507 StringRef PassName
= NameOfWrappedPass
!= "" ? NameOfWrappedPass
: "no-name";
508 OS_FILE
<< "\"pass\":\"" << PassName
<< "\", ";
510 llvm::json::Value BugsToPrint
{std::move(Bugs
)};
511 OS_FILE
<< "\"bugs\": " << BugsToPrint
;
516 bool llvm::checkDebugInfoMetadata(Module
&M
,
517 iterator_range
<Module::iterator
> Functions
,
518 DebugInfoPerPassMap
&DIPreservationMap
,
519 StringRef Banner
, StringRef NameOfWrappedPass
,
520 StringRef OrigDIVerifyBugsReportFilePath
) {
521 LLVM_DEBUG(dbgs() << Banner
<< ": (after) " << NameOfWrappedPass
<< '\n');
523 if (!M
.getNamedMetadata("llvm.dbg.cu")) {
524 dbg() << Banner
<< ": Skipping module without debug info\n";
528 // Map the debug info holding DIs after a pass.
529 DebugInfoPerPassMap DIPreservationAfter
;
531 // Visit each instruction.
532 for (Function
&F
: Functions
) {
533 if (isFunctionSkipped(F
))
536 // TODO: Collect metadata other than DISubprograms.
537 // Collect the DISubprogram.
538 auto *SP
= F
.getSubprogram();
539 DIPreservationAfter
[NameOfWrappedPass
].DIFunctions
.insert(
543 LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP
<< '\n');
544 for (const DINode
*DN
: SP
->getRetainedNodes()) {
545 if (const auto *DV
= dyn_cast
<DILocalVariable
>(DN
)) {
546 DIPreservationAfter
[NameOfWrappedPass
].DIVariables
[DV
] = 0;
551 for (BasicBlock
&BB
: F
) {
552 // Collect debug locations (!dbg) and debug variable intrinsics.
553 for (Instruction
&I
: BB
) {
558 // Collect dbg.values and dbg.declares.
559 if (auto *DVI
= dyn_cast
<DbgVariableIntrinsic
>(&I
)) {
562 // Skip inlined variables.
563 if (I
.getDebugLoc().getInlinedAt())
565 // Skip undef values.
569 auto *Var
= DVI
->getVariable();
570 DIPreservationAfter
[NameOfWrappedPass
].DIVariables
[Var
]++;
574 // Skip debug instructions other than dbg.value and dbg.declare.
575 if (isa
<DbgInfoIntrinsic
>(&I
))
578 LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I
<< '\n');
580 const DILocation
*Loc
= I
.getDebugLoc().get();
581 bool HasLoc
= Loc
!= nullptr;
583 DIPreservationAfter
[NameOfWrappedPass
].DILocations
.insert({&I
, HasLoc
});
588 // TODO: The name of the module could be read better?
589 StringRef FileNameFromCU
=
590 (cast
<DICompileUnit
>(M
.getNamedMetadata("llvm.dbg.cu")->getOperand(0)))
593 auto DIFunctionsBefore
= DIPreservationMap
[NameOfWrappedPass
].DIFunctions
;
594 auto DIFunctionsAfter
= DIPreservationAfter
[NameOfWrappedPass
].DIFunctions
;
596 auto DILocsBefore
= DIPreservationMap
[NameOfWrappedPass
].DILocations
;
597 auto DILocsAfter
= DIPreservationAfter
[NameOfWrappedPass
].DILocations
;
599 auto InstToDelete
= DIPreservationAfter
[NameOfWrappedPass
].InstToDelete
;
601 auto DIVarsBefore
= DIPreservationMap
[NameOfWrappedPass
].DIVariables
;
602 auto DIVarsAfter
= DIPreservationAfter
[NameOfWrappedPass
].DIVariables
;
604 bool ShouldWriteIntoJSON
= !OrigDIVerifyBugsReportFilePath
.empty();
605 llvm::json::Array Bugs
;
608 checkFunctions(DIFunctionsBefore
, DIFunctionsAfter
, NameOfWrappedPass
,
609 FileNameFromCU
, ShouldWriteIntoJSON
, Bugs
);
610 bool ResultForInsts
= checkInstructions(
611 DILocsBefore
, DILocsAfter
, InstToDelete
, NameOfWrappedPass
,
612 FileNameFromCU
, ShouldWriteIntoJSON
, Bugs
);
614 bool ResultForVars
= checkVars(DIVarsBefore
, DIVarsAfter
, NameOfWrappedPass
,
615 FileNameFromCU
, ShouldWriteIntoJSON
, Bugs
);
617 bool Result
= ResultForFunc
&& ResultForInsts
&& ResultForVars
;
619 StringRef ResultBanner
= NameOfWrappedPass
!= "" ? NameOfWrappedPass
: Banner
;
620 if (ShouldWriteIntoJSON
&& !Bugs
.empty())
621 writeJSON(OrigDIVerifyBugsReportFilePath
, FileNameFromCU
, NameOfWrappedPass
,
625 dbg() << ResultBanner
<< ": PASS\n";
627 dbg() << ResultBanner
<< ": FAIL\n";
629 LLVM_DEBUG(dbgs() << "\n\n");
634 /// Return true if a mis-sized diagnostic is issued for \p DVI.
635 bool diagnoseMisSizedDbgValue(Module
&M
, DbgValueInst
*DVI
) {
636 // The size of a dbg.value's value operand should match the size of the
637 // variable it corresponds to.
639 // TODO: This, along with a check for non-null value operands, should be
640 // promoted to verifier failures.
642 // For now, don't try to interpret anything more complicated than an empty
643 // DIExpression. Eventually we should try to handle OP_deref and fragments.
644 if (DVI
->getExpression()->getNumElements())
647 Value
*V
= DVI
->getVariableLocationOp(0);
651 Type
*Ty
= V
->getType();
652 uint64_t ValueOperandSize
= getAllocSizeInBits(M
, Ty
);
653 Optional
<uint64_t> DbgVarSize
= DVI
->getFragmentSizeInBits();
654 if (!ValueOperandSize
|| !DbgVarSize
)
657 bool HasBadSize
= false;
658 if (Ty
->isIntegerTy()) {
659 auto Signedness
= DVI
->getVariable()->getSignedness();
660 if (Signedness
&& *Signedness
== DIBasicType::Signedness::Signed
)
661 HasBadSize
= ValueOperandSize
< *DbgVarSize
;
663 HasBadSize
= ValueOperandSize
!= *DbgVarSize
;
667 dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
668 << ", but its variable has size " << *DbgVarSize
<< ": ";
675 bool checkDebugifyMetadata(Module
&M
,
676 iterator_range
<Module::iterator
> Functions
,
677 StringRef NameOfWrappedPass
, StringRef Banner
,
678 bool Strip
, DebugifyStatsMap
*StatsMap
) {
679 // Skip modules without debugify metadata.
680 NamedMDNode
*NMD
= M
.getNamedMetadata("llvm.debugify");
682 dbg() << Banner
<< ": Skipping module without debugify metadata\n";
686 auto getDebugifyOperand
= [&](unsigned Idx
) -> unsigned {
687 return mdconst::extract
<ConstantInt
>(NMD
->getOperand(Idx
)->getOperand(0))
690 assert(NMD
->getNumOperands() == 2 &&
691 "llvm.debugify should have exactly 2 operands!");
692 unsigned OriginalNumLines
= getDebugifyOperand(0);
693 unsigned OriginalNumVars
= getDebugifyOperand(1);
694 bool HasErrors
= false;
696 // Track debug info loss statistics if able.
697 DebugifyStatistics
*Stats
= nullptr;
698 if (StatsMap
&& !NameOfWrappedPass
.empty())
699 Stats
= &StatsMap
->operator[](NameOfWrappedPass
);
701 BitVector MissingLines
{OriginalNumLines
, true};
702 BitVector MissingVars
{OriginalNumVars
, true};
703 for (Function
&F
: Functions
) {
704 if (isFunctionSkipped(F
))
707 // Find missing lines.
708 for (Instruction
&I
: instructions(F
)) {
709 if (isa
<DbgValueInst
>(&I
))
712 auto DL
= I
.getDebugLoc();
713 if (DL
&& DL
.getLine() != 0) {
714 MissingLines
.reset(DL
.getLine() - 1);
718 if (!isa
<PHINode
>(&I
) && !DL
) {
719 dbg() << "WARNING: Instruction with empty DebugLoc in function ";
720 dbg() << F
.getName() << " --";
726 // Find missing variables and mis-sized debug values.
727 for (Instruction
&I
: instructions(F
)) {
728 auto *DVI
= dyn_cast
<DbgValueInst
>(&I
);
733 (void)to_integer(DVI
->getVariable()->getName(), Var
, 10);
734 assert(Var
<= OriginalNumVars
&& "Unexpected name for DILocalVariable");
735 bool HasBadSize
= diagnoseMisSizedDbgValue(M
, DVI
);
737 MissingVars
.reset(Var
- 1);
738 HasErrors
|= HasBadSize
;
742 // Print the results.
743 for (unsigned Idx
: MissingLines
.set_bits())
744 dbg() << "WARNING: Missing line " << Idx
+ 1 << "\n";
746 for (unsigned Idx
: MissingVars
.set_bits())
747 dbg() << "WARNING: Missing variable " << Idx
+ 1 << "\n";
749 // Update DI loss statistics.
751 Stats
->NumDbgLocsExpected
+= OriginalNumLines
;
752 Stats
->NumDbgLocsMissing
+= MissingLines
.count();
753 Stats
->NumDbgValuesExpected
+= OriginalNumVars
;
754 Stats
->NumDbgValuesMissing
+= MissingVars
.count();
758 if (!NameOfWrappedPass
.empty())
759 dbg() << " [" << NameOfWrappedPass
<< "]";
760 dbg() << ": " << (HasErrors
? "FAIL" : "PASS") << '\n';
762 // Strip debugify metadata if required.
764 return stripDebugifyMetadata(M
);
769 /// ModulePass for attaching synthetic debug info to everything, used with the
770 /// legacy module pass manager.
771 struct DebugifyModulePass
: public ModulePass
{
772 bool runOnModule(Module
&M
) override
{
773 return applyDebugify(M
, Mode
, DIPreservationMap
, NameOfWrappedPass
);
776 DebugifyModulePass(enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
777 StringRef NameOfWrappedPass
= "",
778 DebugInfoPerPassMap
*DIPreservationMap
= nullptr)
779 : ModulePass(ID
), NameOfWrappedPass(NameOfWrappedPass
),
780 DIPreservationMap(DIPreservationMap
), Mode(Mode
) {}
782 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
783 AU
.setPreservesAll();
786 static char ID
; // Pass identification.
789 StringRef NameOfWrappedPass
;
790 DebugInfoPerPassMap
*DIPreservationMap
;
791 enum DebugifyMode Mode
;
794 /// FunctionPass for attaching synthetic debug info to instructions within a
795 /// single function, used with the legacy module pass manager.
796 struct DebugifyFunctionPass
: public FunctionPass
{
797 bool runOnFunction(Function
&F
) override
{
798 return applyDebugify(F
, Mode
, DIPreservationMap
, NameOfWrappedPass
);
801 DebugifyFunctionPass(
802 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
803 StringRef NameOfWrappedPass
= "",
804 DebugInfoPerPassMap
*DIPreservationMap
= nullptr)
805 : FunctionPass(ID
), NameOfWrappedPass(NameOfWrappedPass
),
806 DIPreservationMap(DIPreservationMap
), Mode(Mode
) {}
808 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
809 AU
.setPreservesAll();
812 static char ID
; // Pass identification.
815 StringRef NameOfWrappedPass
;
816 DebugInfoPerPassMap
*DIPreservationMap
;
817 enum DebugifyMode Mode
;
820 /// ModulePass for checking debug info inserted by -debugify, used with the
821 /// legacy module pass manager.
822 struct CheckDebugifyModulePass
: public ModulePass
{
823 bool runOnModule(Module
&M
) override
{
824 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
825 return checkDebugifyMetadata(M
, M
.functions(), NameOfWrappedPass
,
826 "CheckModuleDebugify", Strip
, StatsMap
);
827 return checkDebugInfoMetadata(
828 M
, M
.functions(), *DIPreservationMap
,
829 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass
,
830 OrigDIVerifyBugsReportFilePath
);
833 CheckDebugifyModulePass(
834 bool Strip
= false, StringRef NameOfWrappedPass
= "",
835 DebugifyStatsMap
*StatsMap
= nullptr,
836 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
837 DebugInfoPerPassMap
*DIPreservationMap
= nullptr,
838 StringRef OrigDIVerifyBugsReportFilePath
= "")
839 : ModulePass(ID
), NameOfWrappedPass(NameOfWrappedPass
),
840 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath
),
841 StatsMap(StatsMap
), DIPreservationMap(DIPreservationMap
), Mode(Mode
),
844 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
845 AU
.setPreservesAll();
848 static char ID
; // Pass identification.
851 StringRef NameOfWrappedPass
;
852 StringRef OrigDIVerifyBugsReportFilePath
;
853 DebugifyStatsMap
*StatsMap
;
854 DebugInfoPerPassMap
*DIPreservationMap
;
855 enum DebugifyMode Mode
;
859 /// FunctionPass for checking debug info inserted by -debugify-function, used
860 /// with the legacy module pass manager.
861 struct CheckDebugifyFunctionPass
: public FunctionPass
{
862 bool runOnFunction(Function
&F
) override
{
863 Module
&M
= *F
.getParent();
864 auto FuncIt
= F
.getIterator();
865 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
866 return checkDebugifyMetadata(M
, make_range(FuncIt
, std::next(FuncIt
)),
867 NameOfWrappedPass
, "CheckFunctionDebugify",
869 return checkDebugInfoMetadata(
870 M
, make_range(FuncIt
, std::next(FuncIt
)), *DIPreservationMap
,
871 "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass
,
872 OrigDIVerifyBugsReportFilePath
);
875 CheckDebugifyFunctionPass(
876 bool Strip
= false, StringRef NameOfWrappedPass
= "",
877 DebugifyStatsMap
*StatsMap
= nullptr,
878 enum DebugifyMode Mode
= DebugifyMode::SyntheticDebugInfo
,
879 DebugInfoPerPassMap
*DIPreservationMap
= nullptr,
880 StringRef OrigDIVerifyBugsReportFilePath
= "")
881 : FunctionPass(ID
), NameOfWrappedPass(NameOfWrappedPass
),
882 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath
),
883 StatsMap(StatsMap
), DIPreservationMap(DIPreservationMap
), Mode(Mode
),
886 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
887 AU
.setPreservesAll();
890 static char ID
; // Pass identification.
893 StringRef NameOfWrappedPass
;
894 StringRef OrigDIVerifyBugsReportFilePath
;
895 DebugifyStatsMap
*StatsMap
;
896 DebugInfoPerPassMap
*DIPreservationMap
;
897 enum DebugifyMode Mode
;
901 } // end anonymous namespace
903 void llvm::exportDebugifyStats(StringRef Path
, const DebugifyStatsMap
&Map
) {
905 raw_fd_ostream OS
{Path
, EC
};
907 errs() << "Could not open file: " << EC
.message() << ", " << Path
<< '\n';
911 OS
<< "Pass Name" << ',' << "# of missing debug values" << ','
912 << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
913 << "Missing/Expected location ratio" << '\n';
914 for (const auto &Entry
: Map
) {
915 StringRef Pass
= Entry
.first
;
916 DebugifyStatistics Stats
= Entry
.second
;
918 OS
<< Pass
<< ',' << Stats
.NumDbgValuesMissing
<< ','
919 << Stats
.NumDbgLocsMissing
<< ',' << Stats
.getMissingValueRatio() << ','
920 << Stats
.getEmptyLocationRatio() << '\n';
924 ModulePass
*createDebugifyModulePass(enum DebugifyMode Mode
,
925 llvm::StringRef NameOfWrappedPass
,
926 DebugInfoPerPassMap
*DIPreservationMap
) {
927 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
928 return new DebugifyModulePass();
929 assert(Mode
== DebugifyMode::OriginalDebugInfo
&& "Must be original mode");
930 return new DebugifyModulePass(Mode
, NameOfWrappedPass
, DIPreservationMap
);
934 createDebugifyFunctionPass(enum DebugifyMode Mode
,
935 llvm::StringRef NameOfWrappedPass
,
936 DebugInfoPerPassMap
*DIPreservationMap
) {
937 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
938 return new DebugifyFunctionPass();
939 assert(Mode
== DebugifyMode::OriginalDebugInfo
&& "Must be original mode");
940 return new DebugifyFunctionPass(Mode
, NameOfWrappedPass
, DIPreservationMap
);
943 PreservedAnalyses
NewPMDebugifyPass::run(Module
&M
, ModuleAnalysisManager
&) {
944 applyDebugifyMetadata(M
, M
.functions(),
945 "ModuleDebugify: ", /*ApplyToMF*/ nullptr);
946 return PreservedAnalyses::all();
949 ModulePass
*createCheckDebugifyModulePass(
950 bool Strip
, StringRef NameOfWrappedPass
, DebugifyStatsMap
*StatsMap
,
951 enum DebugifyMode Mode
, DebugInfoPerPassMap
*DIPreservationMap
,
952 StringRef OrigDIVerifyBugsReportFilePath
) {
953 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
954 return new CheckDebugifyModulePass(Strip
, NameOfWrappedPass
, StatsMap
);
955 assert(Mode
== DebugifyMode::OriginalDebugInfo
&& "Must be original mode");
956 return new CheckDebugifyModulePass(false, NameOfWrappedPass
, nullptr, Mode
,
958 OrigDIVerifyBugsReportFilePath
);
961 FunctionPass
*createCheckDebugifyFunctionPass(
962 bool Strip
, StringRef NameOfWrappedPass
, DebugifyStatsMap
*StatsMap
,
963 enum DebugifyMode Mode
, DebugInfoPerPassMap
*DIPreservationMap
,
964 StringRef OrigDIVerifyBugsReportFilePath
) {
965 if (Mode
== DebugifyMode::SyntheticDebugInfo
)
966 return new CheckDebugifyFunctionPass(Strip
, NameOfWrappedPass
, StatsMap
);
967 assert(Mode
== DebugifyMode::OriginalDebugInfo
&& "Must be original mode");
968 return new CheckDebugifyFunctionPass(false, NameOfWrappedPass
, nullptr, Mode
,
970 OrigDIVerifyBugsReportFilePath
);
973 PreservedAnalyses
NewPMCheckDebugifyPass::run(Module
&M
,
974 ModuleAnalysisManager
&) {
975 checkDebugifyMetadata(M
, M
.functions(), "", "CheckModuleDebugify", false,
977 return PreservedAnalyses::all();
980 static bool isIgnoredPass(StringRef PassID
) {
981 return isSpecialPass(PassID
, {"PassManager", "PassAdaptor",
982 "AnalysisManagerProxy", "PrintFunctionPass",
983 "PrintModulePass", "BitcodeWriterPass",
984 "ThinLTOBitcodeWriterPass", "VerifierPass"});
987 void DebugifyEachInstrumentation::registerCallbacks(
988 PassInstrumentationCallbacks
&PIC
) {
989 PIC
.registerBeforeNonSkippedPassCallback([](StringRef P
, Any IR
) {
990 if (isIgnoredPass(P
))
992 if (any_isa
<const Function
*>(IR
))
993 applyDebugify(*const_cast<Function
*>(any_cast
<const Function
*>(IR
)));
994 else if (any_isa
<const Module
*>(IR
))
995 applyDebugify(*const_cast<Module
*>(any_cast
<const Module
*>(IR
)));
997 PIC
.registerAfterPassCallback([this](StringRef P
, Any IR
,
998 const PreservedAnalyses
&PassPA
) {
999 if (isIgnoredPass(P
))
1001 if (any_isa
<const Function
*>(IR
)) {
1002 auto &F
= *const_cast<Function
*>(any_cast
<const Function
*>(IR
));
1003 Module
&M
= *F
.getParent();
1004 auto It
= F
.getIterator();
1005 checkDebugifyMetadata(M
, make_range(It
, std::next(It
)), P
,
1006 "CheckFunctionDebugify", /*Strip=*/true, &StatsMap
);
1007 } else if (any_isa
<const Module
*>(IR
)) {
1008 auto &M
= *const_cast<Module
*>(any_cast
<const Module
*>(IR
));
1009 checkDebugifyMetadata(M
, M
.functions(), P
, "CheckModuleDebugify",
1010 /*Strip=*/true, &StatsMap
);
1015 char DebugifyModulePass::ID
= 0;
1016 static RegisterPass
<DebugifyModulePass
> DM("debugify",
1017 "Attach debug info to everything");
1019 char CheckDebugifyModulePass::ID
= 0;
1020 static RegisterPass
<CheckDebugifyModulePass
>
1021 CDM("check-debugify", "Check debug info from -debugify");
1023 char DebugifyFunctionPass::ID
= 0;
1024 static RegisterPass
<DebugifyFunctionPass
> DF("debugify-function",
1025 "Attach debug info to a function");
1027 char CheckDebugifyFunctionPass::ID
= 0;
1028 static RegisterPass
<CheckDebugifyFunctionPass
>
1029 CDF("check-debugify-function", "Check debug info from -debugify-function");