1 //===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \file This pass attaches synthetic debug info to everything. It can be used
11 /// to create targeted tests for debug info preservation.
13 //===----------------------------------------------------------------------===//
15 #include "PassPrinters.h"
16 #include "llvm/ADT/BitVector.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/IR/BasicBlock.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/DIBuilder.h"
21 #include "llvm/IR/DebugInfo.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/GlobalVariable.h"
24 #include "llvm/IR/InstIterator.h"
25 #include "llvm/IR/Instruction.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/IntrinsicInst.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Pass.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Transforms/IPO.h"
38 bool isFunctionSkipped(Function
&F
) {
39 return F
.isDeclaration() || !F
.hasExactDefinition();
42 bool applyDebugifyMetadata(Module
&M
) {
43 // Skip modules with debug info.
44 if (M
.getNamedMetadata("llvm.dbg.cu")) {
45 errs() << "Debugify: Skipping module with debug info\n";
50 LLVMContext
&Ctx
= M
.getContext();
52 // Get a DIType which corresponds to Ty.
53 DenseMap
<uint64_t, DIType
*> TypeCache
;
54 auto getCachedDIType
= [&](Type
*Ty
) -> DIType
* {
56 Ty
->isSized() ? M
.getDataLayout().getTypeAllocSizeInBits(Ty
) : 0;
57 DIType
*&DTy
= TypeCache
[Size
];
59 std::string Name
= "ty" + utostr(Size
);
60 DTy
= DIB
.createBasicType(Name
, Size
, dwarf::DW_ATE_unsigned
);
65 unsigned NextLine
= 1;
67 auto File
= DIB
.createFile(M
.getName(), "/");
69 DIB
.createCompileUnit(dwarf::DW_LANG_C
, DIB
.createFile(M
.getName(), "/"),
70 "debugify", /*isOptimized=*/true, "", 0);
72 // Visit each instruction.
73 for (Function
&F
: M
) {
74 if (isFunctionSkipped(F
))
77 auto SPType
= DIB
.createSubroutineType(DIB
.getOrCreateTypeArray(None
));
78 bool IsLocalToUnit
= F
.hasPrivateLinkage() || F
.hasInternalLinkage();
80 DIB
.createFunction(CU
, F
.getName(), F
.getName(), File
, NextLine
, SPType
,
81 IsLocalToUnit
, /*isDefinition=*/true, NextLine
,
82 DINode::FlagZero
, /*isOptimized=*/true);
84 for (BasicBlock
&BB
: F
) {
85 // Attach debug locations.
86 for (Instruction
&I
: BB
)
87 I
.setDebugLoc(DILocation::get(Ctx
, NextLine
++, 1, SP
));
89 // Attach debug values.
90 for (Instruction
&I
: BB
) {
91 // Skip void-valued instructions.
92 if (I
.getType()->isVoidTy())
95 // Skip the terminator instruction and any just-inserted intrinsics.
96 if (isa
<TerminatorInst
>(&I
) || isa
<DbgValueInst
>(&I
))
99 std::string Name
= utostr(NextVar
++);
100 const DILocation
*Loc
= I
.getDebugLoc().get();
101 auto LocalVar
= DIB
.createAutoVariable(SP
, Name
, File
, Loc
->getLine(),
102 getCachedDIType(I
.getType()),
103 /*AlwaysPreserve=*/true);
104 DIB
.insertDbgValueIntrinsic(&I
, LocalVar
, DIB
.createExpression(), Loc
,
108 DIB
.finalizeSubprogram(SP
);
112 // Track the number of distinct lines and variables.
113 NamedMDNode
*NMD
= M
.getOrInsertNamedMetadata("llvm.debugify");
114 auto *IntTy
= Type::getInt32Ty(Ctx
);
115 auto addDebugifyOperand
= [&](unsigned N
) {
116 NMD
->addOperand(MDNode::get(
117 Ctx
, ValueAsMetadata::getConstant(ConstantInt::get(IntTy
, N
))));
119 addDebugifyOperand(NextLine
- 1); // Original number of lines.
120 addDebugifyOperand(NextVar
- 1); // Original number of variables.
124 void checkDebugifyMetadata(Module
&M
) {
125 // Skip modules without debugify metadata.
126 NamedMDNode
*NMD
= M
.getNamedMetadata("llvm.debugify");
130 auto getDebugifyOperand
= [&](unsigned Idx
) -> unsigned {
131 return mdconst::extract
<ConstantInt
>(NMD
->getOperand(Idx
)->getOperand(0))
134 unsigned OriginalNumLines
= getDebugifyOperand(0);
135 unsigned OriginalNumVars
= getDebugifyOperand(1);
136 bool HasErrors
= false;
138 // Find missing lines.
139 BitVector MissingLines
{OriginalNumLines
, true};
140 for (Function
&F
: M
) {
141 if (isFunctionSkipped(F
))
144 for (Instruction
&I
: instructions(F
)) {
145 if (isa
<DbgValueInst
>(&I
))
148 auto DL
= I
.getDebugLoc();
150 MissingLines
.reset(DL
.getLine() - 1);
154 outs() << "ERROR: Instruction with empty DebugLoc -- ";
160 for (unsigned Idx
: MissingLines
.set_bits())
161 outs() << "WARNING: Missing line " << Idx
+ 1 << "\n";
163 // Find missing variables.
164 BitVector MissingVars
{OriginalNumVars
, true};
165 for (Function
&F
: M
) {
166 if (isFunctionSkipped(F
))
169 for (Instruction
&I
: instructions(F
)) {
170 auto *DVI
= dyn_cast
<DbgValueInst
>(&I
);
175 (void)to_integer(DVI
->getVariable()->getName(), Var
, 10);
176 assert(Var
<= OriginalNumVars
&& "Unexpected name for DILocalVariable");
177 MissingVars
.reset(Var
- 1);
180 for (unsigned Idx
: MissingVars
.set_bits())
181 outs() << "ERROR: Missing variable " << Idx
+ 1 << "\n";
182 HasErrors
|= MissingVars
.count() > 0;
184 outs() << "CheckDebugify: " << (HasErrors
? "FAIL" : "PASS") << "\n";
187 /// Attach synthetic debug info to everything.
188 struct DebugifyPass
: public ModulePass
{
189 bool runOnModule(Module
&M
) override
{ return applyDebugifyMetadata(M
); }
191 DebugifyPass() : ModulePass(ID
) {}
193 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
194 AU
.setPreservesAll();
197 static char ID
; // Pass identification.
200 /// Check debug info inserted by -debugify for completeness.
201 struct CheckDebugifyPass
: public ModulePass
{
202 bool runOnModule(Module
&M
) override
{
203 checkDebugifyMetadata(M
);
207 CheckDebugifyPass() : ModulePass(ID
) {}
209 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
210 AU
.setPreservesAll();
213 static char ID
; // Pass identification.
216 } // end anonymous namespace
218 ModulePass
*createDebugifyPass() { return new DebugifyPass(); }
220 PreservedAnalyses
NewPMDebugifyPass::run(Module
&M
, ModuleAnalysisManager
&) {
221 applyDebugifyMetadata(M
);
222 return PreservedAnalyses::all();
225 ModulePass
*createCheckDebugifyPass() { return new CheckDebugifyPass(); }
227 PreservedAnalyses
NewPMCheckDebugifyPass::run(Module
&M
,
228 ModuleAnalysisManager
&) {
229 checkDebugifyMetadata(M
);
230 return PreservedAnalyses::all();
233 char DebugifyPass::ID
= 0;
234 static RegisterPass
<DebugifyPass
> X("debugify",
235 "Attach debug info to everything");
237 char CheckDebugifyPass::ID
= 0;
238 static RegisterPass
<CheckDebugifyPass
> Y("check-debugify",
239 "Check debug info from -debugify");