blob: aa967a72aa07dc08f6bf06417fd9b03254c5e30f [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 Kumarab112b82018-06-05 00:56:07 +000070 auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify",
71 /*isOptimized=*/true, "", 0);
Vedant Kumar195dfd12017-12-08 21:57:28 +000072
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,
Vedant Kumarab112b82018-06-05 00:56:07 +0000148 StringRef NameOfWrappedPass, StringRef Banner,
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000149 bool Strip) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000150 // Skip modules without debugify metadata.
151 NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000152 if (!NMD) {
153 errs() << Banner << "Skipping module without debugify metadata\n";
154 return false;
155 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000156
157 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
158 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
159 ->getZExtValue();
160 };
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000161 assert(NMD->getNumOperands() == 2 &&
162 "llvm.debugify should have exactly 2 operands!");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000163 unsigned OriginalNumLines = getDebugifyOperand(0);
164 unsigned OriginalNumVars = getDebugifyOperand(1);
165 bool HasErrors = false;
166
Vedant Kumar195dfd12017-12-08 21:57:28 +0000167 BitVector MissingLines{OriginalNumLines, true};
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000168 BitVector MissingVars{OriginalNumVars, true};
169 for (Function &F : Functions) {
Vedant Kumar17d8bba2018-02-15 21:28:38 +0000170 if (isFunctionSkipped(F))
171 continue;
172
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000173 // Find missing lines.
Vedant Kumar195dfd12017-12-08 21:57:28 +0000174 for (Instruction &I : instructions(F)) {
175 if (isa<DbgValueInst>(&I))
176 continue;
177
178 auto DL = I.getDebugLoc();
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000179 if (DL && DL.getLine() != 0) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000180 MissingLines.reset(DL.getLine() - 1);
181 continue;
182 }
183
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000184 errs() << "ERROR: Instruction with empty DebugLoc in function ";
185 errs() << F.getName() << " --";
186 I.print(errs());
187 errs() << "\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +0000188 HasErrors = true;
189 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000190
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000191 // Find missing variables.
Vedant Kumar195dfd12017-12-08 21:57:28 +0000192 for (Instruction &I : instructions(F)) {
193 auto *DVI = dyn_cast<DbgValueInst>(&I);
194 if (!DVI)
195 continue;
196
197 unsigned Var = ~0U;
198 (void)to_integer(DVI->getVariable()->getName(), Var, 10);
199 assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
200 MissingVars.reset(Var - 1);
201 }
202 }
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000203
204 // Print the results.
205 for (unsigned Idx : MissingLines.set_bits())
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000206 errs() << "WARNING: Missing line " << Idx + 1 << "\n";
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000207
Vedant Kumar195dfd12017-12-08 21:57:28 +0000208 for (unsigned Idx : MissingVars.set_bits())
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000209 errs() << "ERROR: Missing variable " << Idx + 1 << "\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +0000210 HasErrors |= MissingVars.count() > 0;
211
Vedant Kumarb70e3562018-05-24 23:00:22 +0000212 errs() << Banner;
213 if (!NameOfWrappedPass.empty())
214 errs() << " [" << NameOfWrappedPass << "]";
215 errs() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000216 if (HasErrors) {
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000217 errs() << "Module IR Dump\n";
218 M.print(errs(), nullptr, false);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000219 }
220
221 // Strip the Debugify Metadata if required.
222 if (Strip) {
223 StripDebugInfo(M);
224 M.eraseNamedMetadata(NMD);
225 return true;
226 }
227
228 return false;
Vedant Kumar195dfd12017-12-08 21:57:28 +0000229}
230
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000231/// ModulePass for attaching synthetic debug info to everything, used with the
232/// legacy module pass manager.
233struct DebugifyModulePass : public ModulePass {
234 bool runOnModule(Module &M) override {
235 return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
236 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000237
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000238 DebugifyModulePass() : ModulePass(ID) {}
Vedant Kumar195dfd12017-12-08 21:57:28 +0000239
240 void getAnalysisUsage(AnalysisUsage &AU) const override {
241 AU.setPreservesAll();
242 }
243
244 static char ID; // Pass identification.
245};
246
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000247/// FunctionPass for attaching synthetic debug info to instructions within a
248/// single function, used with the legacy module pass manager.
249struct DebugifyFunctionPass : public FunctionPass {
250 bool runOnFunction(Function &F) override {
251 Module &M = *F.getParent();
252 auto FuncIt = F.getIterator();
253 return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
Vedant Kumarab112b82018-06-05 00:56:07 +0000254 "FunctionDebugify: ");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000255 }
256
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000257 DebugifyFunctionPass() : FunctionPass(ID) {}
Vedant Kumar195dfd12017-12-08 21:57:28 +0000258
259 void getAnalysisUsage(AnalysisUsage &AU) const override {
260 AU.setPreservesAll();
261 }
262
263 static char ID; // Pass identification.
264};
265
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000266/// ModulePass for checking debug info inserted by -debugify, used with the
267/// legacy module pass manager.
268struct CheckDebugifyModulePass : public ModulePass {
269 bool runOnModule(Module &M) override {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000270 return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
271 "CheckModuleDebugify", Strip);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000272 }
273
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000274 CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "")
275 : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000276
Vedant Kumarfb7c7682018-06-04 21:43:28 +0000277 void getAnalysisUsage(AnalysisUsage &AU) const override {
278 AU.setPreservesAll();
279 }
280
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000281 static char ID; // Pass identification.
282
283private:
284 bool Strip;
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000285 StringRef NameOfWrappedPass;
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000286};
287
288/// FunctionPass for checking debug info inserted by -debugify-function, used
289/// with the legacy module pass manager.
290struct CheckDebugifyFunctionPass : public FunctionPass {
291 bool runOnFunction(Function &F) override {
292 Module &M = *F.getParent();
293 auto FuncIt = F.getIterator();
294 return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
Vedant Kumar4872535e2018-05-24 23:00:23 +0000295 NameOfWrappedPass, "CheckFunctionDebugify",
296 Strip);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000297 }
298
Vedant Kumar4872535e2018-05-24 23:00:23 +0000299 CheckDebugifyFunctionPass(bool Strip = false,
300 StringRef NameOfWrappedPass = "")
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000301 : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000302
303 void getAnalysisUsage(AnalysisUsage &AU) const override {
304 AU.setPreservesAll();
305 }
306
307 static char ID; // Pass identification.
308
309private:
310 bool Strip;
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000311 StringRef NameOfWrappedPass;
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000312};
313
Vedant Kumar195dfd12017-12-08 21:57:28 +0000314} // end anonymous namespace
315
Vedant Kumarab112b82018-06-05 00:56:07 +0000316ModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); }
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000317
318FunctionPass *createDebugifyFunctionPass() {
319 return new DebugifyFunctionPass();
320}
Vedant Kumar92f7a622018-01-23 20:43:50 +0000321
Vedant Kumar775c7af2018-02-15 21:14:36 +0000322PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000323 applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
Vedant Kumar775c7af2018-02-15 21:14:36 +0000324 return PreservedAnalyses::all();
325}
326
Vedant Kumar36b89d42018-06-04 00:11:47 +0000327ModulePass *createCheckDebugifyModulePass(bool Strip,
328 StringRef NameOfWrappedPass) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000329 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000330}
331
Vedant Kumar36b89d42018-06-04 00:11:47 +0000332FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
333 StringRef NameOfWrappedPass) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000334 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000335}
Vedant Kumar92f7a622018-01-23 20:43:50 +0000336
Vedant Kumar775c7af2018-02-15 21:14:36 +0000337PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
338 ModuleAnalysisManager &) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000339 checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false);
Vedant Kumar775c7af2018-02-15 21:14:36 +0000340 return PreservedAnalyses::all();
341}
342
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000343char DebugifyModulePass::ID = 0;
344static RegisterPass<DebugifyModulePass> DM("debugify",
Vedant Kumar36b89d42018-06-04 00:11:47 +0000345 "Attach debug info to everything");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000346
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000347char CheckDebugifyModulePass::ID = 0;
Vedant Kumar36b89d42018-06-04 00:11:47 +0000348static RegisterPass<CheckDebugifyModulePass>
349 CDM("check-debugify", "Check debug info from -debugify");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000350
351char DebugifyFunctionPass::ID = 0;
352static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
Vedant Kumar36b89d42018-06-04 00:11:47 +0000353 "Attach debug info to a function");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000354
355char CheckDebugifyFunctionPass::ID = 0;
Vedant Kumar36b89d42018-06-04 00:11:47 +0000356static RegisterPass<CheckDebugifyFunctionPass>
357 CDF("check-debugify-function", "Check debug info from -debugify-function");