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 "llvm/ADT/BitVector.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/IR/BasicBlock.h"
18 #include "llvm/IR/Constants.h"
19 #include "llvm/IR/DIBuilder.h"
20 #include "llvm/IR/DebugInfo.h"
21 #include "llvm/IR/Function.h"
22 #include "llvm/IR/GlobalVariable.h"
23 #include "llvm/IR/InstIterator.h"
24 #include "llvm/IR/Instruction.h"
25 #include "llvm/IR/Instructions.h"
26 #include "llvm/IR/IntrinsicInst.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/IR/Type.h"
29 #include "llvm/Pass.h"
30 #include "llvm/Support/raw_ostream.h"
31 #include "llvm/Transforms/IPO.h"
37 bool applyDebugifyMetadata(Module &M) {
38 // Skip modules with debug info.
39 if (M.getNamedMetadata("llvm.dbg.cu")) {
40 errs() << "Debugify: Skipping module with debug info\n";
45 LLVMContext &Ctx = M.getContext();
47 // Get a DIType which corresponds to Ty.
48 DenseMap<uint64_t, DIType *> TypeCache;
49 auto getCachedDIType = [&](Type *Ty) -> DIType * {
50 uint64_t Size = M.getDataLayout().getTypeAllocSizeInBits(Ty);
51 DIType *&DTy = TypeCache[Size];
53 std::string Name = "ty" + utostr(Size);
54 DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
59 unsigned NextLine = 1;
61 auto File = DIB.createFile(M.getName(), "/");
63 DIB.createCompileUnit(dwarf::DW_LANG_C, DIB.createFile(M.getName(), "/"),
64 "debugify", /*isOptimized=*/true, "", 0);
66 // Visit each instruction.
67 for (Function &F : M) {
68 if (F.isDeclaration())
71 auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
72 bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
74 DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
75 IsLocalToUnit, F.hasExactDefinition(), NextLine,
76 DINode::FlagZero, /*isOptimized=*/true);
78 for (BasicBlock &BB : F) {
79 // Attach debug locations.
80 for (Instruction &I : BB)
81 I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
83 // Attach debug values.
84 for (Instruction &I : BB) {
85 // Skip void-valued instructions.
86 if (I.getType()->isVoidTy())
89 // Skip the terminator instruction and any just-inserted intrinsics.
90 if (isa<TerminatorInst>(&I) || isa<DbgValueInst>(&I))
93 std::string Name = utostr(NextVar++);
94 const DILocation *Loc = I.getDebugLoc().get();
95 auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
96 getCachedDIType(I.getType()),
97 /*AlwaysPreserve=*/true);
98 DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc,
102 DIB.finalizeSubprogram(SP);
106 // Track the number of distinct lines and variables.
107 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
108 auto *IntTy = Type::getInt32Ty(Ctx);
109 auto addDebugifyOperand = [&](unsigned N) {
110 NMD->addOperand(MDNode::get(
111 Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
113 addDebugifyOperand(NextLine - 1); // Original number of lines.
114 addDebugifyOperand(NextVar - 1); // Original number of variables.
118 void checkDebugifyMetadata(Module &M) {
119 // Skip modules without debugify metadata.
120 NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
124 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
125 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
128 unsigned OriginalNumLines = getDebugifyOperand(0);
129 unsigned OriginalNumVars = getDebugifyOperand(1);
130 bool HasErrors = false;
132 // Find missing lines.
133 BitVector MissingLines{OriginalNumLines, true};
134 for (Function &F : M) {
135 for (Instruction &I : instructions(F)) {
136 if (isa<DbgValueInst>(&I))
139 auto DL = I.getDebugLoc();
141 MissingLines.reset(DL.getLine() - 1);
145 outs() << "ERROR: Instruction with empty DebugLoc -- ";
151 for (unsigned Idx : MissingLines.set_bits())
152 outs() << "WARNING: Missing line " << Idx + 1 << "\n";
154 // Find missing variables.
155 BitVector MissingVars{OriginalNumVars, true};
156 for (Function &F : M) {
157 for (Instruction &I : instructions(F)) {
158 auto *DVI = dyn_cast<DbgValueInst>(&I);
163 (void)to_integer(DVI->getVariable()->getName(), Var, 10);
164 assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
165 MissingVars.reset(Var - 1);
168 for (unsigned Idx : MissingVars.set_bits())
169 outs() << "ERROR: Missing variable " << Idx + 1 << "\n";
170 HasErrors |= MissingVars.count() > 0;
172 outs() << "CheckDebugify: " << (HasErrors ? "FAIL" : "PASS") << "\n";
175 /// Attach synthetic debug info to everything.
176 struct DebugifyPass : public ModulePass {
177 bool runOnModule(Module &M) override { return applyDebugifyMetadata(M); }
179 DebugifyPass() : ModulePass(ID) {}
181 void getAnalysisUsage(AnalysisUsage &AU) const override {
182 AU.setPreservesAll();
185 static char ID; // Pass identification.
188 /// Check debug info inserted by -debugify for completeness.
189 struct CheckDebugifyPass : public ModulePass {
190 bool runOnModule(Module &M) override {
191 checkDebugifyMetadata(M);
195 CheckDebugifyPass() : ModulePass(ID) {}
197 void getAnalysisUsage(AnalysisUsage &AU) const override {
198 AU.setPreservesAll();
201 static char ID; // Pass identification.
204 } // end anonymous namespace
206 char DebugifyPass::ID = 0;
207 static RegisterPass<DebugifyPass> X("debugify",
208 "Attach debug info to everything");
210 char CheckDebugifyPass::ID = 0;
211 static RegisterPass<CheckDebugifyPass> Y("check-debugify",
212 "Check debug info from -debugify");