blob: 4a7da2eecd379947f6a6fe8d43bedcfee86b13b3 [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 Kumar195dfd12017-12-08 21:57:28 +000094 // Attach debug values.
95 for (Instruction &I : BB) {
96 // Skip void-valued instructions.
97 if (I.getType()->isVoidTy())
98 continue;
99
100 // Skip the terminator instruction and any just-inserted intrinsics.
101 if (isa<TerminatorInst>(&I) || isa<DbgValueInst>(&I))
102 break;
103
Vedant Kumar77f4d4d2018-06-03 22:50:22 +0000104 // Don't insert instructions after a musttail call.
105 if (auto *Call = dyn_cast<CallInst>(&I))
106 if (Call->isMustTailCall())
107 break;
108
Vedant Kumar195dfd12017-12-08 21:57:28 +0000109 std::string Name = utostr(NextVar++);
110 const DILocation *Loc = I.getDebugLoc().get();
111 auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
112 getCachedDIType(I.getType()),
113 /*AlwaysPreserve=*/true);
114 DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc,
115 BB.getTerminator());
116 }
117 }
118 DIB.finalizeSubprogram(SP);
119 }
120 DIB.finalize();
121
122 // Track the number of distinct lines and variables.
123 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
124 auto *IntTy = Type::getInt32Ty(Ctx);
125 auto addDebugifyOperand = [&](unsigned N) {
126 NMD->addOperand(MDNode::get(
127 Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
128 };
129 addDebugifyOperand(NextLine - 1); // Original number of lines.
130 addDebugifyOperand(NextVar - 1); // Original number of variables.
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000131 assert(NMD->getNumOperands() == 2 &&
132 "llvm.debugify should have exactly 2 operands!");
Vedant Kumar4872535e2018-05-24 23:00:23 +0000133
134 // Claim that this synthetic debug info is valid.
135 StringRef DIVersionKey = "Debug Info Version";
136 if (!M.getModuleFlag(DIVersionKey))
137 M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
138
Vedant Kumar195dfd12017-12-08 21:57:28 +0000139 return true;
140}
141
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000142bool checkDebugifyMetadata(Module &M,
143 iterator_range<Module::iterator> Functions,
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000144 StringRef NameOfWrappedPass,
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000145 StringRef Banner,
146 bool Strip) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000147 // Skip modules without debugify metadata.
148 NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000149 if (!NMD) {
150 errs() << Banner << "Skipping module without debugify metadata\n";
151 return false;
152 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000153
154 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
155 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
156 ->getZExtValue();
157 };
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000158 assert(NMD->getNumOperands() == 2 &&
159 "llvm.debugify should have exactly 2 operands!");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000160 unsigned OriginalNumLines = getDebugifyOperand(0);
161 unsigned OriginalNumVars = getDebugifyOperand(1);
162 bool HasErrors = false;
163
Vedant Kumar195dfd12017-12-08 21:57:28 +0000164 BitVector MissingLines{OriginalNumLines, true};
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000165 BitVector MissingVars{OriginalNumVars, true};
166 for (Function &F : Functions) {
Vedant Kumar17d8bba2018-02-15 21:28:38 +0000167 if (isFunctionSkipped(F))
168 continue;
169
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000170 // Find missing lines.
Vedant Kumar195dfd12017-12-08 21:57:28 +0000171 for (Instruction &I : instructions(F)) {
172 if (isa<DbgValueInst>(&I))
173 continue;
174
175 auto DL = I.getDebugLoc();
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000176 if (DL && DL.getLine() != 0) {
Vedant Kumar195dfd12017-12-08 21:57:28 +0000177 MissingLines.reset(DL.getLine() - 1);
178 continue;
179 }
180
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000181 errs() << "ERROR: Instruction with empty DebugLoc in function ";
182 errs() << F.getName() << " --";
183 I.print(errs());
184 errs() << "\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +0000185 HasErrors = true;
186 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000187
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000188 // Find missing variables.
Vedant Kumar195dfd12017-12-08 21:57:28 +0000189 for (Instruction &I : instructions(F)) {
190 auto *DVI = dyn_cast<DbgValueInst>(&I);
191 if (!DVI)
192 continue;
193
194 unsigned Var = ~0U;
195 (void)to_integer(DVI->getVariable()->getName(), Var, 10);
196 assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
197 MissingVars.reset(Var - 1);
198 }
199 }
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000200
201 // Print the results.
202 for (unsigned Idx : MissingLines.set_bits())
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000203 errs() << "WARNING: Missing line " << Idx + 1 << "\n";
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000204
Vedant Kumar195dfd12017-12-08 21:57:28 +0000205 for (unsigned Idx : MissingVars.set_bits())
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000206 errs() << "ERROR: Missing variable " << Idx + 1 << "\n";
Vedant Kumar195dfd12017-12-08 21:57:28 +0000207 HasErrors |= MissingVars.count() > 0;
208
Vedant Kumarb70e3562018-05-24 23:00:22 +0000209 errs() << Banner;
210 if (!NameOfWrappedPass.empty())
211 errs() << " [" << NameOfWrappedPass << "]";
212 errs() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000213 if (HasErrors) {
Anastasis Grammenosd6c66782018-05-17 18:19:58 +0000214 errs() << "Module IR Dump\n";
215 M.print(errs(), nullptr, false);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000216 }
217
218 // Strip the Debugify Metadata if required.
219 if (Strip) {
220 StripDebugInfo(M);
221 M.eraseNamedMetadata(NMD);
222 return true;
223 }
224
225 return false;
Vedant Kumar195dfd12017-12-08 21:57:28 +0000226}
227
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000228/// ModulePass for attaching synthetic debug info to everything, used with the
229/// legacy module pass manager.
230struct DebugifyModulePass : public ModulePass {
231 bool runOnModule(Module &M) override {
232 return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
233 }
Vedant Kumar195dfd12017-12-08 21:57:28 +0000234
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000235 DebugifyModulePass() : ModulePass(ID) {}
Vedant Kumar195dfd12017-12-08 21:57:28 +0000236
237 void getAnalysisUsage(AnalysisUsage &AU) const override {
238 AU.setPreservesAll();
239 }
240
241 static char ID; // Pass identification.
242};
243
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000244/// FunctionPass for attaching synthetic debug info to instructions within a
245/// single function, used with the legacy module pass manager.
246struct DebugifyFunctionPass : public FunctionPass {
247 bool runOnFunction(Function &F) override {
248 Module &M = *F.getParent();
249 auto FuncIt = F.getIterator();
250 return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
251 "FunctionDebugify: ");
Vedant Kumar195dfd12017-12-08 21:57:28 +0000252 }
253
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000254 DebugifyFunctionPass() : FunctionPass(ID) {}
Vedant Kumar195dfd12017-12-08 21:57:28 +0000255
256 void getAnalysisUsage(AnalysisUsage &AU) const override {
257 AU.setPreservesAll();
258 }
259
260 static char ID; // Pass identification.
261};
262
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000263/// ModulePass for checking debug info inserted by -debugify, used with the
264/// legacy module pass manager.
265struct CheckDebugifyModulePass : public ModulePass {
266 bool runOnModule(Module &M) override {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000267 return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
268 "CheckModuleDebugify", Strip);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000269 }
270
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000271 CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "")
272 : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000273
274 static char ID; // Pass identification.
275
276private:
277 bool Strip;
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000278 StringRef NameOfWrappedPass;
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000279};
280
281/// FunctionPass for checking debug info inserted by -debugify-function, used
282/// with the legacy module pass manager.
283struct CheckDebugifyFunctionPass : public FunctionPass {
284 bool runOnFunction(Function &F) override {
285 Module &M = *F.getParent();
286 auto FuncIt = F.getIterator();
287 return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
Vedant Kumar4872535e2018-05-24 23:00:23 +0000288 NameOfWrappedPass, "CheckFunctionDebugify",
289 Strip);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000290 }
291
Vedant Kumar4872535e2018-05-24 23:00:23 +0000292 CheckDebugifyFunctionPass(bool Strip = false,
293 StringRef NameOfWrappedPass = "")
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000294 : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass) {}
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000295
296 void getAnalysisUsage(AnalysisUsage &AU) const override {
297 AU.setPreservesAll();
298 }
299
300 static char ID; // Pass identification.
301
302private:
303 bool Strip;
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000304 StringRef NameOfWrappedPass;
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000305};
306
Vedant Kumar195dfd12017-12-08 21:57:28 +0000307} // end anonymous namespace
308
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000309ModulePass *createDebugifyModulePass() {
310 return new DebugifyModulePass();
311}
312
313FunctionPass *createDebugifyFunctionPass() {
314 return new DebugifyFunctionPass();
315}
Vedant Kumar92f7a622018-01-23 20:43:50 +0000316
Vedant Kumar775c7af2018-02-15 21:14:36 +0000317PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000318 applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
Vedant Kumar775c7af2018-02-15 21:14:36 +0000319 return PreservedAnalyses::all();
320}
321
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000322ModulePass *createCheckDebugifyModulePass(bool Strip, StringRef NameOfWrappedPass) {
323 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000324}
325
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000326FunctionPass *createCheckDebugifyFunctionPass(bool Strip, StringRef NameOfWrappedPass) {
327 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass);
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000328}
Vedant Kumar92f7a622018-01-23 20:43:50 +0000329
Vedant Kumar775c7af2018-02-15 21:14:36 +0000330PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
331 ModuleAnalysisManager &) {
Anastasis Grammenosb4344c62018-05-15 23:38:05 +0000332 checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false);
Vedant Kumar775c7af2018-02-15 21:14:36 +0000333 return PreservedAnalyses::all();
334}
335
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000336char DebugifyModulePass::ID = 0;
337static RegisterPass<DebugifyModulePass> DM("debugify",
Vedant Kumar195dfd12017-12-08 21:57:28 +0000338 "Attach debug info to everything");
339
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000340char CheckDebugifyModulePass::ID = 0;
341static RegisterPass<CheckDebugifyModulePass> CDM("check-debugify",
Vedant Kumar195dfd12017-12-08 21:57:28 +0000342 "Check debug info from -debugify");
Vedant Kumar595ba1d2018-05-15 00:29:27 +0000343
344char DebugifyFunctionPass::ID = 0;
345static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
346 "Attach debug info to a function");
347
348char CheckDebugifyFunctionPass::ID = 0;
349static RegisterPass<CheckDebugifyFunctionPass> CDF("check-debugify-function",
350 "Check debug info from -debugify-function");