[ARM] Add support for MVE pre and post inc loads and stores
[llvm-core.git] / tools / opt / Debugify.cpp
blob222cc702bc1f5da195fa85322b505067b8edc51a
1 //===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file This pass attaches synthetic debug info to everything. It can be used
10 /// to create targeted tests for debug info preservation.
11 ///
12 //===----------------------------------------------------------------------===//
14 #include "Debugify.h"
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"
33 using namespace llvm;
35 namespace {
37 cl::opt<bool> Quiet("debugify-quiet",
38 cl::desc("Suppress verbose debugify output"));
40 raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
42 uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
43 return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
46 bool isFunctionSkipped(Function &F) {
47 return F.isDeclaration() || !F.hasExactDefinition();
50 /// Find the basic block's terminating instruction.
51 ///
52 /// Special care is needed to handle musttail and deopt calls, as these behave
53 /// like (but are in fact not) terminators.
54 Instruction *findTerminatingInstruction(BasicBlock &BB) {
55 if (auto *I = BB.getTerminatingMustTailCall())
56 return I;
57 if (auto *I = BB.getTerminatingDeoptimizeCall())
58 return I;
59 return BB.getTerminator();
62 bool applyDebugifyMetadata(Module &M,
63 iterator_range<Module::iterator> Functions,
64 StringRef Banner) {
65 // Skip modules with debug info.
66 if (M.getNamedMetadata("llvm.dbg.cu")) {
67 dbg() << Banner << "Skipping module with debug info\n";
68 return false;
71 DIBuilder DIB(M);
72 LLVMContext &Ctx = M.getContext();
74 // Get a DIType which corresponds to Ty.
75 DenseMap<uint64_t, DIType *> TypeCache;
76 auto getCachedDIType = [&](Type *Ty) -> DIType * {
77 uint64_t Size = getAllocSizeInBits(M, Ty);
78 DIType *&DTy = TypeCache[Size];
79 if (!DTy) {
80 std::string Name = "ty" + utostr(Size);
81 DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
83 return DTy;
86 unsigned NextLine = 1;
87 unsigned NextVar = 1;
88 auto File = DIB.createFile(M.getName(), "/");
89 auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify",
90 /*isOptimized=*/true, "", 0);
92 // Visit each instruction.
93 for (Function &F : Functions) {
94 if (isFunctionSkipped(F))
95 continue;
97 auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
98 DISubprogram::DISPFlags SPFlags =
99 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;
100 if (F.hasPrivateLinkage() || F.hasInternalLinkage())
101 SPFlags |= DISubprogram::SPFlagLocalToUnit;
102 auto SP = DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine,
103 SPType, NextLine, DINode::FlagZero, SPFlags);
104 F.setSubprogram(SP);
105 for (BasicBlock &BB : F) {
106 // Attach debug locations.
107 for (Instruction &I : BB)
108 I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
110 // Inserting debug values into EH pads can break IR invariants.
111 if (BB.isEHPad())
112 continue;
114 // Find the terminating instruction, after which no debug values are
115 // attached.
116 Instruction *LastInst = findTerminatingInstruction(BB);
117 assert(LastInst && "Expected basic block with a terminator");
119 // Maintain an insertion point which can't be invalidated when updates
120 // are made.
121 BasicBlock::iterator InsertPt = BB.getFirstInsertionPt();
122 assert(InsertPt != BB.end() && "Expected to find an insertion point");
123 Instruction *InsertBefore = &*InsertPt;
125 // Attach debug values.
126 for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) {
127 // Skip void-valued instructions.
128 if (I->getType()->isVoidTy())
129 continue;
131 // Phis and EH pads must be grouped at the beginning of the block.
132 // Only advance the insertion point when we finish visiting these.
133 if (!isa<PHINode>(I) && !I->isEHPad())
134 InsertBefore = I->getNextNode();
136 std::string Name = utostr(NextVar++);
137 const DILocation *Loc = I->getDebugLoc().get();
138 auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
139 getCachedDIType(I->getType()),
140 /*AlwaysPreserve=*/true);
141 DIB.insertDbgValueIntrinsic(I, LocalVar, DIB.createExpression(), Loc,
142 InsertBefore);
145 DIB.finalizeSubprogram(SP);
147 DIB.finalize();
149 // Track the number of distinct lines and variables.
150 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
151 auto *IntTy = Type::getInt32Ty(Ctx);
152 auto addDebugifyOperand = [&](unsigned N) {
153 NMD->addOperand(MDNode::get(
154 Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
156 addDebugifyOperand(NextLine - 1); // Original number of lines.
157 addDebugifyOperand(NextVar - 1); // Original number of variables.
158 assert(NMD->getNumOperands() == 2 &&
159 "llvm.debugify should have exactly 2 operands!");
161 // Claim that this synthetic debug info is valid.
162 StringRef DIVersionKey = "Debug Info Version";
163 if (!M.getModuleFlag(DIVersionKey))
164 M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
166 return true;
169 /// Return true if a mis-sized diagnostic is issued for \p DVI.
170 bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
171 // The size of a dbg.value's value operand should match the size of the
172 // variable it corresponds to.
174 // TODO: This, along with a check for non-null value operands, should be
175 // promoted to verifier failures.
176 Value *V = DVI->getValue();
177 if (!V)
178 return false;
180 // For now, don't try to interpret anything more complicated than an empty
181 // DIExpression. Eventually we should try to handle OP_deref and fragments.
182 if (DVI->getExpression()->getNumElements())
183 return false;
185 Type *Ty = V->getType();
186 uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
187 Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits();
188 if (!ValueOperandSize || !DbgVarSize)
189 return false;
191 bool HasBadSize = false;
192 if (Ty->isIntegerTy()) {
193 auto Signedness = DVI->getVariable()->getSignedness();
194 if (Signedness && *Signedness == DIBasicType::Signedness::Signed)
195 HasBadSize = ValueOperandSize < *DbgVarSize;
196 } else {
197 HasBadSize = ValueOperandSize != *DbgVarSize;
200 if (HasBadSize) {
201 dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
202 << ", but its variable has size " << *DbgVarSize << ": ";
203 DVI->print(dbg());
204 dbg() << "\n";
206 return HasBadSize;
209 bool checkDebugifyMetadata(Module &M,
210 iterator_range<Module::iterator> Functions,
211 StringRef NameOfWrappedPass, StringRef Banner,
212 bool Strip, DebugifyStatsMap *StatsMap) {
213 // Skip modules without debugify metadata.
214 NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
215 if (!NMD) {
216 dbg() << Banner << "Skipping module without debugify metadata\n";
217 return false;
220 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
221 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
222 ->getZExtValue();
224 assert(NMD->getNumOperands() == 2 &&
225 "llvm.debugify should have exactly 2 operands!");
226 unsigned OriginalNumLines = getDebugifyOperand(0);
227 unsigned OriginalNumVars = getDebugifyOperand(1);
228 bool HasErrors = false;
230 // Track debug info loss statistics if able.
231 DebugifyStatistics *Stats = nullptr;
232 if (StatsMap && !NameOfWrappedPass.empty())
233 Stats = &StatsMap->operator[](NameOfWrappedPass);
235 BitVector MissingLines{OriginalNumLines, true};
236 BitVector MissingVars{OriginalNumVars, true};
237 for (Function &F : Functions) {
238 if (isFunctionSkipped(F))
239 continue;
241 // Find missing lines.
242 for (Instruction &I : instructions(F)) {
243 if (isa<DbgValueInst>(&I))
244 continue;
246 auto DL = I.getDebugLoc();
247 if (DL && DL.getLine() != 0) {
248 MissingLines.reset(DL.getLine() - 1);
249 continue;
252 if (!DL) {
253 dbg() << "ERROR: Instruction with empty DebugLoc in function ";
254 dbg() << F.getName() << " --";
255 I.print(dbg());
256 dbg() << "\n";
257 HasErrors = true;
261 // Find missing variables and mis-sized debug values.
262 for (Instruction &I : instructions(F)) {
263 auto *DVI = dyn_cast<DbgValueInst>(&I);
264 if (!DVI)
265 continue;
267 unsigned Var = ~0U;
268 (void)to_integer(DVI->getVariable()->getName(), Var, 10);
269 assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
270 bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI);
271 if (!HasBadSize)
272 MissingVars.reset(Var - 1);
273 HasErrors |= HasBadSize;
277 // Print the results.
278 for (unsigned Idx : MissingLines.set_bits())
279 dbg() << "WARNING: Missing line " << Idx + 1 << "\n";
281 for (unsigned Idx : MissingVars.set_bits())
282 dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";
284 // Update DI loss statistics.
285 if (Stats) {
286 Stats->NumDbgLocsExpected += OriginalNumLines;
287 Stats->NumDbgLocsMissing += MissingLines.count();
288 Stats->NumDbgValuesExpected += OriginalNumVars;
289 Stats->NumDbgValuesMissing += MissingVars.count();
292 dbg() << Banner;
293 if (!NameOfWrappedPass.empty())
294 dbg() << " [" << NameOfWrappedPass << "]";
295 dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
297 // Strip the Debugify Metadata if required.
298 if (Strip) {
299 StripDebugInfo(M);
300 M.eraseNamedMetadata(NMD);
301 return true;
304 return false;
307 /// ModulePass for attaching synthetic debug info to everything, used with the
308 /// legacy module pass manager.
309 struct DebugifyModulePass : public ModulePass {
310 bool runOnModule(Module &M) override {
311 return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
314 DebugifyModulePass() : ModulePass(ID) {}
316 void getAnalysisUsage(AnalysisUsage &AU) const override {
317 AU.setPreservesAll();
320 static char ID; // Pass identification.
323 /// FunctionPass for attaching synthetic debug info to instructions within a
324 /// single function, used with the legacy module pass manager.
325 struct DebugifyFunctionPass : public FunctionPass {
326 bool runOnFunction(Function &F) override {
327 Module &M = *F.getParent();
328 auto FuncIt = F.getIterator();
329 return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
330 "FunctionDebugify: ");
333 DebugifyFunctionPass() : FunctionPass(ID) {}
335 void getAnalysisUsage(AnalysisUsage &AU) const override {
336 AU.setPreservesAll();
339 static char ID; // Pass identification.
342 /// ModulePass for checking debug info inserted by -debugify, used with the
343 /// legacy module pass manager.
344 struct CheckDebugifyModulePass : public ModulePass {
345 bool runOnModule(Module &M) override {
346 return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
347 "CheckModuleDebugify", Strip, StatsMap);
350 CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
351 DebugifyStatsMap *StatsMap = nullptr)
352 : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
353 StatsMap(StatsMap) {}
355 void getAnalysisUsage(AnalysisUsage &AU) const override {
356 AU.setPreservesAll();
359 static char ID; // Pass identification.
361 private:
362 bool Strip;
363 StringRef NameOfWrappedPass;
364 DebugifyStatsMap *StatsMap;
367 /// FunctionPass for checking debug info inserted by -debugify-function, used
368 /// with the legacy module pass manager.
369 struct CheckDebugifyFunctionPass : public FunctionPass {
370 bool runOnFunction(Function &F) override {
371 Module &M = *F.getParent();
372 auto FuncIt = F.getIterator();
373 return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
374 NameOfWrappedPass, "CheckFunctionDebugify",
375 Strip, StatsMap);
378 CheckDebugifyFunctionPass(bool Strip = false,
379 StringRef NameOfWrappedPass = "",
380 DebugifyStatsMap *StatsMap = nullptr)
381 : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
382 StatsMap(StatsMap) {}
384 void getAnalysisUsage(AnalysisUsage &AU) const override {
385 AU.setPreservesAll();
388 static char ID; // Pass identification.
390 private:
391 bool Strip;
392 StringRef NameOfWrappedPass;
393 DebugifyStatsMap *StatsMap;
396 } // end anonymous namespace
398 void exportDebugifyStats(llvm::StringRef Path, const DebugifyStatsMap &Map) {
399 std::error_code EC;
400 raw_fd_ostream OS{Path, EC};
401 if (EC) {
402 errs() << "Could not open file: " << EC.message() << ", " << Path << '\n';
403 return;
406 OS << "Pass Name" << ',' << "# of missing debug values" << ','
407 << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
408 << "Missing/Expected location ratio" << '\n';
409 for (const auto &Entry : Map) {
410 StringRef Pass = Entry.first;
411 DebugifyStatistics Stats = Entry.second;
413 OS << Pass << ',' << Stats.NumDbgValuesMissing << ','
414 << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ','
415 << Stats.getEmptyLocationRatio() << '\n';
419 ModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); }
421 FunctionPass *createDebugifyFunctionPass() {
422 return new DebugifyFunctionPass();
425 PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
426 applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
427 return PreservedAnalyses::all();
430 ModulePass *createCheckDebugifyModulePass(bool Strip,
431 StringRef NameOfWrappedPass,
432 DebugifyStatsMap *StatsMap) {
433 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
436 FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
437 StringRef NameOfWrappedPass,
438 DebugifyStatsMap *StatsMap) {
439 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
442 PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
443 ModuleAnalysisManager &) {
444 checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false,
445 nullptr);
446 return PreservedAnalyses::all();
449 char DebugifyModulePass::ID = 0;
450 static RegisterPass<DebugifyModulePass> DM("debugify",
451 "Attach debug info to everything");
453 char CheckDebugifyModulePass::ID = 0;
454 static RegisterPass<CheckDebugifyModulePass>
455 CDM("check-debugify", "Check debug info from -debugify");
457 char DebugifyFunctionPass::ID = 0;
458 static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
459 "Attach debug info to a function");
461 char CheckDebugifyFunctionPass::ID = 0;
462 static RegisterPass<CheckDebugifyFunctionPass>
463 CDF("check-debugify-function", "Check debug info from -debugify-function");