12cab237bSDimitry Andric //===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
22cab237bSDimitry Andric //
32cab237bSDimitry Andric //                     The LLVM Compiler Infrastructure
42cab237bSDimitry Andric //
52cab237bSDimitry Andric // This file is distributed under the University of Illinois Open Source
62cab237bSDimitry Andric // License. See LICENSE.TXT for details.
72cab237bSDimitry Andric //
82cab237bSDimitry Andric //===----------------------------------------------------------------------===//
92cab237bSDimitry Andric ///
102cab237bSDimitry Andric /// \file This pass attaches synthetic debug info to everything. It can be used
112cab237bSDimitry Andric /// to create targeted tests for debug info preservation.
122cab237bSDimitry Andric ///
132cab237bSDimitry Andric //===----------------------------------------------------------------------===//
142cab237bSDimitry Andric 
154ba319b5SDimitry Andric #include "Debugify.h"
162cab237bSDimitry Andric #include "llvm/ADT/BitVector.h"
172cab237bSDimitry Andric #include "llvm/ADT/StringExtras.h"
182cab237bSDimitry Andric #include "llvm/IR/BasicBlock.h"
192cab237bSDimitry Andric #include "llvm/IR/Constants.h"
202cab237bSDimitry Andric #include "llvm/IR/DIBuilder.h"
212cab237bSDimitry Andric #include "llvm/IR/DebugInfo.h"
222cab237bSDimitry Andric #include "llvm/IR/Function.h"
232cab237bSDimitry Andric #include "llvm/IR/GlobalVariable.h"
242cab237bSDimitry Andric #include "llvm/IR/InstIterator.h"
252cab237bSDimitry Andric #include "llvm/IR/Instruction.h"
262cab237bSDimitry Andric #include "llvm/IR/Instructions.h"
272cab237bSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
282cab237bSDimitry Andric #include "llvm/IR/Module.h"
292cab237bSDimitry Andric #include "llvm/IR/Type.h"
302cab237bSDimitry Andric #include "llvm/Pass.h"
312cab237bSDimitry Andric #include "llvm/Support/raw_ostream.h"
322cab237bSDimitry Andric #include "llvm/Transforms/IPO.h"
332cab237bSDimitry Andric 
342cab237bSDimitry Andric using namespace llvm;
352cab237bSDimitry Andric 
362cab237bSDimitry Andric namespace {
372cab237bSDimitry Andric 
384ba319b5SDimitry Andric cl::opt<bool> Quiet("debugify-quiet",
394ba319b5SDimitry Andric                     cl::desc("Suppress verbose debugify output"));
404ba319b5SDimitry Andric 
dbg()414ba319b5SDimitry Andric raw_ostream &dbg() { return Quiet ? nulls() : errs(); }
424ba319b5SDimitry Andric 
getAllocSizeInBits(Module & M,Type * Ty)434ba319b5SDimitry Andric uint64_t getAllocSizeInBits(Module &M, Type *Ty) {
444ba319b5SDimitry Andric   return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;
454ba319b5SDimitry Andric }
464ba319b5SDimitry Andric 
isFunctionSkipped(Function & F)474ba319b5SDimitry Andric bool isFunctionSkipped(Function &F) {
484ba319b5SDimitry Andric   return F.isDeclaration() || !F.hasExactDefinition();
494ba319b5SDimitry Andric }
504ba319b5SDimitry Andric 
514ba319b5SDimitry Andric /// Find the basic block's terminating instruction.
524ba319b5SDimitry Andric ///
534ba319b5SDimitry Andric /// Special care is needed to handle musttail and deopt calls, as these behave
544ba319b5SDimitry Andric /// like (but are in fact not) terminators.
findTerminatingInstruction(BasicBlock & BB)554ba319b5SDimitry Andric Instruction *findTerminatingInstruction(BasicBlock &BB) {
564ba319b5SDimitry Andric   if (auto *I = BB.getTerminatingMustTailCall())
574ba319b5SDimitry Andric     return I;
584ba319b5SDimitry Andric   if (auto *I = BB.getTerminatingDeoptimizeCall())
594ba319b5SDimitry Andric     return I;
604ba319b5SDimitry Andric   return BB.getTerminator();
614ba319b5SDimitry Andric }
624ba319b5SDimitry Andric 
applyDebugifyMetadata(Module & M,iterator_range<Module::iterator> Functions,StringRef Banner)634ba319b5SDimitry Andric bool applyDebugifyMetadata(Module &M,
644ba319b5SDimitry Andric                            iterator_range<Module::iterator> Functions,
654ba319b5SDimitry Andric                            StringRef Banner) {
662cab237bSDimitry Andric   // Skip modules with debug info.
672cab237bSDimitry Andric   if (M.getNamedMetadata("llvm.dbg.cu")) {
684ba319b5SDimitry Andric     dbg() << Banner << "Skipping module with debug info\n";
692cab237bSDimitry Andric     return false;
702cab237bSDimitry Andric   }
712cab237bSDimitry Andric 
722cab237bSDimitry Andric   DIBuilder DIB(M);
732cab237bSDimitry Andric   LLVMContext &Ctx = M.getContext();
742cab237bSDimitry Andric 
752cab237bSDimitry Andric   // Get a DIType which corresponds to Ty.
762cab237bSDimitry Andric   DenseMap<uint64_t, DIType *> TypeCache;
772cab237bSDimitry Andric   auto getCachedDIType = [&](Type *Ty) -> DIType * {
784ba319b5SDimitry Andric     uint64_t Size = getAllocSizeInBits(M, Ty);
792cab237bSDimitry Andric     DIType *&DTy = TypeCache[Size];
802cab237bSDimitry Andric     if (!DTy) {
812cab237bSDimitry Andric       std::string Name = "ty" + utostr(Size);
822cab237bSDimitry Andric       DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
832cab237bSDimitry Andric     }
842cab237bSDimitry Andric     return DTy;
852cab237bSDimitry Andric   };
862cab237bSDimitry Andric 
872cab237bSDimitry Andric   unsigned NextLine = 1;
882cab237bSDimitry Andric   unsigned NextVar = 1;
892cab237bSDimitry Andric   auto File = DIB.createFile(M.getName(), "/");
904ba319b5SDimitry Andric   auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify",
914ba319b5SDimitry Andric                                   /*isOptimized=*/true, "", 0);
922cab237bSDimitry Andric 
932cab237bSDimitry Andric   // Visit each instruction.
944ba319b5SDimitry Andric   for (Function &F : Functions) {
954ba319b5SDimitry Andric     if (isFunctionSkipped(F))
962cab237bSDimitry Andric       continue;
972cab237bSDimitry Andric 
982cab237bSDimitry Andric     auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
99*b5893f02SDimitry Andric     DISubprogram::DISPFlags SPFlags =
100*b5893f02SDimitry Andric         DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;
101*b5893f02SDimitry Andric     if (F.hasPrivateLinkage() || F.hasInternalLinkage())
102*b5893f02SDimitry Andric       SPFlags |= DISubprogram::SPFlagLocalToUnit;
103*b5893f02SDimitry Andric     auto SP = DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine,
104*b5893f02SDimitry Andric                                  SPType, NextLine, DINode::FlagZero, SPFlags);
1052cab237bSDimitry Andric     F.setSubprogram(SP);
1062cab237bSDimitry Andric     for (BasicBlock &BB : F) {
1072cab237bSDimitry Andric       // Attach debug locations.
1082cab237bSDimitry Andric       for (Instruction &I : BB)
1092cab237bSDimitry Andric         I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
1102cab237bSDimitry Andric 
1114ba319b5SDimitry Andric       // Inserting debug values into EH pads can break IR invariants.
1124ba319b5SDimitry Andric       if (BB.isEHPad())
1132cab237bSDimitry Andric         continue;
1142cab237bSDimitry Andric 
1154ba319b5SDimitry Andric       // Find the terminating instruction, after which no debug values are
1164ba319b5SDimitry Andric       // attached.
1174ba319b5SDimitry Andric       Instruction *LastInst = findTerminatingInstruction(BB);
1184ba319b5SDimitry Andric       assert(LastInst && "Expected basic block with a terminator");
1194ba319b5SDimitry Andric 
1204ba319b5SDimitry Andric       // Maintain an insertion point which can't be invalidated when updates
1214ba319b5SDimitry Andric       // are made.
1224ba319b5SDimitry Andric       BasicBlock::iterator InsertPt = BB.getFirstInsertionPt();
1234ba319b5SDimitry Andric       assert(InsertPt != BB.end() && "Expected to find an insertion point");
1244ba319b5SDimitry Andric       Instruction *InsertBefore = &*InsertPt;
1254ba319b5SDimitry Andric 
1264ba319b5SDimitry Andric       // Attach debug values.
1274ba319b5SDimitry Andric       for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) {
1284ba319b5SDimitry Andric         // Skip void-valued instructions.
1294ba319b5SDimitry Andric         if (I->getType()->isVoidTy())
1304ba319b5SDimitry Andric           continue;
1314ba319b5SDimitry Andric 
1324ba319b5SDimitry Andric         // Phis and EH pads must be grouped at the beginning of the block.
1334ba319b5SDimitry Andric         // Only advance the insertion point when we finish visiting these.
1344ba319b5SDimitry Andric         if (!isa<PHINode>(I) && !I->isEHPad())
1354ba319b5SDimitry Andric           InsertBefore = I->getNextNode();
1362cab237bSDimitry Andric 
1372cab237bSDimitry Andric         std::string Name = utostr(NextVar++);
1384ba319b5SDimitry Andric         const DILocation *Loc = I->getDebugLoc().get();
1392cab237bSDimitry Andric         auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
1404ba319b5SDimitry Andric                                                getCachedDIType(I->getType()),
1412cab237bSDimitry Andric                                                /*AlwaysPreserve=*/true);
1424ba319b5SDimitry Andric         DIB.insertDbgValueIntrinsic(I, LocalVar, DIB.createExpression(), Loc,
1434ba319b5SDimitry Andric                                     InsertBefore);
1442cab237bSDimitry Andric       }
1452cab237bSDimitry Andric     }
1462cab237bSDimitry Andric     DIB.finalizeSubprogram(SP);
1472cab237bSDimitry Andric   }
1482cab237bSDimitry Andric   DIB.finalize();
1492cab237bSDimitry Andric 
1502cab237bSDimitry Andric   // Track the number of distinct lines and variables.
1512cab237bSDimitry Andric   NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
1522cab237bSDimitry Andric   auto *IntTy = Type::getInt32Ty(Ctx);
1532cab237bSDimitry Andric   auto addDebugifyOperand = [&](unsigned N) {
1542cab237bSDimitry Andric     NMD->addOperand(MDNode::get(
1552cab237bSDimitry Andric         Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
1562cab237bSDimitry Andric   };
1572cab237bSDimitry Andric   addDebugifyOperand(NextLine - 1); // Original number of lines.
1582cab237bSDimitry Andric   addDebugifyOperand(NextVar - 1);  // Original number of variables.
1594ba319b5SDimitry Andric   assert(NMD->getNumOperands() == 2 &&
1604ba319b5SDimitry Andric          "llvm.debugify should have exactly 2 operands!");
1614ba319b5SDimitry Andric 
1624ba319b5SDimitry Andric   // Claim that this synthetic debug info is valid.
1634ba319b5SDimitry Andric   StringRef DIVersionKey = "Debug Info Version";
1644ba319b5SDimitry Andric   if (!M.getModuleFlag(DIVersionKey))
1654ba319b5SDimitry Andric     M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION);
1664ba319b5SDimitry Andric 
1672cab237bSDimitry Andric   return true;
1682cab237bSDimitry Andric }
1692cab237bSDimitry Andric 
1704ba319b5SDimitry Andric /// Return true if a mis-sized diagnostic is issued for \p DVI.
diagnoseMisSizedDbgValue(Module & M,DbgValueInst * DVI)1714ba319b5SDimitry Andric bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
1724ba319b5SDimitry Andric   // The size of a dbg.value's value operand should match the size of the
1734ba319b5SDimitry Andric   // variable it corresponds to.
1744ba319b5SDimitry Andric   //
1754ba319b5SDimitry Andric   // TODO: This, along with a check for non-null value operands, should be
1764ba319b5SDimitry Andric   // promoted to verifier failures.
1774ba319b5SDimitry Andric   Value *V = DVI->getValue();
1784ba319b5SDimitry Andric   if (!V)
1794ba319b5SDimitry Andric     return false;
1804ba319b5SDimitry Andric 
1814ba319b5SDimitry Andric   // For now, don't try to interpret anything more complicated than an empty
1824ba319b5SDimitry Andric   // DIExpression. Eventually we should try to handle OP_deref and fragments.
1834ba319b5SDimitry Andric   if (DVI->getExpression()->getNumElements())
1844ba319b5SDimitry Andric     return false;
1854ba319b5SDimitry Andric 
1864ba319b5SDimitry Andric   Type *Ty = V->getType();
1874ba319b5SDimitry Andric   uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
1884ba319b5SDimitry Andric   Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits();
1894ba319b5SDimitry Andric   if (!ValueOperandSize || !DbgVarSize)
1904ba319b5SDimitry Andric     return false;
1914ba319b5SDimitry Andric 
1924ba319b5SDimitry Andric   bool HasBadSize = false;
1934ba319b5SDimitry Andric   if (Ty->isIntegerTy()) {
1944ba319b5SDimitry Andric     auto Signedness = DVI->getVariable()->getSignedness();
1954ba319b5SDimitry Andric     if (Signedness && *Signedness == DIBasicType::Signedness::Signed)
1964ba319b5SDimitry Andric       HasBadSize = ValueOperandSize < *DbgVarSize;
1974ba319b5SDimitry Andric   } else {
1984ba319b5SDimitry Andric     HasBadSize = ValueOperandSize != *DbgVarSize;
1994ba319b5SDimitry Andric   }
2004ba319b5SDimitry Andric 
2014ba319b5SDimitry Andric   if (HasBadSize) {
2024ba319b5SDimitry Andric     dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize
2034ba319b5SDimitry Andric           << ", but its variable has size " << *DbgVarSize << ": ";
2044ba319b5SDimitry Andric     DVI->print(dbg());
2054ba319b5SDimitry Andric     dbg() << "\n";
2064ba319b5SDimitry Andric   }
2074ba319b5SDimitry Andric   return HasBadSize;
2084ba319b5SDimitry Andric }
2094ba319b5SDimitry Andric 
checkDebugifyMetadata(Module & M,iterator_range<Module::iterator> Functions,StringRef NameOfWrappedPass,StringRef Banner,bool Strip,DebugifyStatsMap * StatsMap)2104ba319b5SDimitry Andric bool checkDebugifyMetadata(Module &M,
2114ba319b5SDimitry Andric                            iterator_range<Module::iterator> Functions,
2124ba319b5SDimitry Andric                            StringRef NameOfWrappedPass, StringRef Banner,
2134ba319b5SDimitry Andric                            bool Strip, DebugifyStatsMap *StatsMap) {
2142cab237bSDimitry Andric   // Skip modules without debugify metadata.
2152cab237bSDimitry Andric   NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
2164ba319b5SDimitry Andric   if (!NMD) {
2174ba319b5SDimitry Andric     dbg() << Banner << "Skipping module without debugify metadata\n";
2184ba319b5SDimitry Andric     return false;
2194ba319b5SDimitry Andric   }
2202cab237bSDimitry Andric 
2212cab237bSDimitry Andric   auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
2222cab237bSDimitry Andric     return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
2232cab237bSDimitry Andric         ->getZExtValue();
2242cab237bSDimitry Andric   };
2254ba319b5SDimitry Andric   assert(NMD->getNumOperands() == 2 &&
2264ba319b5SDimitry Andric          "llvm.debugify should have exactly 2 operands!");
2272cab237bSDimitry Andric   unsigned OriginalNumLines = getDebugifyOperand(0);
2282cab237bSDimitry Andric   unsigned OriginalNumVars = getDebugifyOperand(1);
2292cab237bSDimitry Andric   bool HasErrors = false;
2302cab237bSDimitry Andric 
2314ba319b5SDimitry Andric   // Track debug info loss statistics if able.
2324ba319b5SDimitry Andric   DebugifyStatistics *Stats = nullptr;
2334ba319b5SDimitry Andric   if (StatsMap && !NameOfWrappedPass.empty())
2344ba319b5SDimitry Andric     Stats = &StatsMap->operator[](NameOfWrappedPass);
2354ba319b5SDimitry Andric 
2362cab237bSDimitry Andric   BitVector MissingLines{OriginalNumLines, true};
2374ba319b5SDimitry Andric   BitVector MissingVars{OriginalNumVars, true};
2384ba319b5SDimitry Andric   for (Function &F : Functions) {
2394ba319b5SDimitry Andric     if (isFunctionSkipped(F))
2404ba319b5SDimitry Andric       continue;
2414ba319b5SDimitry Andric 
2424ba319b5SDimitry Andric     // Find missing lines.
2432cab237bSDimitry Andric     for (Instruction &I : instructions(F)) {
2442cab237bSDimitry Andric       if (isa<DbgValueInst>(&I))
2452cab237bSDimitry Andric         continue;
2462cab237bSDimitry Andric 
2472cab237bSDimitry Andric       auto DL = I.getDebugLoc();
2484ba319b5SDimitry Andric       if (DL && DL.getLine() != 0) {
2492cab237bSDimitry Andric         MissingLines.reset(DL.getLine() - 1);
2502cab237bSDimitry Andric         continue;
2512cab237bSDimitry Andric       }
2522cab237bSDimitry Andric 
2534ba319b5SDimitry Andric       if (!DL) {
2544ba319b5SDimitry Andric         dbg() << "ERROR: Instruction with empty DebugLoc in function ";
2554ba319b5SDimitry Andric         dbg() << F.getName() << " --";
2564ba319b5SDimitry Andric         I.print(dbg());
2574ba319b5SDimitry Andric         dbg() << "\n";
2582cab237bSDimitry Andric         HasErrors = true;
2592cab237bSDimitry Andric       }
2602cab237bSDimitry Andric     }
2612cab237bSDimitry Andric 
2624ba319b5SDimitry Andric     // Find missing variables and mis-sized debug values.
2632cab237bSDimitry Andric     for (Instruction &I : instructions(F)) {
2642cab237bSDimitry Andric       auto *DVI = dyn_cast<DbgValueInst>(&I);
2652cab237bSDimitry Andric       if (!DVI)
2662cab237bSDimitry Andric         continue;
2672cab237bSDimitry Andric 
2682cab237bSDimitry Andric       unsigned Var = ~0U;
2692cab237bSDimitry Andric       (void)to_integer(DVI->getVariable()->getName(), Var, 10);
2702cab237bSDimitry Andric       assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
2714ba319b5SDimitry Andric       bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI);
2724ba319b5SDimitry Andric       if (!HasBadSize)
2732cab237bSDimitry Andric         MissingVars.reset(Var - 1);
2744ba319b5SDimitry Andric       HasErrors |= HasBadSize;
2752cab237bSDimitry Andric     }
2762cab237bSDimitry Andric   }
2774ba319b5SDimitry Andric 
2784ba319b5SDimitry Andric   // Print the results.
2794ba319b5SDimitry Andric   for (unsigned Idx : MissingLines.set_bits())
2804ba319b5SDimitry Andric     dbg() << "WARNING: Missing line " << Idx + 1 << "\n";
2814ba319b5SDimitry Andric 
2822cab237bSDimitry Andric   for (unsigned Idx : MissingVars.set_bits())
2834ba319b5SDimitry Andric     dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";
2842cab237bSDimitry Andric 
2854ba319b5SDimitry Andric   // Update DI loss statistics.
2864ba319b5SDimitry Andric   if (Stats) {
2874ba319b5SDimitry Andric     Stats->NumDbgLocsExpected += OriginalNumLines;
2884ba319b5SDimitry Andric     Stats->NumDbgLocsMissing += MissingLines.count();
2894ba319b5SDimitry Andric     Stats->NumDbgValuesExpected += OriginalNumVars;
2904ba319b5SDimitry Andric     Stats->NumDbgValuesMissing += MissingVars.count();
2912cab237bSDimitry Andric   }
2922cab237bSDimitry Andric 
2934ba319b5SDimitry Andric   dbg() << Banner;
2944ba319b5SDimitry Andric   if (!NameOfWrappedPass.empty())
2954ba319b5SDimitry Andric     dbg() << " [" << NameOfWrappedPass << "]";
2964ba319b5SDimitry Andric   dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';
2972cab237bSDimitry Andric 
2984ba319b5SDimitry Andric   // Strip the Debugify Metadata if required.
2994ba319b5SDimitry Andric   if (Strip) {
3004ba319b5SDimitry Andric     StripDebugInfo(M);
3014ba319b5SDimitry Andric     M.eraseNamedMetadata(NMD);
3024ba319b5SDimitry Andric     return true;
3034ba319b5SDimitry Andric   }
3044ba319b5SDimitry Andric 
3054ba319b5SDimitry Andric   return false;
3064ba319b5SDimitry Andric }
3074ba319b5SDimitry Andric 
3084ba319b5SDimitry Andric /// ModulePass for attaching synthetic debug info to everything, used with the
3094ba319b5SDimitry Andric /// legacy module pass manager.
3104ba319b5SDimitry Andric struct DebugifyModulePass : public ModulePass {
runOnModule__anonfea7d2800111::DebugifyModulePass3114ba319b5SDimitry Andric   bool runOnModule(Module &M) override {
3124ba319b5SDimitry Andric     return applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
3134ba319b5SDimitry Andric   }
3144ba319b5SDimitry Andric 
DebugifyModulePass__anonfea7d2800111::DebugifyModulePass3154ba319b5SDimitry Andric   DebugifyModulePass() : ModulePass(ID) {}
3162cab237bSDimitry Andric 
getAnalysisUsage__anonfea7d2800111::DebugifyModulePass3172cab237bSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
3182cab237bSDimitry Andric     AU.setPreservesAll();
3192cab237bSDimitry Andric   }
3202cab237bSDimitry Andric 
3212cab237bSDimitry Andric   static char ID; // Pass identification.
3222cab237bSDimitry Andric };
3232cab237bSDimitry Andric 
3244ba319b5SDimitry Andric /// FunctionPass for attaching synthetic debug info to instructions within a
3254ba319b5SDimitry Andric /// single function, used with the legacy module pass manager.
3264ba319b5SDimitry Andric struct DebugifyFunctionPass : public FunctionPass {
runOnFunction__anonfea7d2800111::DebugifyFunctionPass3274ba319b5SDimitry Andric   bool runOnFunction(Function &F) override {
3284ba319b5SDimitry Andric     Module &M = *F.getParent();
3294ba319b5SDimitry Andric     auto FuncIt = F.getIterator();
3304ba319b5SDimitry Andric     return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
3314ba319b5SDimitry Andric                                  "FunctionDebugify: ");
3322cab237bSDimitry Andric   }
3332cab237bSDimitry Andric 
DebugifyFunctionPass__anonfea7d2800111::DebugifyFunctionPass3344ba319b5SDimitry Andric   DebugifyFunctionPass() : FunctionPass(ID) {}
3352cab237bSDimitry Andric 
getAnalysisUsage__anonfea7d2800111::DebugifyFunctionPass3362cab237bSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
3372cab237bSDimitry Andric     AU.setPreservesAll();
3382cab237bSDimitry Andric   }
3392cab237bSDimitry Andric 
3402cab237bSDimitry Andric   static char ID; // Pass identification.
3412cab237bSDimitry Andric };
3422cab237bSDimitry Andric 
3434ba319b5SDimitry Andric /// ModulePass for checking debug info inserted by -debugify, used with the
3444ba319b5SDimitry Andric /// legacy module pass manager.
3454ba319b5SDimitry Andric struct CheckDebugifyModulePass : public ModulePass {
runOnModule__anonfea7d2800111::CheckDebugifyModulePass3464ba319b5SDimitry Andric   bool runOnModule(Module &M) override {
3474ba319b5SDimitry Andric     return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
3484ba319b5SDimitry Andric                                  "CheckModuleDebugify", Strip, StatsMap);
3494ba319b5SDimitry Andric   }
3504ba319b5SDimitry Andric 
CheckDebugifyModulePass__anonfea7d2800111::CheckDebugifyModulePass3514ba319b5SDimitry Andric   CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
3524ba319b5SDimitry Andric                           DebugifyStatsMap *StatsMap = nullptr)
3534ba319b5SDimitry Andric       : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
3544ba319b5SDimitry Andric         StatsMap(StatsMap) {}
3554ba319b5SDimitry Andric 
getAnalysisUsage__anonfea7d2800111::CheckDebugifyModulePass3564ba319b5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
3574ba319b5SDimitry Andric     AU.setPreservesAll();
3584ba319b5SDimitry Andric   }
3594ba319b5SDimitry Andric 
3604ba319b5SDimitry Andric   static char ID; // Pass identification.
3614ba319b5SDimitry Andric 
3624ba319b5SDimitry Andric private:
3634ba319b5SDimitry Andric   bool Strip;
3644ba319b5SDimitry Andric   StringRef NameOfWrappedPass;
3654ba319b5SDimitry Andric   DebugifyStatsMap *StatsMap;
3664ba319b5SDimitry Andric };
3674ba319b5SDimitry Andric 
3684ba319b5SDimitry Andric /// FunctionPass for checking debug info inserted by -debugify-function, used
3694ba319b5SDimitry Andric /// with the legacy module pass manager.
3704ba319b5SDimitry Andric struct CheckDebugifyFunctionPass : public FunctionPass {
runOnFunction__anonfea7d2800111::CheckDebugifyFunctionPass3714ba319b5SDimitry Andric   bool runOnFunction(Function &F) override {
3724ba319b5SDimitry Andric     Module &M = *F.getParent();
3734ba319b5SDimitry Andric     auto FuncIt = F.getIterator();
3744ba319b5SDimitry Andric     return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
3754ba319b5SDimitry Andric                                  NameOfWrappedPass, "CheckFunctionDebugify",
3764ba319b5SDimitry Andric                                  Strip, StatsMap);
3774ba319b5SDimitry Andric   }
3784ba319b5SDimitry Andric 
CheckDebugifyFunctionPass__anonfea7d2800111::CheckDebugifyFunctionPass3794ba319b5SDimitry Andric   CheckDebugifyFunctionPass(bool Strip = false,
3804ba319b5SDimitry Andric                             StringRef NameOfWrappedPass = "",
3814ba319b5SDimitry Andric                             DebugifyStatsMap *StatsMap = nullptr)
3824ba319b5SDimitry Andric       : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
3834ba319b5SDimitry Andric         StatsMap(StatsMap) {}
3844ba319b5SDimitry Andric 
getAnalysisUsage__anonfea7d2800111::CheckDebugifyFunctionPass3854ba319b5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
3864ba319b5SDimitry Andric     AU.setPreservesAll();
3874ba319b5SDimitry Andric   }
3884ba319b5SDimitry Andric 
3894ba319b5SDimitry Andric   static char ID; // Pass identification.
3904ba319b5SDimitry Andric 
3914ba319b5SDimitry Andric private:
3924ba319b5SDimitry Andric   bool Strip;
3934ba319b5SDimitry Andric   StringRef NameOfWrappedPass;
3944ba319b5SDimitry Andric   DebugifyStatsMap *StatsMap;
3954ba319b5SDimitry Andric };
3964ba319b5SDimitry Andric 
3972cab237bSDimitry Andric } // end anonymous namespace
3982cab237bSDimitry Andric 
exportDebugifyStats(llvm::StringRef Path,const DebugifyStatsMap & Map)3994ba319b5SDimitry Andric void exportDebugifyStats(llvm::StringRef Path, const DebugifyStatsMap &Map) {
4004ba319b5SDimitry Andric   std::error_code EC;
4014ba319b5SDimitry Andric   raw_fd_ostream OS{Path, EC};
4024ba319b5SDimitry Andric   if (EC) {
4034ba319b5SDimitry Andric     errs() << "Could not open file: " << EC.message() << ", " << Path << '\n';
4044ba319b5SDimitry Andric     return;
4054ba319b5SDimitry Andric   }
4064ba319b5SDimitry Andric 
4074ba319b5SDimitry Andric   OS << "Pass Name" << ',' << "# of missing debug values" << ','
4084ba319b5SDimitry Andric      << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','
4094ba319b5SDimitry Andric      << "Missing/Expected location ratio" << '\n';
4104ba319b5SDimitry Andric   for (const auto &Entry : Map) {
4114ba319b5SDimitry Andric     StringRef Pass = Entry.first;
4124ba319b5SDimitry Andric     DebugifyStatistics Stats = Entry.second;
4134ba319b5SDimitry Andric 
4144ba319b5SDimitry Andric     OS << Pass << ',' << Stats.NumDbgValuesMissing << ','
4154ba319b5SDimitry Andric        << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ','
4164ba319b5SDimitry Andric        << Stats.getEmptyLocationRatio() << '\n';
4174ba319b5SDimitry Andric   }
4184ba319b5SDimitry Andric }
4194ba319b5SDimitry Andric 
createDebugifyModulePass()4204ba319b5SDimitry Andric ModulePass *createDebugifyModulePass() { return new DebugifyModulePass(); }
4214ba319b5SDimitry Andric 
createDebugifyFunctionPass()4224ba319b5SDimitry Andric FunctionPass *createDebugifyFunctionPass() {
4234ba319b5SDimitry Andric   return new DebugifyFunctionPass();
4244ba319b5SDimitry Andric }
4254ba319b5SDimitry Andric 
run(Module & M,ModuleAnalysisManager &)4264ba319b5SDimitry Andric PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
4274ba319b5SDimitry Andric   applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
4284ba319b5SDimitry Andric   return PreservedAnalyses::all();
4294ba319b5SDimitry Andric }
4304ba319b5SDimitry Andric 
createCheckDebugifyModulePass(bool Strip,StringRef NameOfWrappedPass,DebugifyStatsMap * StatsMap)4314ba319b5SDimitry Andric ModulePass *createCheckDebugifyModulePass(bool Strip,
4324ba319b5SDimitry Andric                                           StringRef NameOfWrappedPass,
4334ba319b5SDimitry Andric                                           DebugifyStatsMap *StatsMap) {
4344ba319b5SDimitry Andric   return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
4354ba319b5SDimitry Andric }
4364ba319b5SDimitry Andric 
createCheckDebugifyFunctionPass(bool Strip,StringRef NameOfWrappedPass,DebugifyStatsMap * StatsMap)4374ba319b5SDimitry Andric FunctionPass *createCheckDebugifyFunctionPass(bool Strip,
4384ba319b5SDimitry Andric                                               StringRef NameOfWrappedPass,
4394ba319b5SDimitry Andric                                               DebugifyStatsMap *StatsMap) {
4404ba319b5SDimitry Andric   return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
4414ba319b5SDimitry Andric }
4424ba319b5SDimitry Andric 
run(Module & M,ModuleAnalysisManager &)4434ba319b5SDimitry Andric PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
4444ba319b5SDimitry Andric                                               ModuleAnalysisManager &) {
4454ba319b5SDimitry Andric   checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false,
4464ba319b5SDimitry Andric                         nullptr);
4474ba319b5SDimitry Andric   return PreservedAnalyses::all();
4484ba319b5SDimitry Andric }
4494ba319b5SDimitry Andric 
4504ba319b5SDimitry Andric char DebugifyModulePass::ID = 0;
4514ba319b5SDimitry Andric static RegisterPass<DebugifyModulePass> DM("debugify",
4522cab237bSDimitry Andric                                            "Attach debug info to everything");
4532cab237bSDimitry Andric 
4544ba319b5SDimitry Andric char CheckDebugifyModulePass::ID = 0;
4554ba319b5SDimitry Andric static RegisterPass<CheckDebugifyModulePass>
4564ba319b5SDimitry Andric     CDM("check-debugify", "Check debug info from -debugify");
4574ba319b5SDimitry Andric 
4584ba319b5SDimitry Andric char DebugifyFunctionPass::ID = 0;
4594ba319b5SDimitry Andric static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
4604ba319b5SDimitry Andric                                              "Attach debug info to a function");
4614ba319b5SDimitry Andric 
4624ba319b5SDimitry Andric char CheckDebugifyFunctionPass::ID = 0;
4634ba319b5SDimitry Andric static RegisterPass<CheckDebugifyFunctionPass>
4644ba319b5SDimitry Andric     CDF("check-debugify-function", "Check debug info from -debugify-function");
465