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