1356843Sdim//===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
2356843Sdim//
3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4356843Sdim// See https://llvm.org/LICENSE.txt for license information.
5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6356843Sdim//
7356843Sdim//===----------------------------------------------------------------------===//
8356843Sdim///
9356843Sdim/// \file This pass attaches synthetic debug info to everything. It can be used
10356843Sdim/// to create targeted tests for debug info preservation.
11356843Sdim///
12356843Sdim//===----------------------------------------------------------------------===//
13356843Sdim
14356843Sdim#include "llvm/Transforms/Utils/Debugify.h"
15356843Sdim#include "llvm/ADT/BitVector.h"
16356843Sdim#include "llvm/ADT/StringExtras.h"
17356843Sdim#include "llvm/IR/DIBuilder.h"
18356843Sdim#include "llvm/IR/DebugInfo.h"
19356843Sdim#include "llvm/IR/InstIterator.h"
20356843Sdim#include "llvm/IR/Instructions.h"
21356843Sdim#include "llvm/IR/IntrinsicInst.h"
22356843Sdim#include "llvm/IR/Module.h"
23356843Sdim#include "llvm/Pass.h"
24356843Sdim#include "llvm/Support/CommandLine.h"
25356843Sdim
26356843Sdimusing namespace llvm;
27356843Sdim
28356843Sdimnamespace {
29356843Sdim
30356843Sdimcl::opt<bool> Quiet("debugify-quiet",
31356843Sdim                    cl::desc("Suppress verbose debugify output"));
32356843Sdim
33356843Sdimraw_ostream &dbg() { return Quiet ? nulls() : errs(); }
34356843Sdim
35356843Sdimuint64_t getAllocSizeInBits(Module &M, Type *Ty) {
36356843Sdim  return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
37356843Sdim}
38356843Sdim
39356843Sdimbool isFunctionSkipped(Function &F) {
40356843Sdim  return F.isDeclaration() || !F.hasExactDefinition();
41356843Sdim}
42356843Sdim
43356843Sdim/// Find the basic block's terminating instruction.
44356843Sdim///
45356843Sdim/// Special care is needed to handle musttail and deopt calls, as these behave
46356843Sdim/// like (but are in fact not) terminators.
47356843SdimInstruction *findTerminatingInstruction(BasicBlock &BB) {
48356843Sdim  if (auto *I = BB.getTerminatingMustTailCall())
49356843Sdim    return I;
50356843Sdim  if (auto *I = BB.getTerminatingDeoptimizeCall())
51356843Sdim    return I;
52356843Sdim  return BB.getTerminator();
53356843Sdim}
54356843Sdim
55356843Sdimbool applyDebugifyMetadata(Module &M,
56356843Sdim                           iterator_range<Module::iterator> Functions,
57356843Sdim                           StringRef Banner) {
58356843Sdim  // Skip modules with debug info.
59356843Sdim  if (M.getNamedMetadata("llvm.dbg.cu")) {
60356843Sdim    dbg() << Banner << "Skipping module with debug info\n";
61356843Sdim    return false;
62356843Sdim  }
63356843Sdim
64356843Sdim  DIBuilder DIB(M);
65356843Sdim  LLVMContext &Ctx = M.getContext();
66356843Sdim
67356843Sdim  // Get a DIType which corresponds to Ty.
68356843Sdim  DenseMap<uint64_t, DIType *> TypeCache;
69356843Sdim  auto getCachedDIType = [&](Type *Ty) -> DIType * {
70356843Sdim    uint64_t Size = getAllocSizeInBits(M, Ty);
71356843Sdim    DIType *&DTy = TypeCache[Size];
72356843Sdim    if (!DTy) {
73356843Sdim      std::string Name = "ty" + utostr(Size);
74356843Sdim      DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
75356843Sdim    }
76356843Sdim    return DTy;
77356843Sdim  };
78356843Sdim
79356843Sdim  unsigned NextLine = 1;
80356843Sdim  unsigned NextVar = 1;
81356843Sdim  auto File = DIB.createFile(M.getName(), "/");
82356843Sdim  auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify",
83356843Sdim                                  /*isOptimized=*/true, "", 0);
84356843Sdim
85356843Sdim  // Visit each instruction.
86356843Sdim  for (Function &F : Functions) {
87356843Sdim    if (isFunctionSkipped(F))
88356843Sdim      continue;
89356843Sdim
90356843Sdim    auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
91356843Sdim    DISubprogram::DISPFlags SPFlags =
92356843Sdim        DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;
93356843Sdim    if (F.hasPrivateLinkage() || F.hasInternalLinkage())
94356843Sdim      SPFlags |= DISubprogram::SPFlagLocalToUnit;
95356843Sdim    auto SP = DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine,
96356843Sdim                                 SPType, NextLine, DINode::FlagZero, SPFlags);
97356843Sdim    F.setSubprogram(SP);
98356843Sdim    for (BasicBlock &BB : F) {
99356843Sdim      // Attach debug locations.
100356843Sdim      for (Instruction &I : BB)
101356843Sdim        I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
102356843Sdim
103356843Sdim      // Inserting debug values into EH pads can break IR invariants.
104356843Sdim      if (BB.isEHPad())
105356843Sdim        continue;
106356843Sdim
107356843Sdim      // Find the terminating instruction, after which no debug values are
108356843Sdim      // attached.
109356843Sdim      Instruction *LastInst = findTerminatingInstruction(BB);
110356843Sdim      assert(LastInst && "Expected basic block with a terminator");
111356843Sdim
112356843Sdim      // Maintain an insertion point which can't be invalidated when updates
113356843Sdim      // are made.
114356843Sdim      BasicBlock::iterator InsertPt = BB.getFirstInsertionPt();
115356843Sdim      assert(InsertPt != BB.end() && "Expected to find an insertion point");
116356843Sdim      Instruction *InsertBefore = &*InsertPt;
117356843Sdim
118356843Sdim      // Attach debug values.
119356843Sdim      for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) {
120356843Sdim        // Skip void-valued instructions.
121356843Sdim        if (I->getType()->isVoidTy())
122356843Sdim          continue;
123356843Sdim
124356843Sdim        // Phis and EH pads must be grouped at the beginning of the block.
125356843Sdim        // Only advance the insertion point when we finish visiting these.
126356843Sdim        if (!isa<PHINode>(I) && !I->isEHPad())
127356843Sdim          InsertBefore = I->getNextNode();
128356843Sdim
129356843Sdim        std::string Name = utostr(NextVar++);
130356843Sdim        const DILocation *Loc = I->getDebugLoc().get();
131356843Sdim        auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
132356843Sdim                                               getCachedDIType(I->getType()),
133356843Sdim                                               /*AlwaysPreserve=*/true);
134356843Sdim        DIB.insertDbgValueIntrinsic(I, LocalVar, DIB.createExpression(), Loc,
135356843Sdim                                    InsertBefore);
136356843Sdim      }
137356843Sdim    }
138356843Sdim    DIB.finalizeSubprogram(SP);
139356843Sdim  }
140356843Sdim  DIB.finalize();
141356843Sdim
142356843Sdim  // Track the number of distinct lines and variables.
143356843Sdim  NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
144356843Sdim  auto *IntTy = Type::getInt32Ty(Ctx);
145356843Sdim  auto addDebugifyOperand = [&](unsigned N) {
146356843Sdim    NMD->addOperand(MDNode::get(
147356843Sdim        Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
148356843Sdim  };
149356843Sdim  addDebugifyOperand(NextLine - 1); // Original number of lines.
150356843Sdim  addDebugifyOperand(NextVar - 1);  // Original number of variables.
151356843Sdim  assert(NMD->getNumOperands() == 2 &&
152356843Sdim         "llvm.debugify should have exactly 2 operands!");
153356843Sdim
154356843Sdim  // Claim that this synthetic debug info is valid.
155356843Sdim  StringRef DIVersionKey = "Debug Info Version";
156356843Sdim  if (!M.getModuleFlag(DIVersionKey))
157356843Sdim    M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
158356843Sdim
159356843Sdim  return true;
160356843Sdim}
161356843Sdim
162356843Sdim/// Return true if a mis-sized diagnostic is issued for \p DVI.
163356843Sdimbool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
164356843Sdim  // The size of a dbg.value's value operand should match the size of the
165356843Sdim  // variable it corresponds to.
166356843Sdim  //
167356843Sdim  // TODO: This, along with a check for non-null value operands, should be
168356843Sdim  // promoted to verifier failures.
169356843Sdim  Value *V = DVI->getValue();
170356843Sdim  if (!V)
171356843Sdim    return false;
172356843Sdim
173356843Sdim  // For now, don't try to interpret anything more complicated than an empty
174356843Sdim  // DIExpression. Eventually we should try to handle OP_deref and fragments.
175356843Sdim  if (DVI->getExpression()->getNumElements())
176356843Sdim    return false;
177356843Sdim
178356843Sdim  Type *Ty = V->getType();
179356843Sdim  uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
180356843Sdim  Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits();
181356843Sdim  if (!ValueOperandSize || !DbgVarSize)
182356843Sdim    return false;
183356843Sdim
184356843Sdim  bool HasBadSize = false;
185356843Sdim  if (Ty->isIntegerTy()) {
186356843Sdim    auto Signedness = DVI->getVariable()->getSignedness();
187356843Sdim    if (Signedness && *Signedness == DIBasicType::Signedness::Signed)
188356843Sdim      HasBadSize = ValueOperandSize < *DbgVarSize;
189356843Sdim  } else {
190356843Sdim    HasBadSize = ValueOperandSize != *DbgVarSize;
191356843Sdim  }
192356843Sdim
193356843Sdim  if (HasBadSize) {
194356843Sdim    dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
195356843Sdim          << ", but its variable has size " << *DbgVarSize << ": ";
196356843Sdim    DVI->print(dbg());
197356843Sdim    dbg() << "\n";
198356843Sdim  }
199356843Sdim  return HasBadSize;
200356843Sdim}
201356843Sdim
202356843Sdimbool checkDebugifyMetadata(Module &M,
203356843Sdim                           iterator_range<Module::iterator> Functions,
204356843Sdim                           StringRef NameOfWrappedPass, StringRef Banner,
205356843Sdim                           bool Strip, DebugifyStatsMap *StatsMap) {
206356843Sdim  // Skip modules without debugify metadata.
207356843Sdim  NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
208356843Sdim  if (!NMD) {
209356843Sdim    dbg() << Banner << "Skipping module without debugify metadata\n";
210356843Sdim    return false;
211356843Sdim  }
212356843Sdim
213356843Sdim  auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
214356843Sdim    return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
215356843Sdim        ->getZExtValue();
216356843Sdim  };
217356843Sdim  assert(NMD->getNumOperands() == 2 &&
218356843Sdim         "llvm.debugify should have exactly 2 operands!");
219356843Sdim  unsigned OriginalNumLines = getDebugifyOperand(0);
220356843Sdim  unsigned OriginalNumVars = getDebugifyOperand(1);
221356843Sdim  bool HasErrors = false;
222356843Sdim
223356843Sdim  // Track debug info loss statistics if able.
224356843Sdim  DebugifyStatistics *Stats = nullptr;
225356843Sdim  if (StatsMap && !NameOfWrappedPass.empty())
226356843Sdim    Stats = &StatsMap->operator[](NameOfWrappedPass);
227356843Sdim
228356843Sdim  BitVector MissingLines{OriginalNumLines, true};
229356843Sdim  BitVector MissingVars{OriginalNumVars, true};
230356843Sdim  for (Function &F : Functions) {
231356843Sdim    if (isFunctionSkipped(F))
232356843Sdim      continue;
233356843Sdim
234356843Sdim    // Find missing lines.
235356843Sdim    for (Instruction &I : instructions(F)) {
236356843Sdim      if (isa<DbgValueInst>(&I))
237356843Sdim        continue;
238356843Sdim
239356843Sdim      auto DL = I.getDebugLoc();
240356843Sdim      if (DL && DL.getLine() != 0) {
241356843Sdim        MissingLines.reset(DL.getLine() - 1);
242356843Sdim        continue;
243356843Sdim      }
244356843Sdim
245356843Sdim      if (!DL) {
246356843Sdim        dbg() << "ERROR: Instruction with empty DebugLoc in function ";
247356843Sdim        dbg() << F.getName() << " --";
248356843Sdim        I.print(dbg());
249356843Sdim        dbg() << "\n";
250356843Sdim        HasErrors = true;
251356843Sdim      }
252356843Sdim    }
253356843Sdim
254356843Sdim    // Find missing variables and mis-sized debug values.
255356843Sdim    for (Instruction &I : instructions(F)) {
256356843Sdim      auto *DVI = dyn_cast<DbgValueInst>(&I);
257356843Sdim      if (!DVI)
258356843Sdim        continue;
259356843Sdim
260356843Sdim      unsigned Var = ~0U;
261356843Sdim      (void)to_integer(DVI->getVariable()->getName(), Var, 10);
262356843Sdim      assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
263356843Sdim      bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI);
264356843Sdim      if (!HasBadSize)
265356843Sdim        MissingVars.reset(Var - 1);
266356843Sdim      HasErrors |= HasBadSize;
267356843Sdim    }
268356843Sdim  }
269356843Sdim
270356843Sdim  // Print the results.
271356843Sdim  for (unsigned Idx : MissingLines.set_bits())
272356843Sdim    dbg() << "WARNING: Missing line " << Idx + 1 << "\n";
273356843Sdim
274356843Sdim  for (unsigned Idx : MissingVars.set_bits())
275356843Sdim    dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";
276356843Sdim
277356843Sdim  // Update DI loss statistics.
278356843Sdim  if (Stats) {
279356843Sdim    Stats->NumDbgLocsExpected += OriginalNumLines;
280356843Sdim    Stats->NumDbgLocsMissing += MissingLines.count();
281356843Sdim    Stats->NumDbgValuesExpected += OriginalNumVars;
282356843Sdim    Stats->NumDbgValuesMissing += MissingVars.count();
283356843Sdim  }
284356843Sdim
285356843Sdim  dbg() << Banner;
286356843Sdim  if (!NameOfWrappedPass.empty())
287356843Sdim    dbg() << " [" << NameOfWrappedPass << "]";
288356843Sdim  dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
289356843Sdim
290356843Sdim  // Strip the Debugify Metadata if required.
291356843Sdim  if (Strip) {
292356843Sdim    StripDebugInfo(M);
293356843Sdim    M.eraseNamedMetadata(NMD);
294356843Sdim    return true;
295356843Sdim  }
296356843Sdim
297356843Sdim  return false;
298356843Sdim}
299356843Sdim
300356843Sdim/// ModulePass for attaching synthetic debug info to everything, used with the
301356843Sdim/// legacy module pass manager.
302356843Sdimstruct DebugifyModulePass : public ModulePass {
303356843Sdim  bool runOnModule(Module &M) override {
304356843Sdim    return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
305356843Sdim  }
306356843Sdim
307356843Sdim  DebugifyModulePass() : ModulePass(ID) {}
308356843Sdim
309356843Sdim  void getAnalysisUsage(AnalysisUsage &AU) const override {
310356843Sdim    AU.setPreservesAll();
311356843Sdim  }
312356843Sdim
313356843Sdim  static char ID; // Pass identification.
314356843Sdim};
315356843Sdim
316356843Sdim/// FunctionPass for attaching synthetic debug info to instructions within a
317356843Sdim/// single function, used with the legacy module pass manager.
318356843Sdimstruct DebugifyFunctionPass : public FunctionPass {
319356843Sdim  bool runOnFunction(Function &F) override {
320356843Sdim    Module &M = *F.getParent();
321356843Sdim    auto FuncIt = F.getIterator();
322356843Sdim    return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
323356843Sdim                                 "FunctionDebugify: ");
324356843Sdim  }
325356843Sdim
326356843Sdim  DebugifyFunctionPass() : FunctionPass(ID) {}
327356843Sdim
328356843Sdim  void getAnalysisUsage(AnalysisUsage &AU) const override {
329356843Sdim    AU.setPreservesAll();
330356843Sdim  }
331356843Sdim
332356843Sdim  static char ID; // Pass identification.
333356843Sdim};
334356843Sdim
335356843Sdim/// ModulePass for checking debug info inserted by -debugify, used with the
336356843Sdim/// legacy module pass manager.
337356843Sdimstruct CheckDebugifyModulePass : public ModulePass {
338356843Sdim  bool runOnModule(Module &M) override {
339356843Sdim    return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
340356843Sdim                                 "CheckModuleDebugify", Strip, StatsMap);
341356843Sdim  }
342356843Sdim
343356843Sdim  CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
344356843Sdim                          DebugifyStatsMap *StatsMap = nullptr)
345356843Sdim      : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
346356843Sdim        StatsMap(StatsMap) {}
347356843Sdim
348356843Sdim  void getAnalysisUsage(AnalysisUsage &AU) const override {
349356843Sdim    AU.setPreservesAll();
350356843Sdim  }
351356843Sdim
352356843Sdim  static char ID; // Pass identification.
353356843Sdim
354356843Sdimprivate:
355356843Sdim  bool Strip;
356356843Sdim  StringRef NameOfWrappedPass;
357356843Sdim  DebugifyStatsMap *StatsMap;
358356843Sdim};
359356843Sdim
360356843Sdim/// FunctionPass for checking debug info inserted by -debugify-function, used
361356843Sdim/// with the legacy module pass manager.
362356843Sdimstruct CheckDebugifyFunctionPass : public FunctionPass {
363356843Sdim  bool runOnFunction(Function &F) override {
364356843Sdim    Module &M = *F.getParent();
365356843Sdim    auto FuncIt = F.getIterator();
366356843Sdim    return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
367356843Sdim                                 NameOfWrappedPass, "CheckFunctionDebugify",
368356843Sdim                                 Strip, StatsMap);
369356843Sdim  }
370356843Sdim
371356843Sdim  CheckDebugifyFunctionPass(bool Strip = false,
372356843Sdim                            StringRef NameOfWrappedPass = "",
373356843Sdim                            DebugifyStatsMap *StatsMap = nullptr)
374356843Sdim      : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
375356843Sdim        StatsMap(StatsMap) {}
376356843Sdim
377356843Sdim  void getAnalysisUsage(AnalysisUsage &AU) const override {
378356843Sdim    AU.setPreservesAll();
379356843Sdim  }
380356843Sdim
381356843Sdim  static char ID; // Pass identification.
382356843Sdim
383356843Sdimprivate:
384356843Sdim  bool Strip;
385356843Sdim  StringRef NameOfWrappedPass;
386356843Sdim  DebugifyStatsMap *StatsMap;
387356843Sdim};
388356843Sdim
389356843Sdim} // end anonymous namespace
390356843Sdim
391356843SdimModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); }
392356843Sdim
393356843SdimFunctionPass *createDebugifyFunctionPass() {
394356843Sdim  return new DebugifyFunctionPass();
395356843Sdim}
396356843Sdim
397356843SdimPreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
398356843Sdim  applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
399356843Sdim  return PreservedAnalyses::all();
400356843Sdim}
401356843Sdim
402356843SdimModulePass *createCheckDebugifyModulePass(bool Strip,
403356843Sdim                                          StringRef NameOfWrappedPass,
404356843Sdim                                          DebugifyStatsMap *StatsMap) {
405356843Sdim  return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
406356843Sdim}
407356843Sdim
408356843SdimFunctionPass *createCheckDebugifyFunctionPass(bool Strip,
409356843Sdim                                              StringRef NameOfWrappedPass,
410356843Sdim                                              DebugifyStatsMap *StatsMap) {
411356843Sdim  return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
412356843Sdim}
413356843Sdim
414356843SdimPreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
415356843Sdim                                              ModuleAnalysisManager &) {
416356843Sdim  checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false,
417356843Sdim                        nullptr);
418356843Sdim  return PreservedAnalyses::all();
419356843Sdim}
420356843Sdim
421356843Sdimchar DebugifyModulePass::ID = 0;
422356843Sdimstatic RegisterPass<DebugifyModulePass> DM("debugify",
423356843Sdim                                           "Attach debug info to everything");
424356843Sdim
425356843Sdimchar CheckDebugifyModulePass::ID = 0;
426356843Sdimstatic RegisterPass<CheckDebugifyModulePass>
427356843Sdim    CDM("check-debugify", "Check debug info from -debugify");
428356843Sdim
429356843Sdimchar DebugifyFunctionPass::ID = 0;
430356843Sdimstatic RegisterPass<DebugifyFunctionPass> DF("debugify-function",
431356843Sdim                                             "Attach debug info to a function");
432356843Sdim
433356843Sdimchar CheckDebugifyFunctionPass::ID = 0;
434356843Sdimstatic RegisterPass<CheckDebugifyFunctionPass>
435356843Sdim    CDF("check-debugify-function", "Check debug info from -debugify-function");
436