blob: e81facf79887a9feb034fecbf7fbcf4c81b66e6e [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 Kumara9e27312018-06-06 19:05:41 +000038cl::opt<bool> Quiet("debugify-quiet",
39 cl::desc("Suppress verbose debugify output"));
40
41raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
42
Vedant Kumar17d8bba2018-02-15 21:28:38 +000043bool isFunctionSkipped(Function &F) {
44 return F.isDeclaration() || !F.hasExactDefinition();
45}
46
Vedant Kumar6d354ed2018-06-06 19:05:42 +000047/// Find the basic block's terminating instruction.
Vedant Kumar800255f2018-06-05 00:56:07 +000048///
Vedant Kumar6d354ed2018-06-06 19:05:42 +000049/// Special care is needed to handle musttail and deopt calls, as these behave
50/// like (but are in fact not) terminators.
51Instruction *findTerminatingInstruction(BasicBlock &BB) {
Vedant Kumar800255f2018-06-05 00:56:07 +000052 if (auto *I = BB.getTerminatingMustTailCall())
53 return I;
54 if (auto *I = BB.getTerminatingDeoptimizeCall())
55 return I;
56 return BB.getTerminator();
57}
58
Vedant Kumar595ba1d2018-05-15 00:29:27 +000059bool applyDebugifyMetadata(Module &M,
60 iterator_range<Module::iterator> Functions,
61 StringRef Banner) {
Vedant Kumar195dfd12017-12-08 21:57:28 +000062 // Skip modules with debug info.
63 if (M.getNamedMetadata("llvm.dbg.cu")) {
Vedant Kumara9e27312018-06-06 19:05:41 +000064 dbg() << Banner << "Skipping module with debug info\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +000065 return false;
66 }
67
68 DIBuilder DIB(M);
69 LLVMContext &Ctx = M.getContext();
70
71 // Get a DIType which corresponds to Ty.
72 DenseMap<uint64_t, DIType *> TypeCache;
73 auto getCachedDIType = [&](Type *Ty) -> DIType * {
Vedant Kumar1f6f5f12018-01-06 00:37:01 +000074 uint64_t Size =
75 Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
Vedant Kumar195dfd12017-12-08 21:57:28 +000076 DIType *&DTy = TypeCache[Size];
77 if (!DTy) {
78 std::string Name = "ty" + utostr(Size);
79 DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
80 }
81 return DTy;
82 };
83
84 unsigned NextLine = 1;
85 unsigned NextVar = 1;
86 auto File = DIB.createFile(M.getName(), "/");
Vedant Kumarab112b82018-06-05 00:56:07 +000087 auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify",
88 /*isOptimized=*/true, "", 0);
Vedant Kumar195dfd12017-12-08 21:57:28 +000089
90 // Visit each instruction.
Vedant Kumar595ba1d2018-05-15 00:29:27 +000091 for (Function &F : Functions) {
Vedant Kumar17d8bba2018-02-15 21:28:38 +000092 if (isFunctionSkipped(F))
Vedant Kumar195dfd12017-12-08 21:57:28 +000093 continue;
94
95 auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
96 bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
97 auto SP =
98 DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
Vedant Kumar16276322018-02-13 18:15:27 +000099 IsLocalToUnit, /*isDefinition=*/true, NextLine,
Vedant Kumar195dfd12017-12-08 21:57:28 +0000100 DINode::FlagZero, /*isOptimized=*/true);
101 F.setSubprogram(SP);
102 for (BasicBlock &BB : F) {
103 // Attach debug locations.
104 for (Instruction &I : BB)
105 I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
106
Vedant Kumar77f4d4d2018-06-03 22:50:22 +0000107 // Inserting debug values into EH pads can break IR invariants.
108 if (BB.isEHPad())
109 continue;
110
Vedant Kumar6d354ed2018-06-06 19:05:42 +0000111 // Find the terminating instruction, after which no debug values are
112 // attached.
113 Instruction *LastInst = findTerminatingInstruction(BB);
114 assert(LastInst && "Expected basic block with a terminator");
115
116 // Maintain an insertion point which can't be invalidated when updates
117 // are made.
118 BasicBlock::iterator InsertPt = BB.getFirstInsertionPt();
119 assert(InsertPt != BB.end() && "Expected to find an insertion point");
120 Instruction *InsertBefore = &*InsertPt;
Vedant Kumar7dda2212018-06-04 03:33:01 +0000121
Vedant Kumar195dfd12017-12-08 21:57:28 +0000122 // Attach debug values.
Vedant Kumar6d354ed2018-06-06 19:05:42 +0000123 for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000124 // Skip void-valued instructions.
Vedant Kumar6d354ed2018-06-06 19:05:42 +0000125 if (I->getType()->isVoidTy())
Vedant Kumar195dfd12017-12-08 21:57:28 +0000126 continue;
127
Vedant Kumar6d354ed2018-06-06 19:05:42 +0000128 // Phis and EH pads must be grouped at the beginning of the block.
129 // Only advance the insertion point when we finish visiting these.
130 if (!isa<PHINode>(I) && !I->isEHPad())
131 InsertBefore = I->getNextNode();
Vedant Kumar195dfd12017-12-08 21:57:28 +0000132
133 std::string Name = utostr(NextVar++);
Vedant Kumar6d354ed2018-06-06 19:05:42 +0000134 const DILocation *Loc = I->getDebugLoc().get();
Vedant Kumar195dfd12017-12-08 21:57:28 +0000135 auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
Vedant Kumar6d354ed2018-06-06 19:05:42 +0000136 getCachedDIType(I->getType()),
Vedant Kumar195dfd12017-12-08 21:57:28 +0000137 /*AlwaysPreserve=*/true);
Vedant Kumar6d354ed2018-06-06 19:05:42 +0000138 DIB.insertDbgValueIntrinsic(I, LocalVar, DIB.createExpression(), Loc,
139 InsertBefore);
Vedant Kumar195dfd12017-12-08 21:57:28 +0000140 }
141 }
142 DIB.finalizeSubprogram(SP);
143 }
144 DIB.finalize();
145
146 // Track the number of distinct lines and variables.
147 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
148 auto *IntTy = Type::getInt32Ty(Ctx);
149 auto addDebugifyOperand = [&](unsigned N) {
150 NMD->addOperand(MDNode::get(
151 Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
152 };
153 addDebugifyOperand(NextLine - 1); // Original number of lines.
154 addDebugifyOperand(NextVar - 1); // Original number of variables.
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000155 assert(NMD->getNumOperands() == 2 &&
156 "llvm.debugify should have exactly 2 operands!");
Vedant Kumar4872535e2018-05-24 23:00:23 +0000157
158 // Claim that this synthetic debug info is valid.
159 StringRef DIVersionKey = "Debug Info Version";
160 if (!M.getModuleFlag(DIVersionKey))
161 M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
162
Vedant Kumar195dfd12017-12-08 21:57:28 +0000163 return true;
164}
165
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000166bool checkDebugifyMetadata(Module &M,
167 iterator_range<Module::iterator> Functions,
Vedant Kumarab112b82018-06-05 00:56:07 +0000168 StringRef NameOfWrappedPass, StringRef Banner,
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000169 bool Strip) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000170 // Skip modules without debugify metadata.
171 NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000172 if (!NMD) {
Vedant Kumara9e27312018-06-06 19:05:41 +0000173 dbg() << Banner << "Skipping module without debugify metadata\n";
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000174 return false;
175 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000176
177 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
178 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
179 ->getZExtValue();
180 };
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000181 assert(NMD->getNumOperands() == 2 &&
182 "llvm.debugify should have exactly 2 operands!");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000183 unsigned OriginalNumLines = getDebugifyOperand(0);
184 unsigned OriginalNumVars = getDebugifyOperand(1);
185 bool HasErrors = false;
186
Vedant Kumar195dfd12017-12-08 21:57:28 +0000187 BitVector MissingLines{OriginalNumLines, true};
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000188 BitVector MissingVars{OriginalNumVars, true};
189 for (Function &F : Functions) {
Vedant Kumar17d8bba2018-02-15 21:28:38 +0000190 if (isFunctionSkipped(F))
191 continue;
192
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000193 // Find missing lines.
Vedant Kumar195dfd12017-12-08 21:57:28 +0000194 for (Instruction &I : instructions(F)) {
195 if (isa<DbgValueInst>(&I))
196 continue;
197
198 auto DL = I.getDebugLoc();
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000199 if (DL && DL.getLine() != 0) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000200 MissingLines.reset(DL.getLine() - 1);
201 continue;
202 }
203
Vedant Kumara9e27312018-06-06 19:05:41 +0000204 dbg() << "ERROR: Instruction with empty DebugLoc in function ";
205 dbg() << F.getName() << " --";
206 I.print(dbg());
207 dbg() << "\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +0000208 HasErrors = true;
209 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000210
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000211 // Find missing variables.
Vedant Kumar195dfd12017-12-08 21:57:28 +0000212 for (Instruction &I : instructions(F)) {
213 auto *DVI = dyn_cast<DbgValueInst>(&I);
214 if (!DVI)
215 continue;
216
217 unsigned Var = ~0U;
218 (void)to_integer(DVI->getVariable()->getName(), Var, 10);
219 assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
220 MissingVars.reset(Var - 1);
221 }
222 }
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000223
224 // Print the results.
225 for (unsigned Idx : MissingLines.set_bits())
Vedant Kumara9e27312018-06-06 19:05:41 +0000226 dbg() << "WARNING: Missing line " << Idx + 1 << "\n";
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000227
Vedant Kumar195dfd12017-12-08 21:57:28 +0000228 for (unsigned Idx : MissingVars.set_bits())
Vedant Kumar2e6c5f92018-06-26 18:54:10 +0000229 dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +0000230
Vedant Kumara9e27312018-06-06 19:05:41 +0000231 dbg() << Banner;
Vedant Kumarb70e3562018-05-24 23:00:22 +0000232 if (!NameOfWrappedPass.empty())
Vedant Kumara9e27312018-06-06 19:05:41 +0000233 dbg() << " [" << NameOfWrappedPass << "]";
234 dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000235
236 // Strip the Debugify Metadata if required.
237 if (Strip) {
238 StripDebugInfo(M);
239 M.eraseNamedMetadata(NMD);
240 return true;
241 }
242
243 return false;
Vedant Kumar195dfd12017-12-08 21:57:28 +0000244}
245
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000246/// ModulePass for attaching synthetic debug info to everything, used with the
247/// legacy module pass manager.
248struct DebugifyModulePass : public ModulePass {
249 bool runOnModule(Module &M) override {
250 return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
251 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000252
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000253 DebugifyModulePass() : ModulePass(ID) {}
Vedant Kumar195dfd12017-12-08 21:57:28 +0000254
255 void getAnalysisUsage(AnalysisUsage &AU) const override {
256 AU.setPreservesAll();
257 }
258
259 static char ID; // Pass identification.
260};
261
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000262/// FunctionPass for attaching synthetic debug info to instructions within a
263/// single function, used with the legacy module pass manager.
264struct DebugifyFunctionPass : public FunctionPass {
265 bool runOnFunction(Function &F) override {
266 Module &M = *F.getParent();
267 auto FuncIt = F.getIterator();
268 return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
Vedant Kumarab112b82018-06-05 00:56:07 +0000269 "FunctionDebugify: ");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000270 }
271
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000272 DebugifyFunctionPass() : FunctionPass(ID) {}
Vedant Kumar195dfd12017-12-08 21:57:28 +0000273
274 void getAnalysisUsage(AnalysisUsage &AU) const override {
275 AU.setPreservesAll();
276 }
277
278 static char ID; // Pass identification.
279};
280
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000281/// ModulePass for checking debug info inserted by -debugify, used with the
282/// legacy module pass manager.
283struct CheckDebugifyModulePass : public ModulePass {
284 bool runOnModule(Module &M) override {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000285 return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
286 "CheckModuleDebugify", Strip);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000287 }
288
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000289 CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "")
290 : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000291
Vedant Kumarfb7c7682018-06-04 21:43:28 +0000292 void getAnalysisUsage(AnalysisUsage &AU) const override {
293 AU.setPreservesAll();
294 }
295
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000296 static char ID; // Pass identification.
297
298private:
299 bool Strip;
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000300 StringRef NameOfWrappedPass;
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000301};
302
303/// FunctionPass for checking debug info inserted by -debugify-function, used
304/// with the legacy module pass manager.
305struct CheckDebugifyFunctionPass : public FunctionPass {
306 bool runOnFunction(Function &F) override {
307 Module &M = *F.getParent();
308 auto FuncIt = F.getIterator();
309 return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
Vedant Kumar4872535e2018-05-24 23:00:23 +0000310 NameOfWrappedPass, "CheckFunctionDebugify",
311 Strip);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000312 }
313
Vedant Kumar4872535e2018-05-24 23:00:23 +0000314 CheckDebugifyFunctionPass(bool Strip = false,
315 StringRef NameOfWrappedPass = "")
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000316 : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000317
318 void getAnalysisUsage(AnalysisUsage &AU) const override {
319 AU.setPreservesAll();
320 }
321
322 static char ID; // Pass identification.
323
324private:
325 bool Strip;
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000326 StringRef NameOfWrappedPass;
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000327};
328
Vedant Kumar195dfd12017-12-08 21:57:28 +0000329} // end anonymous namespace
330
Vedant Kumarab112b82018-06-05 00:56:07 +0000331ModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); }
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000332
333FunctionPass *createDebugifyFunctionPass() {
334 return new DebugifyFunctionPass();
335}
Vedant Kumar92f7a622018-01-23 20:43:50 +0000336
Vedant Kumar775c7af2018-02-15 21:14:36 +0000337PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000338 applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
Vedant Kumar775c7af2018-02-15 21:14:36 +0000339 return PreservedAnalyses::all();
340}
341
Vedant Kumar36b89d42018-06-04 00:11:47 +0000342ModulePass *createCheckDebugifyModulePass(bool Strip,
343 StringRef NameOfWrappedPass) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000344 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000345}
346
Vedant Kumar36b89d42018-06-04 00:11:47 +0000347FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
348 StringRef NameOfWrappedPass) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000349 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000350}
Vedant Kumar92f7a622018-01-23 20:43:50 +0000351
Vedant Kumar775c7af2018-02-15 21:14:36 +0000352PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
353 ModuleAnalysisManager &) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000354 checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false);
Vedant Kumar775c7af2018-02-15 21:14:36 +0000355 return PreservedAnalyses::all();
356}
357
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000358char DebugifyModulePass::ID = 0;
359static RegisterPass<DebugifyModulePass> DM("debugify",
Vedant Kumar36b89d42018-06-04 00:11:47 +0000360 "Attach debug info to everything");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000361
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000362char CheckDebugifyModulePass::ID = 0;
Vedant Kumar36b89d42018-06-04 00:11:47 +0000363static RegisterPass<CheckDebugifyModulePass>
364 CDM("check-debugify", "Check debug info from -debugify");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000365
366char DebugifyFunctionPass::ID = 0;
367static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
Vedant Kumar36b89d42018-06-04 00:11:47 +0000368 "Attach debug info to a function");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000369
370char CheckDebugifyFunctionPass::ID = 0;
Vedant Kumar36b89d42018-06-04 00:11:47 +0000371static RegisterPass<CheckDebugifyFunctionPass>
372 CDF("check-debugify-function", "Check debug info from -debugify-function");