blob: 0a900a520ab5824b69d3b7f6ac7e8bcd3129396b [file] [log] [blame]
Vedant Kumar195dfd12017-12-08 21:57:28 +00001//===- 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
Vedant Kumar775c7af2018-02-15 21:14:36 +000015#include "PassPrinters.h"
Vedant Kumar195dfd12017-12-08 21:57:28 +000016#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"
33
34using namespace llvm;
35
36namespace {
37
Vedant Kumar17d8bba2018-02-15 21:28:38 +000038bool isFunctionSkipped(Function &F) {
39 return F.isDeclaration() || !F.hasExactDefinition();
40}
41
Vedant Kumar595ba1d2018-05-15 00:29:27 +000042bool applyDebugifyMetadata(Module &M,
43 iterator_range<Module::iterator> Functions,
44 StringRef Banner) {
Vedant Kumar195dfd12017-12-08 21:57:28 +000045 // Skip modules with debug info.
46 if (M.getNamedMetadata("llvm.dbg.cu")) {
Vedant Kumar595ba1d2018-05-15 00:29:27 +000047 errs() << Banner << "Skipping module with debug info\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +000048 return false;
49 }
50
51 DIBuilder DIB(M);
52 LLVMContext &Ctx = M.getContext();
53
54 // Get a DIType which corresponds to Ty.
55 DenseMap<uint64_t, DIType *> TypeCache;
56 auto getCachedDIType = [&](Type *Ty) -> DIType * {
Vedant Kumar1f6f5f12018-01-06 00:37:01 +000057 uint64_t Size =
58 Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
Vedant Kumar195dfd12017-12-08 21:57:28 +000059 DIType *&DTy = TypeCache[Size];
60 if (!DTy) {
61 std::string Name = "ty" + utostr(Size);
62 DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
63 }
64 return DTy;
65 };
66
67 unsigned NextLine = 1;
68 unsigned NextVar = 1;
69 auto File = DIB.createFile(M.getName(), "/");
Vedant Kumar595ba1d2018-05-15 00:29:27 +000070 auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File,
Vedant Kumar195dfd12017-12-08 21:57:28 +000071 "debugify", /*isOptimized=*/true, "", 0);
72
73 // Visit each instruction.
Vedant Kumar595ba1d2018-05-15 00:29:27 +000074 for (Function &F : Functions) {
Vedant Kumar17d8bba2018-02-15 21:28:38 +000075 if (isFunctionSkipped(F))
Vedant Kumar195dfd12017-12-08 21:57:28 +000076 continue;
77
78 auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
79 bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
80 auto SP =
81 DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
Vedant Kumar16276322018-02-13 18:15:27 +000082 IsLocalToUnit, /*isDefinition=*/true, NextLine,
Vedant Kumar195dfd12017-12-08 21:57:28 +000083 DINode::FlagZero, /*isOptimized=*/true);
84 F.setSubprogram(SP);
85 for (BasicBlock &BB : F) {
86 // Attach debug locations.
87 for (Instruction &I : BB)
88 I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
89
Vedant Kumar77f4d4d2018-06-03 22:50:22 +000090 // Inserting debug values into EH pads can break IR invariants.
91 if (BB.isEHPad())
92 continue;
93
Vedant Kumar7dda2212018-06-04 03:33:01 +000094 // Debug values must be inserted before a musttail call (if one is
95 // present), or before the block terminator otherwise.
96 Instruction *LastInst = BB.getTerminatingMustTailCall();
97 if (!LastInst)
98 LastInst = BB.getTerminator();
99
Vedant Kumar195dfd12017-12-08 21:57:28 +0000100 // Attach debug values.
Vedant Kumar7dda2212018-06-04 03:33:01 +0000101 for (auto It = BB.begin(), End = LastInst->getIterator(); It != End;
102 ++It) {
103 Instruction &I = *It;
104
Vedant Kumar195dfd12017-12-08 21:57:28 +0000105 // Skip void-valued instructions.
106 if (I.getType()->isVoidTy())
107 continue;
108
Vedant Kumar7dda2212018-06-04 03:33:01 +0000109 // Skip any just-inserted intrinsics.
110 if (isa<DbgValueInst>(&I))
Vedant Kumar195dfd12017-12-08 21:57:28 +0000111 break;
112
113 std::string Name = utostr(NextVar++);
114 const DILocation *Loc = I.getDebugLoc().get();
115 auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
116 getCachedDIType(I.getType()),
117 /*AlwaysPreserve=*/true);
118 DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc,
Vedant Kumar7dda2212018-06-04 03:33:01 +0000119 LastInst);
Vedant Kumar195dfd12017-12-08 21:57:28 +0000120 }
121 }
122 DIB.finalizeSubprogram(SP);
123 }
124 DIB.finalize();
125
126 // Track the number of distinct lines and variables.
127 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
128 auto *IntTy = Type::getInt32Ty(Ctx);
129 auto addDebugifyOperand = [&](unsigned N) {
130 NMD->addOperand(MDNode::get(
131 Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
132 };
133 addDebugifyOperand(NextLine - 1); // Original number of lines.
134 addDebugifyOperand(NextVar - 1); // Original number of variables.
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000135 assert(NMD->getNumOperands() == 2 &&
136 "llvm.debugify should have exactly 2 operands!");
Vedant Kumar4872535e2018-05-24 23:00:23 +0000137
138 // Claim that this synthetic debug info is valid.
139 StringRef DIVersionKey = "Debug Info Version";
140 if (!M.getModuleFlag(DIVersionKey))
141 M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
142
Vedant Kumar195dfd12017-12-08 21:57:28 +0000143 return true;
144}
145
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000146bool checkDebugifyMetadata(Module &M,
147 iterator_range<Module::iterator> Functions,
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000148 StringRef NameOfWrappedPass,
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000149 StringRef Banner,
150 bool Strip) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000151 // Skip modules without debugify metadata.
152 NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000153 if (!NMD) {
154 errs() << Banner << "Skipping module without debugify metadata\n";
155 return false;
156 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000157
158 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
159 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
160 ->getZExtValue();
161 };
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000162 assert(NMD->getNumOperands() == 2 &&
163 "llvm.debugify should have exactly 2 operands!");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000164 unsigned OriginalNumLines = getDebugifyOperand(0);
165 unsigned OriginalNumVars = getDebugifyOperand(1);
166 bool HasErrors = false;
167
Vedant Kumar195dfd12017-12-08 21:57:28 +0000168 BitVector MissingLines{OriginalNumLines, true};
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000169 BitVector MissingVars{OriginalNumVars, true};
170 for (Function &F : Functions) {
Vedant Kumar17d8bba2018-02-15 21:28:38 +0000171 if (isFunctionSkipped(F))
172 continue;
173
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000174 // Find missing lines.
Vedant Kumar195dfd12017-12-08 21:57:28 +0000175 for (Instruction &I : instructions(F)) {
176 if (isa<DbgValueInst>(&I))
177 continue;
178
179 auto DL = I.getDebugLoc();
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000180 if (DL && DL.getLine() != 0) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000181 MissingLines.reset(DL.getLine() - 1);
182 continue;
183 }
184
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000185 errs() << "ERROR: Instruction with empty DebugLoc in function ";
186 errs() << F.getName() << " --";
187 I.print(errs());
188 errs() << "\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +0000189 HasErrors = true;
190 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000191
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000192 // Find missing variables.
Vedant Kumar195dfd12017-12-08 21:57:28 +0000193 for (Instruction &I : instructions(F)) {
194 auto *DVI = dyn_cast<DbgValueInst>(&I);
195 if (!DVI)
196 continue;
197
198 unsigned Var = ~0U;
199 (void)to_integer(DVI->getVariable()->getName(), Var, 10);
200 assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
201 MissingVars.reset(Var - 1);
202 }
203 }
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000204
205 // Print the results.
206 for (unsigned Idx : MissingLines.set_bits())
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000207 errs() << "WARNING: Missing line " << Idx + 1 << "\n";
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000208
Vedant Kumar195dfd12017-12-08 21:57:28 +0000209 for (unsigned Idx : MissingVars.set_bits())
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000210 errs() << "ERROR: Missing variable " << Idx + 1 << "\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +0000211 HasErrors |= MissingVars.count() > 0;
212
Vedant Kumarb70e3562018-05-24 23:00:22 +0000213 errs() << Banner;
214 if (!NameOfWrappedPass.empty())
215 errs() << " [" << NameOfWrappedPass << "]";
216 errs() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000217 if (HasErrors) {
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000218 errs() << "Module IR Dump\n";
219 M.print(errs(), nullptr, false);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000220 }
221
222 // Strip the Debugify Metadata if required.
223 if (Strip) {
224 StripDebugInfo(M);
225 M.eraseNamedMetadata(NMD);
226 return true;
227 }
228
229 return false;
Vedant Kumar195dfd12017-12-08 21:57:28 +0000230}
231
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000232/// ModulePass for attaching synthetic debug info to everything, used with the
233/// legacy module pass manager.
234struct DebugifyModulePass : public ModulePass {
235 bool runOnModule(Module &M) override {
236 return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
237 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000238
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000239 DebugifyModulePass() : ModulePass(ID) {}
Vedant Kumar195dfd12017-12-08 21:57:28 +0000240
241 void getAnalysisUsage(AnalysisUsage &AU) const override {
242 AU.setPreservesAll();
243 }
244
245 static char ID; // Pass identification.
246};
247
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000248/// FunctionPass for attaching synthetic debug info to instructions within a
249/// single function, used with the legacy module pass manager.
250struct DebugifyFunctionPass : public FunctionPass {
251 bool runOnFunction(Function &F) override {
252 Module &M = *F.getParent();
253 auto FuncIt = F.getIterator();
254 return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
255 "FunctionDebugify: ");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000256 }
257
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000258 DebugifyFunctionPass() : FunctionPass(ID) {}
Vedant Kumar195dfd12017-12-08 21:57:28 +0000259
260 void getAnalysisUsage(AnalysisUsage &AU) const override {
261 AU.setPreservesAll();
262 }
263
264 static char ID; // Pass identification.
265};
266
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000267/// ModulePass for checking debug info inserted by -debugify, used with the
268/// legacy module pass manager.
269struct CheckDebugifyModulePass : public ModulePass {
270 bool runOnModule(Module &M) override {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000271 return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
272 "CheckModuleDebugify", Strip);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000273 }
274
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000275 CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "")
276 : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000277
278 static char ID; // Pass identification.
279
280private:
281 bool Strip;
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000282 StringRef NameOfWrappedPass;
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000283};
284
285/// FunctionPass for checking debug info inserted by -debugify-function, used
286/// with the legacy module pass manager.
287struct CheckDebugifyFunctionPass : public FunctionPass {
288 bool runOnFunction(Function &F) override {
289 Module &M = *F.getParent();
290 auto FuncIt = F.getIterator();
291 return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
Vedant Kumar4872535e2018-05-24 23:00:23 +0000292 NameOfWrappedPass, "CheckFunctionDebugify",
293 Strip);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000294 }
295
Vedant Kumar4872535e2018-05-24 23:00:23 +0000296 CheckDebugifyFunctionPass(bool Strip = false,
297 StringRef NameOfWrappedPass = "")
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000298 : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000299
300 void getAnalysisUsage(AnalysisUsage &AU) const override {
301 AU.setPreservesAll();
302 }
303
304 static char ID; // Pass identification.
305
306private:
307 bool Strip;
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000308 StringRef NameOfWrappedPass;
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000309};
310
Vedant Kumar195dfd12017-12-08 21:57:28 +0000311} // end anonymous namespace
312
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000313ModulePass *createDebugifyModulePass() {
314 return new DebugifyModulePass();
315}
316
317FunctionPass *createDebugifyFunctionPass() {
318 return new DebugifyFunctionPass();
319}
Vedant Kumar92f7a622018-01-23 20:43:50 +0000320
Vedant Kumar775c7af2018-02-15 21:14:36 +0000321PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000322 applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
Vedant Kumar775c7af2018-02-15 21:14:36 +0000323 return PreservedAnalyses::all();
324}
325
Vedant Kumar36b89d42018-06-04 00:11:47 +0000326ModulePass *createCheckDebugifyModulePass(bool Strip,
327 StringRef NameOfWrappedPass) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000328 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000329}
330
Vedant Kumar36b89d42018-06-04 00:11:47 +0000331FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
332 StringRef NameOfWrappedPass) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000333 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000334}
Vedant Kumar92f7a622018-01-23 20:43:50 +0000335
Vedant Kumar775c7af2018-02-15 21:14:36 +0000336PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
337 ModuleAnalysisManager &) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000338 checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false);
Vedant Kumar775c7af2018-02-15 21:14:36 +0000339 return PreservedAnalyses::all();
340}
341
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000342char DebugifyModulePass::ID = 0;
343static RegisterPass<DebugifyModulePass> DM("debugify",
Vedant Kumar36b89d42018-06-04 00:11:47 +0000344 "Attach debug info to everything");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000345
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000346char CheckDebugifyModulePass::ID = 0;
Vedant Kumar36b89d42018-06-04 00:11:47 +0000347static RegisterPass<CheckDebugifyModulePass>
348 CDM("check-debugify", "Check debug info from -debugify");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000349
350char DebugifyFunctionPass::ID = 0;
351static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
Vedant Kumar36b89d42018-06-04 00:11:47 +0000352 "Attach debug info to a function");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000353
354char CheckDebugifyFunctionPass::ID = 0;
Vedant Kumar36b89d42018-06-04 00:11:47 +0000355static RegisterPass<CheckDebugifyFunctionPass>
356 CDF("check-debugify-function", "Check debug info from -debugify-function");