]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/opt/Debugify.cpp
Merge lld trunk r321017 to contrib/llvm/tools/lld.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / opt / Debugify.cpp
1 //===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file This pass attaches synthetic debug info to everything. It can be used
11 /// to create targeted tests for debug info preservation.
12 ///
13 //===----------------------------------------------------------------------===//
14
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"
32
33 using namespace llvm;
34
35 namespace {
36
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";
41     return false;
42   }
43
44   DIBuilder DIB(M);
45   LLVMContext &Ctx = M.getContext();
46
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];
52     if (!DTy) {
53       std::string Name = "ty" + utostr(Size);
54       DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
55     }
56     return DTy;
57   };
58
59   unsigned NextLine = 1;
60   unsigned NextVar = 1;
61   auto File = DIB.createFile(M.getName(), "/");
62   auto CU =
63       DIB.createCompileUnit(dwarf::DW_LANG_C, DIB.createFile(M.getName(), "/"),
64                             "debugify", /*isOptimized=*/true, "", 0);
65
66   // Visit each instruction.
67   for (Function &F : M) {
68     if (F.isDeclaration())
69       continue;
70
71     auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
72     bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
73     auto SP =
74         DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
75                            IsLocalToUnit, F.hasExactDefinition(), NextLine,
76                            DINode::FlagZero, /*isOptimized=*/true);
77     F.setSubprogram(SP);
78     for (BasicBlock &BB : F) {
79       // Attach debug locations.
80       for (Instruction &I : BB)
81         I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
82
83       // Attach debug values.
84       for (Instruction &I : BB) {
85         // Skip void-valued instructions.
86         if (I.getType()->isVoidTy())
87           continue;
88
89         // Skip the terminator instruction and any just-inserted intrinsics.
90         if (isa<TerminatorInst>(&I) || isa<DbgValueInst>(&I))
91           break;
92
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,
99                                     BB.getTerminator());
100       }
101     }
102     DIB.finalizeSubprogram(SP);
103   }
104   DIB.finalize();
105
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))));
112   };
113   addDebugifyOperand(NextLine - 1); // Original number of lines.
114   addDebugifyOperand(NextVar - 1);  // Original number of variables.
115   return true;
116 }
117
118 void checkDebugifyMetadata(Module &M) {
119   // Skip modules without debugify metadata.
120   NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
121   if (!NMD)
122     return;
123
124   auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
125     return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
126         ->getZExtValue();
127   };
128   unsigned OriginalNumLines = getDebugifyOperand(0);
129   unsigned OriginalNumVars = getDebugifyOperand(1);
130   bool HasErrors = false;
131
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))
137         continue;
138
139       auto DL = I.getDebugLoc();
140       if (DL) {
141         MissingLines.reset(DL.getLine() - 1);
142         continue;
143       }
144
145       outs() << "ERROR: Instruction with empty DebugLoc -- ";
146       I.print(outs());
147       outs() << "\n";
148       HasErrors = true;
149     }
150   }
151   for (unsigned Idx : MissingLines.set_bits())
152     outs() << "WARNING: Missing line " << Idx + 1 << "\n";
153
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);
159       if (!DVI)
160         continue;
161
162       unsigned Var = ~0U;
163       (void)to_integer(DVI->getVariable()->getName(), Var, 10);
164       assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
165       MissingVars.reset(Var - 1);
166     }
167   }
168   for (unsigned Idx : MissingVars.set_bits())
169     outs() << "ERROR: Missing variable " << Idx + 1 << "\n";
170   HasErrors |= MissingVars.count() > 0;
171
172   outs() << "CheckDebugify: " << (HasErrors ? "FAIL" : "PASS") << "\n";
173 }
174
175 /// Attach synthetic debug info to everything.
176 struct DebugifyPass : public ModulePass {
177   bool runOnModule(Module &M) override { return applyDebugifyMetadata(M); }
178
179   DebugifyPass() : ModulePass(ID) {}
180
181   void getAnalysisUsage(AnalysisUsage &AU) const override {
182     AU.setPreservesAll();
183   }
184
185   static char ID; // Pass identification.
186 };
187
188 /// Check debug info inserted by -debugify for completeness.
189 struct CheckDebugifyPass : public ModulePass {
190   bool runOnModule(Module &M) override {
191     checkDebugifyMetadata(M);
192     return false;
193   }
194
195   CheckDebugifyPass() : ModulePass(ID) {}
196
197   void getAnalysisUsage(AnalysisUsage &AU) const override {
198     AU.setPreservesAll();
199   }
200
201   static char ID; // Pass identification.
202 };
203
204 } // end anonymous namespace
205
206 char DebugifyPass::ID = 0;
207 static RegisterPass<DebugifyPass> X("debugify",
208                                     "Attach debug info to everything");
209
210 char CheckDebugifyPass::ID = 0;
211 static RegisterPass<CheckDebugifyPass> Y("check-debugify",
212                                          "Check debug info from -debugify");