xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/Debugify.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
1480093f4SDimitry Andric //===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric ///
9480093f4SDimitry Andric /// \file This pass attaches synthetic debug info to everything. It can be used
10480093f4SDimitry Andric /// to create targeted tests for debug info preservation.
11480093f4SDimitry Andric ///
12480093f4SDimitry Andric //===----------------------------------------------------------------------===//
13480093f4SDimitry Andric 
14480093f4SDimitry Andric #include "llvm/Transforms/Utils/Debugify.h"
15480093f4SDimitry Andric #include "llvm/ADT/BitVector.h"
16480093f4SDimitry Andric #include "llvm/ADT/StringExtras.h"
17480093f4SDimitry Andric #include "llvm/IR/DIBuilder.h"
18480093f4SDimitry Andric #include "llvm/IR/DebugInfo.h"
19480093f4SDimitry Andric #include "llvm/IR/InstIterator.h"
20480093f4SDimitry Andric #include "llvm/IR/Instructions.h"
21480093f4SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
22480093f4SDimitry Andric #include "llvm/IR/Module.h"
23*e8d8bef9SDimitry Andric #include "llvm/IR/PassInstrumentation.h"
24480093f4SDimitry Andric #include "llvm/Pass.h"
25480093f4SDimitry Andric #include "llvm/Support/CommandLine.h"
26480093f4SDimitry Andric 
27480093f4SDimitry Andric using namespace llvm;
28480093f4SDimitry Andric 
29480093f4SDimitry Andric namespace {
30480093f4SDimitry Andric 
31480093f4SDimitry Andric cl::opt<bool> Quiet("debugify-quiet",
32480093f4SDimitry Andric                     cl::desc("Suppress verbose debugify output"));
33480093f4SDimitry Andric 
345ffd83dbSDimitry Andric enum class Level {
355ffd83dbSDimitry Andric   Locations,
365ffd83dbSDimitry Andric   LocationsAndVariables
375ffd83dbSDimitry Andric };
385ffd83dbSDimitry Andric cl::opt<Level> DebugifyLevel(
395ffd83dbSDimitry Andric     "debugify-level", cl::desc("Kind of debug info to add"),
405ffd83dbSDimitry Andric     cl::values(clEnumValN(Level::Locations, "locations", "Locations only"),
415ffd83dbSDimitry Andric                clEnumValN(Level::LocationsAndVariables, "location+variables",
425ffd83dbSDimitry Andric                           "Locations and Variables")),
435ffd83dbSDimitry Andric     cl::init(Level::LocationsAndVariables));
445ffd83dbSDimitry Andric 
45480093f4SDimitry Andric raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
46480093f4SDimitry Andric 
47480093f4SDimitry Andric uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
48480093f4SDimitry Andric   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
49480093f4SDimitry Andric }
50480093f4SDimitry Andric 
51480093f4SDimitry Andric bool isFunctionSkipped(Function &F) {
52480093f4SDimitry Andric   return F.isDeclaration() || !F.hasExactDefinition();
53480093f4SDimitry Andric }
54480093f4SDimitry Andric 
55480093f4SDimitry Andric /// Find the basic block's terminating instruction.
56480093f4SDimitry Andric ///
57480093f4SDimitry Andric /// Special care is needed to handle musttail and deopt calls, as these behave
58480093f4SDimitry Andric /// like (but are in fact not) terminators.
59480093f4SDimitry Andric Instruction *findTerminatingInstruction(BasicBlock &BB) {
60480093f4SDimitry Andric   if (auto *I = BB.getTerminatingMustTailCall())
61480093f4SDimitry Andric     return I;
62480093f4SDimitry Andric   if (auto *I = BB.getTerminatingDeoptimizeCall())
63480093f4SDimitry Andric     return I;
64480093f4SDimitry Andric   return BB.getTerminator();
65480093f4SDimitry Andric }
665ffd83dbSDimitry Andric } // end anonymous namespace
67480093f4SDimitry Andric 
685ffd83dbSDimitry Andric bool llvm::applyDebugifyMetadata(
695ffd83dbSDimitry Andric     Module &M, iterator_range<Module::iterator> Functions, StringRef Banner,
705ffd83dbSDimitry Andric     std::function<bool(DIBuilder &DIB, Function &F)> ApplyToMF) {
71480093f4SDimitry Andric   // Skip modules with debug info.
72480093f4SDimitry Andric   if (M.getNamedMetadata("llvm.dbg.cu")) {
73480093f4SDimitry Andric     dbg() << Banner << "Skipping module with debug info\n";
74480093f4SDimitry Andric     return false;
75480093f4SDimitry Andric   }
76480093f4SDimitry Andric 
77480093f4SDimitry Andric   DIBuilder DIB(M);
78480093f4SDimitry Andric   LLVMContext &Ctx = M.getContext();
795ffd83dbSDimitry Andric   auto *Int32Ty = Type::getInt32Ty(Ctx);
80480093f4SDimitry Andric 
81480093f4SDimitry Andric   // Get a DIType which corresponds to Ty.
82480093f4SDimitry Andric   DenseMap<uint64_t, DIType *> TypeCache;
83480093f4SDimitry Andric   auto getCachedDIType = [&](Type *Ty) -> DIType * {
84480093f4SDimitry Andric     uint64_t Size = getAllocSizeInBits(M, Ty);
85480093f4SDimitry Andric     DIType *&DTy = TypeCache[Size];
86480093f4SDimitry Andric     if (!DTy) {
87480093f4SDimitry Andric       std::string Name = "ty" + utostr(Size);
88480093f4SDimitry Andric       DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
89480093f4SDimitry Andric     }
90480093f4SDimitry Andric     return DTy;
91480093f4SDimitry Andric   };
92480093f4SDimitry Andric 
93480093f4SDimitry Andric   unsigned NextLine = 1;
94480093f4SDimitry Andric   unsigned NextVar = 1;
95480093f4SDimitry Andric   auto File = DIB.createFile(M.getName(), "/");
96480093f4SDimitry Andric   auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify",
97480093f4SDimitry Andric                                   /*isOptimized=*/true, "", 0);
98480093f4SDimitry Andric 
99480093f4SDimitry Andric   // Visit each instruction.
100480093f4SDimitry Andric   for (Function &F : Functions) {
101480093f4SDimitry Andric     if (isFunctionSkipped(F))
102480093f4SDimitry Andric       continue;
103480093f4SDimitry Andric 
1045ffd83dbSDimitry Andric     bool InsertedDbgVal = false;
105480093f4SDimitry Andric     auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
106480093f4SDimitry Andric     DISubprogram::DISPFlags SPFlags =
107480093f4SDimitry Andric         DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;
108480093f4SDimitry Andric     if (F.hasPrivateLinkage() || F.hasInternalLinkage())
109480093f4SDimitry Andric       SPFlags |= DISubprogram::SPFlagLocalToUnit;
110480093f4SDimitry Andric     auto SP = DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine,
111480093f4SDimitry Andric                                  SPType, NextLine, DINode::FlagZero, SPFlags);
112480093f4SDimitry Andric     F.setSubprogram(SP);
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric     // Helper that inserts a dbg.value before \p InsertBefore, copying the
1155ffd83dbSDimitry Andric     // location (and possibly the type, if it's non-void) from \p TemplateInst.
1165ffd83dbSDimitry Andric     auto insertDbgVal = [&](Instruction &TemplateInst,
1175ffd83dbSDimitry Andric                             Instruction *InsertBefore) {
1185ffd83dbSDimitry Andric       std::string Name = utostr(NextVar++);
1195ffd83dbSDimitry Andric       Value *V = &TemplateInst;
1205ffd83dbSDimitry Andric       if (TemplateInst.getType()->isVoidTy())
1215ffd83dbSDimitry Andric         V = ConstantInt::get(Int32Ty, 0);
1225ffd83dbSDimitry Andric       const DILocation *Loc = TemplateInst.getDebugLoc().get();
1235ffd83dbSDimitry Andric       auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
1245ffd83dbSDimitry Andric                                              getCachedDIType(V->getType()),
1255ffd83dbSDimitry Andric                                              /*AlwaysPreserve=*/true);
1265ffd83dbSDimitry Andric       DIB.insertDbgValueIntrinsic(V, LocalVar, DIB.createExpression(), Loc,
1275ffd83dbSDimitry Andric                                   InsertBefore);
1285ffd83dbSDimitry Andric     };
1295ffd83dbSDimitry Andric 
130480093f4SDimitry Andric     for (BasicBlock &BB : F) {
131480093f4SDimitry Andric       // Attach debug locations.
132480093f4SDimitry Andric       for (Instruction &I : BB)
133480093f4SDimitry Andric         I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
134480093f4SDimitry Andric 
1355ffd83dbSDimitry Andric       if (DebugifyLevel < Level::LocationsAndVariables)
1365ffd83dbSDimitry Andric         continue;
1375ffd83dbSDimitry Andric 
138480093f4SDimitry Andric       // Inserting debug values into EH pads can break IR invariants.
139480093f4SDimitry Andric       if (BB.isEHPad())
140480093f4SDimitry Andric         continue;
141480093f4SDimitry Andric 
142480093f4SDimitry Andric       // Find the terminating instruction, after which no debug values are
143480093f4SDimitry Andric       // attached.
144480093f4SDimitry Andric       Instruction *LastInst = findTerminatingInstruction(BB);
145480093f4SDimitry Andric       assert(LastInst && "Expected basic block with a terminator");
146480093f4SDimitry Andric 
147480093f4SDimitry Andric       // Maintain an insertion point which can't be invalidated when updates
148480093f4SDimitry Andric       // are made.
149480093f4SDimitry Andric       BasicBlock::iterator InsertPt = BB.getFirstInsertionPt();
150480093f4SDimitry Andric       assert(InsertPt != BB.end() && "Expected to find an insertion point");
151480093f4SDimitry Andric       Instruction *InsertBefore = &*InsertPt;
152480093f4SDimitry Andric 
153480093f4SDimitry Andric       // Attach debug values.
154480093f4SDimitry Andric       for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) {
155480093f4SDimitry Andric         // Skip void-valued instructions.
156480093f4SDimitry Andric         if (I->getType()->isVoidTy())
157480093f4SDimitry Andric           continue;
158480093f4SDimitry Andric 
159480093f4SDimitry Andric         // Phis and EH pads must be grouped at the beginning of the block.
160480093f4SDimitry Andric         // Only advance the insertion point when we finish visiting these.
161480093f4SDimitry Andric         if (!isa<PHINode>(I) && !I->isEHPad())
162480093f4SDimitry Andric           InsertBefore = I->getNextNode();
163480093f4SDimitry Andric 
1645ffd83dbSDimitry Andric         insertDbgVal(*I, InsertBefore);
1655ffd83dbSDimitry Andric         InsertedDbgVal = true;
166480093f4SDimitry Andric       }
167480093f4SDimitry Andric     }
1685ffd83dbSDimitry Andric     // Make sure we emit at least one dbg.value, otherwise MachineDebugify may
1695ffd83dbSDimitry Andric     // not have anything to work with as it goes about inserting DBG_VALUEs.
1705ffd83dbSDimitry Andric     // (It's common for MIR tests to be written containing skeletal IR with
1715ffd83dbSDimitry Andric     // empty functions -- we're still interested in debugifying the MIR within
1725ffd83dbSDimitry Andric     // those tests, and this helps with that.)
1735ffd83dbSDimitry Andric     if (DebugifyLevel == Level::LocationsAndVariables && !InsertedDbgVal) {
1745ffd83dbSDimitry Andric       auto *Term = findTerminatingInstruction(F.getEntryBlock());
1755ffd83dbSDimitry Andric       insertDbgVal(*Term, Term);
1765ffd83dbSDimitry Andric     }
1775ffd83dbSDimitry Andric     if (ApplyToMF)
1785ffd83dbSDimitry Andric       ApplyToMF(DIB, F);
179480093f4SDimitry Andric     DIB.finalizeSubprogram(SP);
180480093f4SDimitry Andric   }
181480093f4SDimitry Andric   DIB.finalize();
182480093f4SDimitry Andric 
183480093f4SDimitry Andric   // Track the number of distinct lines and variables.
184480093f4SDimitry Andric   NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
185480093f4SDimitry Andric   auto addDebugifyOperand = [&](unsigned N) {
186480093f4SDimitry Andric     NMD->addOperand(MDNode::get(
1875ffd83dbSDimitry Andric         Ctx, ValueAsMetadata::getConstant(ConstantInt::get(Int32Ty, N))));
188480093f4SDimitry Andric   };
189480093f4SDimitry Andric   addDebugifyOperand(NextLine - 1); // Original number of lines.
190480093f4SDimitry Andric   addDebugifyOperand(NextVar - 1);  // Original number of variables.
191480093f4SDimitry Andric   assert(NMD->getNumOperands() == 2 &&
192480093f4SDimitry Andric          "llvm.debugify should have exactly 2 operands!");
193480093f4SDimitry Andric 
194480093f4SDimitry Andric   // Claim that this synthetic debug info is valid.
195480093f4SDimitry Andric   StringRef DIVersionKey = "Debug Info Version";
196480093f4SDimitry Andric   if (!M.getModuleFlag(DIVersionKey))
197480093f4SDimitry Andric     M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
198480093f4SDimitry Andric 
199480093f4SDimitry Andric   return true;
200480093f4SDimitry Andric }
201480093f4SDimitry Andric 
202*e8d8bef9SDimitry Andric static bool applyDebugify(Function &F) {
203*e8d8bef9SDimitry Andric   Module &M = *F.getParent();
204*e8d8bef9SDimitry Andric   auto FuncIt = F.getIterator();
205*e8d8bef9SDimitry Andric   return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
206*e8d8bef9SDimitry Andric                                "FunctionDebugify: ", /*ApplyToMF=*/nullptr);
207*e8d8bef9SDimitry Andric }
208*e8d8bef9SDimitry Andric 
209*e8d8bef9SDimitry Andric static bool applyDebugify(Module &M) {
210*e8d8bef9SDimitry Andric   return applyDebugifyMetadata(M, M.functions(),
211*e8d8bef9SDimitry Andric                                "ModuleDebugify: ", /*ApplyToMF=*/nullptr);
212*e8d8bef9SDimitry Andric }
213*e8d8bef9SDimitry Andric 
2145ffd83dbSDimitry Andric bool llvm::stripDebugifyMetadata(Module &M) {
2155ffd83dbSDimitry Andric   bool Changed = false;
2165ffd83dbSDimitry Andric 
2175ffd83dbSDimitry Andric   // Remove the llvm.debugify module-level named metadata.
2185ffd83dbSDimitry Andric   NamedMDNode *DebugifyMD = M.getNamedMetadata("llvm.debugify");
2195ffd83dbSDimitry Andric   if (DebugifyMD) {
2205ffd83dbSDimitry Andric     M.eraseNamedMetadata(DebugifyMD);
2215ffd83dbSDimitry Andric     Changed = true;
2225ffd83dbSDimitry Andric   }
2235ffd83dbSDimitry Andric 
2245ffd83dbSDimitry Andric   // Strip out all debug intrinsics and supporting metadata (subprograms, types,
2255ffd83dbSDimitry Andric   // variables, etc).
2265ffd83dbSDimitry Andric   Changed |= StripDebugInfo(M);
2275ffd83dbSDimitry Andric 
2285ffd83dbSDimitry Andric   // Strip out the dead dbg.value prototype.
2295ffd83dbSDimitry Andric   Function *DbgValF = M.getFunction("llvm.dbg.value");
2305ffd83dbSDimitry Andric   if (DbgValF) {
2315ffd83dbSDimitry Andric     assert(DbgValF->isDeclaration() && DbgValF->use_empty() &&
2325ffd83dbSDimitry Andric            "Not all debug info stripped?");
2335ffd83dbSDimitry Andric     DbgValF->eraseFromParent();
2345ffd83dbSDimitry Andric     Changed = true;
2355ffd83dbSDimitry Andric   }
2365ffd83dbSDimitry Andric 
2375ffd83dbSDimitry Andric   // Strip out the module-level Debug Info Version metadata.
2385ffd83dbSDimitry Andric   // FIXME: There must be an easier way to remove an operand from a NamedMDNode.
2395ffd83dbSDimitry Andric   NamedMDNode *NMD = M.getModuleFlagsMetadata();
2405ffd83dbSDimitry Andric   if (!NMD)
2415ffd83dbSDimitry Andric     return Changed;
242*e8d8bef9SDimitry Andric   SmallVector<MDNode *, 4> Flags(NMD->operands());
2435ffd83dbSDimitry Andric   NMD->clearOperands();
2445ffd83dbSDimitry Andric   for (MDNode *Flag : Flags) {
2455ffd83dbSDimitry Andric     MDString *Key = dyn_cast_or_null<MDString>(Flag->getOperand(1));
2465ffd83dbSDimitry Andric     if (Key->getString() == "Debug Info Version") {
2475ffd83dbSDimitry Andric       Changed = true;
2485ffd83dbSDimitry Andric       continue;
2495ffd83dbSDimitry Andric     }
2505ffd83dbSDimitry Andric     NMD->addOperand(Flag);
2515ffd83dbSDimitry Andric   }
2525ffd83dbSDimitry Andric   // If we left it empty we might as well remove it.
2535ffd83dbSDimitry Andric   if (NMD->getNumOperands() == 0)
2545ffd83dbSDimitry Andric     NMD->eraseFromParent();
2555ffd83dbSDimitry Andric 
2565ffd83dbSDimitry Andric   return Changed;
2575ffd83dbSDimitry Andric }
2585ffd83dbSDimitry Andric 
2595ffd83dbSDimitry Andric namespace {
260480093f4SDimitry Andric /// Return true if a mis-sized diagnostic is issued for \p DVI.
261480093f4SDimitry Andric bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
262480093f4SDimitry Andric   // The size of a dbg.value's value operand should match the size of the
263480093f4SDimitry Andric   // variable it corresponds to.
264480093f4SDimitry Andric   //
265480093f4SDimitry Andric   // TODO: This, along with a check for non-null value operands, should be
266480093f4SDimitry Andric   // promoted to verifier failures.
267480093f4SDimitry Andric   Value *V = DVI->getValue();
268480093f4SDimitry Andric   if (!V)
269480093f4SDimitry Andric     return false;
270480093f4SDimitry Andric 
271480093f4SDimitry Andric   // For now, don't try to interpret anything more complicated than an empty
272480093f4SDimitry Andric   // DIExpression. Eventually we should try to handle OP_deref and fragments.
273480093f4SDimitry Andric   if (DVI->getExpression()->getNumElements())
274480093f4SDimitry Andric     return false;
275480093f4SDimitry Andric 
276480093f4SDimitry Andric   Type *Ty = V->getType();
277480093f4SDimitry Andric   uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
278480093f4SDimitry Andric   Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits();
279480093f4SDimitry Andric   if (!ValueOperandSize || !DbgVarSize)
280480093f4SDimitry Andric     return false;
281480093f4SDimitry Andric 
282480093f4SDimitry Andric   bool HasBadSize = false;
283480093f4SDimitry Andric   if (Ty->isIntegerTy()) {
284480093f4SDimitry Andric     auto Signedness = DVI->getVariable()->getSignedness();
285480093f4SDimitry Andric     if (Signedness && *Signedness == DIBasicType::Signedness::Signed)
286480093f4SDimitry Andric       HasBadSize = ValueOperandSize < *DbgVarSize;
287480093f4SDimitry Andric   } else {
288480093f4SDimitry Andric     HasBadSize = ValueOperandSize != *DbgVarSize;
289480093f4SDimitry Andric   }
290480093f4SDimitry Andric 
291480093f4SDimitry Andric   if (HasBadSize) {
292480093f4SDimitry Andric     dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
293480093f4SDimitry Andric           << ", but its variable has size " << *DbgVarSize << ": ";
294480093f4SDimitry Andric     DVI->print(dbg());
295480093f4SDimitry Andric     dbg() << "\n";
296480093f4SDimitry Andric   }
297480093f4SDimitry Andric   return HasBadSize;
298480093f4SDimitry Andric }
299480093f4SDimitry Andric 
300480093f4SDimitry Andric bool checkDebugifyMetadata(Module &M,
301480093f4SDimitry Andric                            iterator_range<Module::iterator> Functions,
302480093f4SDimitry Andric                            StringRef NameOfWrappedPass, StringRef Banner,
303480093f4SDimitry Andric                            bool Strip, DebugifyStatsMap *StatsMap) {
304480093f4SDimitry Andric   // Skip modules without debugify metadata.
305480093f4SDimitry Andric   NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
306480093f4SDimitry Andric   if (!NMD) {
3075ffd83dbSDimitry Andric     dbg() << Banner << ": Skipping module without debugify metadata\n";
308480093f4SDimitry Andric     return false;
309480093f4SDimitry Andric   }
310480093f4SDimitry Andric 
311480093f4SDimitry Andric   auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
312480093f4SDimitry Andric     return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
313480093f4SDimitry Andric         ->getZExtValue();
314480093f4SDimitry Andric   };
315480093f4SDimitry Andric   assert(NMD->getNumOperands() == 2 &&
316480093f4SDimitry Andric          "llvm.debugify should have exactly 2 operands!");
317480093f4SDimitry Andric   unsigned OriginalNumLines = getDebugifyOperand(0);
318480093f4SDimitry Andric   unsigned OriginalNumVars = getDebugifyOperand(1);
319480093f4SDimitry Andric   bool HasErrors = false;
320480093f4SDimitry Andric 
321480093f4SDimitry Andric   // Track debug info loss statistics if able.
322480093f4SDimitry Andric   DebugifyStatistics *Stats = nullptr;
323480093f4SDimitry Andric   if (StatsMap && !NameOfWrappedPass.empty())
324480093f4SDimitry Andric     Stats = &StatsMap->operator[](NameOfWrappedPass);
325480093f4SDimitry Andric 
326480093f4SDimitry Andric   BitVector MissingLines{OriginalNumLines, true};
327480093f4SDimitry Andric   BitVector MissingVars{OriginalNumVars, true};
328480093f4SDimitry Andric   for (Function &F : Functions) {
329480093f4SDimitry Andric     if (isFunctionSkipped(F))
330480093f4SDimitry Andric       continue;
331480093f4SDimitry Andric 
332480093f4SDimitry Andric     // Find missing lines.
333480093f4SDimitry Andric     for (Instruction &I : instructions(F)) {
3345ffd83dbSDimitry Andric       if (isa<DbgValueInst>(&I) || isa<PHINode>(&I))
335480093f4SDimitry Andric         continue;
336480093f4SDimitry Andric 
337480093f4SDimitry Andric       auto DL = I.getDebugLoc();
338480093f4SDimitry Andric       if (DL && DL.getLine() != 0) {
339480093f4SDimitry Andric         MissingLines.reset(DL.getLine() - 1);
340480093f4SDimitry Andric         continue;
341480093f4SDimitry Andric       }
342480093f4SDimitry Andric 
343480093f4SDimitry Andric       if (!DL) {
3445ffd83dbSDimitry Andric         dbg() << "WARNING: Instruction with empty DebugLoc in function ";
345480093f4SDimitry Andric         dbg() << F.getName() << " --";
346480093f4SDimitry Andric         I.print(dbg());
347480093f4SDimitry Andric         dbg() << "\n";
348480093f4SDimitry Andric       }
349480093f4SDimitry Andric     }
350480093f4SDimitry Andric 
351480093f4SDimitry Andric     // Find missing variables and mis-sized debug values.
352480093f4SDimitry Andric     for (Instruction &I : instructions(F)) {
353480093f4SDimitry Andric       auto *DVI = dyn_cast<DbgValueInst>(&I);
354480093f4SDimitry Andric       if (!DVI)
355480093f4SDimitry Andric         continue;
356480093f4SDimitry Andric 
357480093f4SDimitry Andric       unsigned Var = ~0U;
358480093f4SDimitry Andric       (void)to_integer(DVI->getVariable()->getName(), Var, 10);
359480093f4SDimitry Andric       assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
360480093f4SDimitry Andric       bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI);
361480093f4SDimitry Andric       if (!HasBadSize)
362480093f4SDimitry Andric         MissingVars.reset(Var - 1);
363480093f4SDimitry Andric       HasErrors |= HasBadSize;
364480093f4SDimitry Andric     }
365480093f4SDimitry Andric   }
366480093f4SDimitry Andric 
367480093f4SDimitry Andric   // Print the results.
368480093f4SDimitry Andric   for (unsigned Idx : MissingLines.set_bits())
369480093f4SDimitry Andric     dbg() << "WARNING: Missing line " << Idx + 1 << "\n";
370480093f4SDimitry Andric 
371480093f4SDimitry Andric   for (unsigned Idx : MissingVars.set_bits())
372480093f4SDimitry Andric     dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";
373480093f4SDimitry Andric 
374480093f4SDimitry Andric   // Update DI loss statistics.
375480093f4SDimitry Andric   if (Stats) {
376480093f4SDimitry Andric     Stats->NumDbgLocsExpected += OriginalNumLines;
377480093f4SDimitry Andric     Stats->NumDbgLocsMissing += MissingLines.count();
378480093f4SDimitry Andric     Stats->NumDbgValuesExpected += OriginalNumVars;
379480093f4SDimitry Andric     Stats->NumDbgValuesMissing += MissingVars.count();
380480093f4SDimitry Andric   }
381480093f4SDimitry Andric 
382480093f4SDimitry Andric   dbg() << Banner;
383480093f4SDimitry Andric   if (!NameOfWrappedPass.empty())
384480093f4SDimitry Andric     dbg() << " [" << NameOfWrappedPass << "]";
385480093f4SDimitry Andric   dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
386480093f4SDimitry Andric 
3875ffd83dbSDimitry Andric   // Strip debugify metadata if required.
3885ffd83dbSDimitry Andric   if (Strip)
3895ffd83dbSDimitry Andric     return stripDebugifyMetadata(M);
390480093f4SDimitry Andric 
391480093f4SDimitry Andric   return false;
392480093f4SDimitry Andric }
393480093f4SDimitry Andric 
394480093f4SDimitry Andric /// ModulePass for attaching synthetic debug info to everything, used with the
395480093f4SDimitry Andric /// legacy module pass manager.
396480093f4SDimitry Andric struct DebugifyModulePass : public ModulePass {
397*e8d8bef9SDimitry Andric   bool runOnModule(Module &M) override { return applyDebugify(M); }
398480093f4SDimitry Andric 
399480093f4SDimitry Andric   DebugifyModulePass() : ModulePass(ID) {}
400480093f4SDimitry Andric 
401480093f4SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
402480093f4SDimitry Andric     AU.setPreservesAll();
403480093f4SDimitry Andric   }
404480093f4SDimitry Andric 
405480093f4SDimitry Andric   static char ID; // Pass identification.
406480093f4SDimitry Andric };
407480093f4SDimitry Andric 
408480093f4SDimitry Andric /// FunctionPass for attaching synthetic debug info to instructions within a
409480093f4SDimitry Andric /// single function, used with the legacy module pass manager.
410480093f4SDimitry Andric struct DebugifyFunctionPass : public FunctionPass {
411*e8d8bef9SDimitry Andric   bool runOnFunction(Function &F) override { return applyDebugify(F); }
412480093f4SDimitry Andric 
413480093f4SDimitry Andric   DebugifyFunctionPass() : FunctionPass(ID) {}
414480093f4SDimitry Andric 
415480093f4SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
416480093f4SDimitry Andric     AU.setPreservesAll();
417480093f4SDimitry Andric   }
418480093f4SDimitry Andric 
419480093f4SDimitry Andric   static char ID; // Pass identification.
420480093f4SDimitry Andric };
421480093f4SDimitry Andric 
422480093f4SDimitry Andric /// ModulePass for checking debug info inserted by -debugify, used with the
423480093f4SDimitry Andric /// legacy module pass manager.
424480093f4SDimitry Andric struct CheckDebugifyModulePass : public ModulePass {
425480093f4SDimitry Andric   bool runOnModule(Module &M) override {
426480093f4SDimitry Andric     return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
427480093f4SDimitry Andric                                  "CheckModuleDebugify", Strip, StatsMap);
428480093f4SDimitry Andric   }
429480093f4SDimitry Andric 
430480093f4SDimitry Andric   CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
431480093f4SDimitry Andric                           DebugifyStatsMap *StatsMap = nullptr)
432480093f4SDimitry Andric       : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
433480093f4SDimitry Andric         StatsMap(StatsMap) {}
434480093f4SDimitry Andric 
435480093f4SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
436480093f4SDimitry Andric     AU.setPreservesAll();
437480093f4SDimitry Andric   }
438480093f4SDimitry Andric 
439480093f4SDimitry Andric   static char ID; // Pass identification.
440480093f4SDimitry Andric 
441480093f4SDimitry Andric private:
442480093f4SDimitry Andric   bool Strip;
443480093f4SDimitry Andric   StringRef NameOfWrappedPass;
444480093f4SDimitry Andric   DebugifyStatsMap *StatsMap;
445480093f4SDimitry Andric };
446480093f4SDimitry Andric 
447480093f4SDimitry Andric /// FunctionPass for checking debug info inserted by -debugify-function, used
448480093f4SDimitry Andric /// with the legacy module pass manager.
449480093f4SDimitry Andric struct CheckDebugifyFunctionPass : public FunctionPass {
450480093f4SDimitry Andric   bool runOnFunction(Function &F) override {
451480093f4SDimitry Andric     Module &M = *F.getParent();
452480093f4SDimitry Andric     auto FuncIt = F.getIterator();
453480093f4SDimitry Andric     return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
454480093f4SDimitry Andric                                  NameOfWrappedPass, "CheckFunctionDebugify",
455480093f4SDimitry Andric                                  Strip, StatsMap);
456480093f4SDimitry Andric   }
457480093f4SDimitry Andric 
458480093f4SDimitry Andric   CheckDebugifyFunctionPass(bool Strip = false,
459480093f4SDimitry Andric                             StringRef NameOfWrappedPass = "",
460480093f4SDimitry Andric                             DebugifyStatsMap *StatsMap = nullptr)
461480093f4SDimitry Andric       : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
462480093f4SDimitry Andric         StatsMap(StatsMap) {}
463480093f4SDimitry Andric 
464480093f4SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
465480093f4SDimitry Andric     AU.setPreservesAll();
466480093f4SDimitry Andric   }
467480093f4SDimitry Andric 
468480093f4SDimitry Andric   static char ID; // Pass identification.
469480093f4SDimitry Andric 
470480093f4SDimitry Andric private:
471480093f4SDimitry Andric   bool Strip;
472480093f4SDimitry Andric   StringRef NameOfWrappedPass;
473480093f4SDimitry Andric   DebugifyStatsMap *StatsMap;
474480093f4SDimitry Andric };
475480093f4SDimitry Andric 
476480093f4SDimitry Andric } // end anonymous namespace
477480093f4SDimitry Andric 
478*e8d8bef9SDimitry Andric void llvm::exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map) {
479*e8d8bef9SDimitry Andric   std::error_code EC;
480*e8d8bef9SDimitry Andric   raw_fd_ostream OS{Path, EC};
481*e8d8bef9SDimitry Andric   if (EC) {
482*e8d8bef9SDimitry Andric     errs() << "Could not open file: " << EC.message() << ", " << Path << '\n';
483*e8d8bef9SDimitry Andric     return;
484*e8d8bef9SDimitry Andric   }
485480093f4SDimitry Andric 
486*e8d8bef9SDimitry Andric   OS << "Pass Name" << ',' << "# of missing debug values" << ','
487*e8d8bef9SDimitry Andric      << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
488*e8d8bef9SDimitry Andric      << "Missing/Expected location ratio" << '\n';
489*e8d8bef9SDimitry Andric   for (const auto &Entry : Map) {
490*e8d8bef9SDimitry Andric     StringRef Pass = Entry.first;
491*e8d8bef9SDimitry Andric     DebugifyStatistics Stats = Entry.second;
492*e8d8bef9SDimitry Andric 
493*e8d8bef9SDimitry Andric     OS << Pass << ',' << Stats.NumDbgValuesMissing << ','
494*e8d8bef9SDimitry Andric        << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ','
495*e8d8bef9SDimitry Andric        << Stats.getEmptyLocationRatio() << '\n';
496*e8d8bef9SDimitry Andric   }
497*e8d8bef9SDimitry Andric }
498*e8d8bef9SDimitry Andric 
499*e8d8bef9SDimitry Andric ModulePass *llvm::createDebugifyModulePass() {
500*e8d8bef9SDimitry Andric   return new DebugifyModulePass();
501*e8d8bef9SDimitry Andric }
502*e8d8bef9SDimitry Andric 
503*e8d8bef9SDimitry Andric FunctionPass *llvm::createDebugifyFunctionPass() {
504480093f4SDimitry Andric   return new DebugifyFunctionPass();
505480093f4SDimitry Andric }
506480093f4SDimitry Andric 
507480093f4SDimitry Andric PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
5085ffd83dbSDimitry Andric   applyDebugifyMetadata(M, M.functions(),
5095ffd83dbSDimitry Andric                         "ModuleDebugify: ", /*ApplyToMF*/ nullptr);
510480093f4SDimitry Andric   return PreservedAnalyses::all();
511480093f4SDimitry Andric }
512480093f4SDimitry Andric 
513*e8d8bef9SDimitry Andric ModulePass *llvm::createCheckDebugifyModulePass(bool Strip,
514480093f4SDimitry Andric                                                 StringRef NameOfWrappedPass,
515480093f4SDimitry Andric                                                 DebugifyStatsMap *StatsMap) {
516480093f4SDimitry Andric   return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
517480093f4SDimitry Andric }
518480093f4SDimitry Andric 
519*e8d8bef9SDimitry Andric FunctionPass *
520*e8d8bef9SDimitry Andric llvm::createCheckDebugifyFunctionPass(bool Strip, StringRef NameOfWrappedPass,
521480093f4SDimitry Andric                                       DebugifyStatsMap *StatsMap) {
522480093f4SDimitry Andric   return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
523480093f4SDimitry Andric }
524480093f4SDimitry Andric 
525480093f4SDimitry Andric PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
526480093f4SDimitry Andric                                               ModuleAnalysisManager &) {
527480093f4SDimitry Andric   checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false,
528480093f4SDimitry Andric                         nullptr);
529480093f4SDimitry Andric   return PreservedAnalyses::all();
530480093f4SDimitry Andric }
531480093f4SDimitry Andric 
532*e8d8bef9SDimitry Andric static bool isIgnoredPass(StringRef PassID) {
533*e8d8bef9SDimitry Andric   return isSpecialPass(PassID, {"PassManager", "PassAdaptor",
534*e8d8bef9SDimitry Andric                                 "AnalysisManagerProxy", "PrintFunctionPass",
535*e8d8bef9SDimitry Andric                                 "PrintModulePass", "BitcodeWriterPass",
536*e8d8bef9SDimitry Andric                                 "ThinLTOBitcodeWriterPass", "VerifierPass"});
537*e8d8bef9SDimitry Andric }
538*e8d8bef9SDimitry Andric 
539*e8d8bef9SDimitry Andric void DebugifyEachInstrumentation::registerCallbacks(
540*e8d8bef9SDimitry Andric     PassInstrumentationCallbacks &PIC) {
541*e8d8bef9SDimitry Andric   PIC.registerBeforeNonSkippedPassCallback([](StringRef P, Any IR) {
542*e8d8bef9SDimitry Andric     if (isIgnoredPass(P))
543*e8d8bef9SDimitry Andric       return;
544*e8d8bef9SDimitry Andric     if (any_isa<const Function *>(IR))
545*e8d8bef9SDimitry Andric       applyDebugify(*const_cast<Function *>(any_cast<const Function *>(IR)));
546*e8d8bef9SDimitry Andric     else if (any_isa<const Module *>(IR))
547*e8d8bef9SDimitry Andric       applyDebugify(*const_cast<Module *>(any_cast<const Module *>(IR)));
548*e8d8bef9SDimitry Andric   });
549*e8d8bef9SDimitry Andric   PIC.registerAfterPassCallback([this](StringRef P, Any IR,
550*e8d8bef9SDimitry Andric                                        const PreservedAnalyses &PassPA) {
551*e8d8bef9SDimitry Andric     if (isIgnoredPass(P))
552*e8d8bef9SDimitry Andric       return;
553*e8d8bef9SDimitry Andric     if (any_isa<const Function *>(IR)) {
554*e8d8bef9SDimitry Andric       auto &F = *const_cast<Function *>(any_cast<const Function *>(IR));
555*e8d8bef9SDimitry Andric       Module &M = *F.getParent();
556*e8d8bef9SDimitry Andric       auto It = F.getIterator();
557*e8d8bef9SDimitry Andric       checkDebugifyMetadata(M, make_range(It, std::next(It)), P,
558*e8d8bef9SDimitry Andric                             "CheckFunctionDebugify", /*Strip=*/true, &StatsMap);
559*e8d8bef9SDimitry Andric     } else if (any_isa<const Module *>(IR)) {
560*e8d8bef9SDimitry Andric       auto &M = *const_cast<Module *>(any_cast<const Module *>(IR));
561*e8d8bef9SDimitry Andric       checkDebugifyMetadata(M, M.functions(), P, "CheckModuleDebugify",
562*e8d8bef9SDimitry Andric                             /*Strip=*/true, &StatsMap);
563*e8d8bef9SDimitry Andric     }
564*e8d8bef9SDimitry Andric   });
565*e8d8bef9SDimitry Andric }
566*e8d8bef9SDimitry Andric 
567480093f4SDimitry Andric char DebugifyModulePass::ID = 0;
568480093f4SDimitry Andric static RegisterPass<DebugifyModulePass> DM("debugify",
569480093f4SDimitry Andric                                            "Attach debug info to everything");
570480093f4SDimitry Andric 
571480093f4SDimitry Andric char CheckDebugifyModulePass::ID = 0;
572480093f4SDimitry Andric static RegisterPass<CheckDebugifyModulePass>
573480093f4SDimitry Andric     CDM("check-debugify", "Check debug info from -debugify");
574480093f4SDimitry Andric 
575480093f4SDimitry Andric char DebugifyFunctionPass::ID = 0;
576480093f4SDimitry Andric static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
577480093f4SDimitry Andric                                              "Attach debug info to a function");
578480093f4SDimitry Andric 
579480093f4SDimitry Andric char CheckDebugifyFunctionPass::ID = 0;
580480093f4SDimitry Andric static RegisterPass<CheckDebugifyFunctionPass>
581480093f4SDimitry Andric     CDF("check-debugify-function", "Check debug info from -debugify-function");
582