1 //===- Debugify.cpp - Check debug info preservation in optimizations ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file In the `synthetic` mode, the `-debugify` attaches synthetic debug info 10 /// to everything. It can be used to create targeted tests for debug info 11 /// preservation. In addition, when using the `original` mode, it can check 12 /// original debug info preservation. The `synthetic` mode is default one. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/Transforms/Utils/Debugify.h" 17 #include "llvm/ADT/BitVector.h" 18 #include "llvm/ADT/StringExtras.h" 19 #include "llvm/IR/DIBuilder.h" 20 #include "llvm/IR/DebugInfo.h" 21 #include "llvm/IR/InstIterator.h" 22 #include "llvm/IR/Instructions.h" 23 #include "llvm/IR/IntrinsicInst.h" 24 #include "llvm/IR/Module.h" 25 #include "llvm/IR/PassInstrumentation.h" 26 #include "llvm/Pass.h" 27 #include "llvm/Support/CommandLine.h" 28 29 #define DEBUG_TYPE "debugify" 30 31 using namespace llvm; 32 33 namespace { 34 35 cl::opt<bool> Quiet("debugify-quiet", 36 cl::desc("Suppress verbose debugify output")); 37 38 enum class Level { 39 Locations, 40 LocationsAndVariables 41 }; 42 43 // Used for the synthetic mode only. 44 cl::opt<Level> DebugifyLevel( 45 "debugify-level", cl::desc("Kind of debug info to add"), 46 cl::values(clEnumValN(Level::Locations, "locations", "Locations only"), 47 clEnumValN(Level::LocationsAndVariables, "location+variables", 48 "Locations and Variables")), 49 cl::init(Level::LocationsAndVariables)); 50 51 raw_ostream &dbg() { return Quiet ? nulls() : errs(); } 52 53 uint64_t getAllocSizeInBits(Module &M, Type *Ty) { 54 return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0; 55 } 56 57 bool isFunctionSkipped(Function &F) { 58 return F.isDeclaration() || !F.hasExactDefinition(); 59 } 60 61 /// Find the basic block's terminating instruction. 62 /// 63 /// Special care is needed to handle musttail and deopt calls, as these behave 64 /// like (but are in fact not) terminators. 65 Instruction *findTerminatingInstruction(BasicBlock &BB) { 66 if (auto *I = BB.getTerminatingMustTailCall()) 67 return I; 68 if (auto *I = BB.getTerminatingDeoptimizeCall()) 69 return I; 70 return BB.getTerminator(); 71 } 72 } // end anonymous namespace 73 74 bool llvm::applyDebugifyMetadata( 75 Module &M, iterator_range<Module::iterator> Functions, StringRef Banner, 76 std::function<bool(DIBuilder &DIB, Function &F)> ApplyToMF) { 77 // Skip modules with debug info. 78 if (M.getNamedMetadata("llvm.dbg.cu")) { 79 dbg() << Banner << "Skipping module with debug info\n"; 80 return false; 81 } 82 83 DIBuilder DIB(M); 84 LLVMContext &Ctx = M.getContext(); 85 auto *Int32Ty = Type::getInt32Ty(Ctx); 86 87 // Get a DIType which corresponds to Ty. 88 DenseMap<uint64_t, DIType *> TypeCache; 89 auto getCachedDIType = [&](Type *Ty) -> DIType * { 90 uint64_t Size = getAllocSizeInBits(M, Ty); 91 DIType *&DTy = TypeCache[Size]; 92 if (!DTy) { 93 std::string Name = "ty" + utostr(Size); 94 DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned); 95 } 96 return DTy; 97 }; 98 99 unsigned NextLine = 1; 100 unsigned NextVar = 1; 101 auto File = DIB.createFile(M.getName(), "/"); 102 auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File, "debugify", 103 /*isOptimized=*/true, "", 0); 104 105 // Visit each instruction. 106 for (Function &F : Functions) { 107 if (isFunctionSkipped(F)) 108 continue; 109 110 bool InsertedDbgVal = false; 111 auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); 112 DISubprogram::DISPFlags SPFlags = 113 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized; 114 if (F.hasPrivateLinkage() || F.hasInternalLinkage()) 115 SPFlags |= DISubprogram::SPFlagLocalToUnit; 116 auto SP = DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, 117 SPType, NextLine, DINode::FlagZero, SPFlags); 118 F.setSubprogram(SP); 119 120 // Helper that inserts a dbg.value before \p InsertBefore, copying the 121 // location (and possibly the type, if it's non-void) from \p TemplateInst. 122 auto insertDbgVal = [&](Instruction &TemplateInst, 123 Instruction *InsertBefore) { 124 std::string Name = utostr(NextVar++); 125 Value *V = &TemplateInst; 126 if (TemplateInst.getType()->isVoidTy()) 127 V = ConstantInt::get(Int32Ty, 0); 128 const DILocation *Loc = TemplateInst.getDebugLoc().get(); 129 auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(), 130 getCachedDIType(V->getType()), 131 /*AlwaysPreserve=*/true); 132 DIB.insertDbgValueIntrinsic(V, LocalVar, DIB.createExpression(), Loc, 133 InsertBefore); 134 }; 135 136 for (BasicBlock &BB : F) { 137 // Attach debug locations. 138 for (Instruction &I : BB) 139 I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP)); 140 141 if (DebugifyLevel < Level::LocationsAndVariables) 142 continue; 143 144 // Inserting debug values into EH pads can break IR invariants. 145 if (BB.isEHPad()) 146 continue; 147 148 // Find the terminating instruction, after which no debug values are 149 // attached. 150 Instruction *LastInst = findTerminatingInstruction(BB); 151 assert(LastInst && "Expected basic block with a terminator"); 152 153 // Maintain an insertion point which can't be invalidated when updates 154 // are made. 155 BasicBlock::iterator InsertPt = BB.getFirstInsertionPt(); 156 assert(InsertPt != BB.end() && "Expected to find an insertion point"); 157 Instruction *InsertBefore = &*InsertPt; 158 159 // Attach debug values. 160 for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) { 161 // Skip void-valued instructions. 162 if (I->getType()->isVoidTy()) 163 continue; 164 165 // Phis and EH pads must be grouped at the beginning of the block. 166 // Only advance the insertion point when we finish visiting these. 167 if (!isa<PHINode>(I) && !I->isEHPad()) 168 InsertBefore = I->getNextNode(); 169 170 insertDbgVal(*I, InsertBefore); 171 InsertedDbgVal = true; 172 } 173 } 174 // Make sure we emit at least one dbg.value, otherwise MachineDebugify may 175 // not have anything to work with as it goes about inserting DBG_VALUEs. 176 // (It's common for MIR tests to be written containing skeletal IR with 177 // empty functions -- we're still interested in debugifying the MIR within 178 // those tests, and this helps with that.) 179 if (DebugifyLevel == Level::LocationsAndVariables && !InsertedDbgVal) { 180 auto *Term = findTerminatingInstruction(F.getEntryBlock()); 181 insertDbgVal(*Term, Term); 182 } 183 if (ApplyToMF) 184 ApplyToMF(DIB, F); 185 DIB.finalizeSubprogram(SP); 186 } 187 DIB.finalize(); 188 189 // Track the number of distinct lines and variables. 190 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify"); 191 auto addDebugifyOperand = [&](unsigned N) { 192 NMD->addOperand(MDNode::get( 193 Ctx, ValueAsMetadata::getConstant(ConstantInt::get(Int32Ty, N)))); 194 }; 195 addDebugifyOperand(NextLine - 1); // Original number of lines. 196 addDebugifyOperand(NextVar - 1); // Original number of variables. 197 assert(NMD->getNumOperands() == 2 && 198 "llvm.debugify should have exactly 2 operands!"); 199 200 // Claim that this synthetic debug info is valid. 201 StringRef DIVersionKey = "Debug Info Version"; 202 if (!M.getModuleFlag(DIVersionKey)) 203 M.addModuleFlag(Module::Warning, DIVersionKey, DEBUG_METADATA_VERSION); 204 205 return true; 206 } 207 208 static bool 209 applyDebugify(Function &F, 210 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, 211 DebugInfoPerPassMap *DIPreservationMap = nullptr, 212 StringRef NameOfWrappedPass = "") { 213 Module &M = *F.getParent(); 214 auto FuncIt = F.getIterator(); 215 if (Mode == DebugifyMode::SyntheticDebugInfo) 216 return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), 217 "FunctionDebugify: ", /*ApplyToMF*/ nullptr); 218 assert(DIPreservationMap); 219 return collectDebugInfoMetadata(M, M.functions(), *DIPreservationMap, 220 "FunctionDebugify (original debuginfo)", 221 NameOfWrappedPass); 222 } 223 224 static bool 225 applyDebugify(Module &M, 226 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, 227 DebugInfoPerPassMap *DIPreservationMap = nullptr, 228 StringRef NameOfWrappedPass = "") { 229 if (Mode == DebugifyMode::SyntheticDebugInfo) 230 return applyDebugifyMetadata(M, M.functions(), 231 "ModuleDebugify: ", /*ApplyToMF*/ nullptr); 232 return collectDebugInfoMetadata(M, M.functions(), *DIPreservationMap, 233 "ModuleDebugify (original debuginfo)", 234 NameOfWrappedPass); 235 } 236 237 bool llvm::stripDebugifyMetadata(Module &M) { 238 bool Changed = false; 239 240 // Remove the llvm.debugify module-level named metadata. 241 NamedMDNode *DebugifyMD = M.getNamedMetadata("llvm.debugify"); 242 if (DebugifyMD) { 243 M.eraseNamedMetadata(DebugifyMD); 244 Changed = true; 245 } 246 247 // Strip out all debug intrinsics and supporting metadata (subprograms, types, 248 // variables, etc). 249 Changed |= StripDebugInfo(M); 250 251 // Strip out the dead dbg.value prototype. 252 Function *DbgValF = M.getFunction("llvm.dbg.value"); 253 if (DbgValF) { 254 assert(DbgValF->isDeclaration() && DbgValF->use_empty() && 255 "Not all debug info stripped?"); 256 DbgValF->eraseFromParent(); 257 Changed = true; 258 } 259 260 // Strip out the module-level Debug Info Version metadata. 261 // FIXME: There must be an easier way to remove an operand from a NamedMDNode. 262 NamedMDNode *NMD = M.getModuleFlagsMetadata(); 263 if (!NMD) 264 return Changed; 265 SmallVector<MDNode *, 4> Flags(NMD->operands()); 266 NMD->clearOperands(); 267 for (MDNode *Flag : Flags) { 268 MDString *Key = dyn_cast_or_null<MDString>(Flag->getOperand(1)); 269 if (Key->getString() == "Debug Info Version") { 270 Changed = true; 271 continue; 272 } 273 NMD->addOperand(Flag); 274 } 275 // If we left it empty we might as well remove it. 276 if (NMD->getNumOperands() == 0) 277 NMD->eraseFromParent(); 278 279 return Changed; 280 } 281 282 bool llvm::collectDebugInfoMetadata(Module &M, 283 iterator_range<Module::iterator> Functions, 284 DebugInfoPerPassMap &DIPreservationMap, 285 StringRef Banner, 286 StringRef NameOfWrappedPass) { 287 LLVM_DEBUG(dbgs() << Banner << ": (before) " << NameOfWrappedPass << '\n'); 288 289 // Clear the map with the debug info before every single pass. 290 DIPreservationMap.clear(); 291 292 if (!M.getNamedMetadata("llvm.dbg.cu")) { 293 dbg() << Banner << ": Skipping module without debug info\n"; 294 return false; 295 } 296 297 // Visit each instruction. 298 for (Function &F : Functions) { 299 if (isFunctionSkipped(F)) 300 continue; 301 302 // Collect the DISubprogram. 303 auto *SP = F.getSubprogram(); 304 DIPreservationMap[NameOfWrappedPass].DIFunctions.insert({F.getName(), SP}); 305 if (SP) 306 LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n'); 307 308 for (BasicBlock &BB : F) { 309 // Collect debug locations (!dbg). 310 // TODO: Collect dbg.values. 311 for (Instruction &I : BB) { 312 // Skip PHIs. 313 if (isa<PHINode>(I)) 314 continue; 315 316 // Skip debug instructions. 317 if (isa<DbgInfoIntrinsic>(&I)) 318 continue; 319 320 LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n'); 321 DIPreservationMap[NameOfWrappedPass].InstToDelete.insert({&I, &I}); 322 323 const DILocation *Loc = I.getDebugLoc().get(); 324 bool HasLoc = Loc != nullptr; 325 DIPreservationMap[NameOfWrappedPass].DILocations.insert({&I, HasLoc}); 326 } 327 } 328 } 329 330 return true; 331 } 332 333 // This checks the preservation of original debug info attached to functions. 334 static bool checkFunctions(const DebugFnMap &DIFunctionsBefore, 335 const DebugFnMap &DIFunctionsAfter, 336 StringRef NameOfWrappedPass, 337 StringRef FileNameFromCU) { 338 bool Preserved = true; 339 for (const auto &F : DIFunctionsAfter) { 340 if (F.second) 341 continue; 342 auto SPIt = DIFunctionsBefore.find(F.first); 343 if (SPIt == DIFunctionsBefore.end()) { 344 dbg() << "ERROR: " << NameOfWrappedPass 345 << " did not generate DISubprogram for " << F.first << " from " 346 << FileNameFromCU << '\n'; 347 Preserved = false; 348 } else { 349 auto SP = SPIt->second; 350 if (!SP) 351 continue; 352 // If the function had the SP attached before the pass, consider it as 353 // a debug info bug. 354 dbg() << "ERROR: " << NameOfWrappedPass << " dropped DISubprogram of " 355 << F.first << " from " << FileNameFromCU << '\n'; 356 Preserved = false; 357 } 358 } 359 360 return Preserved; 361 } 362 363 // This checks the preservation of the original debug info attached to 364 // instructions. 365 static bool checkInstructions(const DebugInstMap &DILocsBefore, 366 const DebugInstMap &DILocsAfter, 367 const WeakInstValueMap &InstToDelete, 368 StringRef NameOfWrappedPass, 369 StringRef FileNameFromCU) { 370 bool Preserved = true; 371 for (const auto &L : DILocsAfter) { 372 if (L.second) 373 continue; 374 auto Instr = L.first; 375 376 // In order to avoid pointer reuse/recycling, skip the values that might 377 // have been deleted during a pass. 378 auto WeakInstrPtr = InstToDelete.find(Instr); 379 if (WeakInstrPtr != InstToDelete.end() && !WeakInstrPtr->second) 380 continue; 381 382 auto FnName = Instr->getFunction()->getName(); 383 auto BB = Instr->getParent(); 384 auto BBName = BB->hasName() ? BB->getName() : "no-name"; 385 386 auto InstrIt = DILocsBefore.find(Instr); 387 if (InstrIt == DILocsBefore.end()) { 388 dbg() << "WARNING: " << NameOfWrappedPass 389 << " did not generate DILocation for " << *Instr 390 << " (BB: " << BBName << ", Fn: " << FnName 391 << ", File: " << FileNameFromCU << ")\n"; 392 Preserved = false; 393 } else { 394 if (!InstrIt->second) 395 continue; 396 // If the instr had the !dbg attached before the pass, consider it as 397 // a debug info issue. 398 dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of " 399 << *Instr << " (BB: " << BBName << ", Fn: " << FnName 400 << ", File: " << FileNameFromCU << ")\n"; 401 Preserved = false; 402 } 403 } 404 405 return Preserved; 406 } 407 408 bool llvm::checkDebugInfoMetadata(Module &M, 409 iterator_range<Module::iterator> Functions, 410 DebugInfoPerPassMap &DIPreservationMap, 411 StringRef Banner, 412 StringRef NameOfWrappedPass) { 413 LLVM_DEBUG(dbgs() << Banner << ": (after) " << NameOfWrappedPass << '\n'); 414 415 if (!M.getNamedMetadata("llvm.dbg.cu")) { 416 dbg() << Banner << ": Skipping module without debug info\n"; 417 return false; 418 } 419 420 // Map the debug info holding DIs after a pass. 421 DebugInfoPerPassMap DIPreservationAfter; 422 423 // Visit each instruction. 424 for (Function &F : Functions) { 425 if (isFunctionSkipped(F)) 426 continue; 427 428 // TODO: Collect metadata other than DISubprograms. 429 // Collect the DISubprogram. 430 auto *SP = F.getSubprogram(); 431 DIPreservationAfter[NameOfWrappedPass].DIFunctions.insert({F.getName(), SP}); 432 if (SP) 433 LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n'); 434 435 for (BasicBlock &BB : F) { 436 // Collect debug locations (!dbg attachments). 437 // TODO: Collect dbg.values. 438 for (Instruction &I : BB) { 439 // Skip PHIs. 440 if (isa<PHINode>(I)) 441 continue; 442 443 // Skip debug instructions. 444 if (isa<DbgInfoIntrinsic>(&I)) 445 continue; 446 447 LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n'); 448 449 const DILocation *Loc = I.getDebugLoc().get(); 450 bool HasLoc = Loc != nullptr; 451 452 DIPreservationAfter[NameOfWrappedPass].DILocations.insert({&I, HasLoc}); 453 } 454 } 455 } 456 457 // TODO: The name of the module could be read better? 458 StringRef FileNameFromCU = 459 (cast<DICompileUnit>(M.getNamedMetadata("llvm.dbg.cu")->getOperand(0))) 460 ->getFilename(); 461 462 auto DIFunctionsBefore = DIPreservationMap[NameOfWrappedPass].DIFunctions; 463 auto DIFunctionsAfter = DIPreservationAfter[NameOfWrappedPass].DIFunctions; 464 465 auto DILocsBefore = DIPreservationMap[NameOfWrappedPass].DILocations; 466 auto DILocsAfter = DIPreservationAfter[NameOfWrappedPass].DILocations; 467 468 auto InstToDelete = DIPreservationAfter[NameOfWrappedPass].InstToDelete; 469 470 bool ResultForFunc = checkFunctions(DIFunctionsBefore, DIFunctionsAfter, 471 NameOfWrappedPass, FileNameFromCU); 472 bool ResultForInsts = 473 checkInstructions(DILocsBefore, DILocsAfter, InstToDelete, 474 NameOfWrappedPass, FileNameFromCU); 475 bool Result = ResultForFunc && ResultForInsts; 476 477 StringRef ResultBanner = NameOfWrappedPass != "" ? NameOfWrappedPass : Banner; 478 if (Result) 479 dbg() << ResultBanner << ": PASS\n"; 480 else 481 dbg() << ResultBanner << ": FAIL\n"; 482 483 LLVM_DEBUG(dbgs() << "\n\n"); 484 return Result; 485 } 486 487 namespace { 488 /// Return true if a mis-sized diagnostic is issued for \p DVI. 489 bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) { 490 // The size of a dbg.value's value operand should match the size of the 491 // variable it corresponds to. 492 // 493 // TODO: This, along with a check for non-null value operands, should be 494 // promoted to verifier failures. 495 Value *V = DVI->getValue(); 496 if (!V) 497 return false; 498 499 // For now, don't try to interpret anything more complicated than an empty 500 // DIExpression. Eventually we should try to handle OP_deref and fragments. 501 if (DVI->getExpression()->getNumElements()) 502 return false; 503 504 Type *Ty = V->getType(); 505 uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty); 506 Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits(); 507 if (!ValueOperandSize || !DbgVarSize) 508 return false; 509 510 bool HasBadSize = false; 511 if (Ty->isIntegerTy()) { 512 auto Signedness = DVI->getVariable()->getSignedness(); 513 if (Signedness && *Signedness == DIBasicType::Signedness::Signed) 514 HasBadSize = ValueOperandSize < *DbgVarSize; 515 } else { 516 HasBadSize = ValueOperandSize != *DbgVarSize; 517 } 518 519 if (HasBadSize) { 520 dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize 521 << ", but its variable has size " << *DbgVarSize << ": "; 522 DVI->print(dbg()); 523 dbg() << "\n"; 524 } 525 return HasBadSize; 526 } 527 528 bool checkDebugifyMetadata(Module &M, 529 iterator_range<Module::iterator> Functions, 530 StringRef NameOfWrappedPass, StringRef Banner, 531 bool Strip, DebugifyStatsMap *StatsMap) { 532 // Skip modules without debugify metadata. 533 NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify"); 534 if (!NMD) { 535 dbg() << Banner << ": Skipping module without debugify metadata\n"; 536 return false; 537 } 538 539 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned { 540 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0)) 541 ->getZExtValue(); 542 }; 543 assert(NMD->getNumOperands() == 2 && 544 "llvm.debugify should have exactly 2 operands!"); 545 unsigned OriginalNumLines = getDebugifyOperand(0); 546 unsigned OriginalNumVars = getDebugifyOperand(1); 547 bool HasErrors = false; 548 549 // Track debug info loss statistics if able. 550 DebugifyStatistics *Stats = nullptr; 551 if (StatsMap && !NameOfWrappedPass.empty()) 552 Stats = &StatsMap->operator[](NameOfWrappedPass); 553 554 BitVector MissingLines{OriginalNumLines, true}; 555 BitVector MissingVars{OriginalNumVars, true}; 556 for (Function &F : Functions) { 557 if (isFunctionSkipped(F)) 558 continue; 559 560 // Find missing lines. 561 for (Instruction &I : instructions(F)) { 562 if (isa<DbgValueInst>(&I) || isa<PHINode>(&I)) 563 continue; 564 565 auto DL = I.getDebugLoc(); 566 if (DL && DL.getLine() != 0) { 567 MissingLines.reset(DL.getLine() - 1); 568 continue; 569 } 570 571 if (!DL) { 572 dbg() << "WARNING: Instruction with empty DebugLoc in function "; 573 dbg() << F.getName() << " --"; 574 I.print(dbg()); 575 dbg() << "\n"; 576 } 577 } 578 579 // Find missing variables and mis-sized debug values. 580 for (Instruction &I : instructions(F)) { 581 auto *DVI = dyn_cast<DbgValueInst>(&I); 582 if (!DVI) 583 continue; 584 585 unsigned Var = ~0U; 586 (void)to_integer(DVI->getVariable()->getName(), Var, 10); 587 assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable"); 588 bool HasBadSize = diagnoseMisSizedDbgValue(M, DVI); 589 if (!HasBadSize) 590 MissingVars.reset(Var - 1); 591 HasErrors |= HasBadSize; 592 } 593 } 594 595 // Print the results. 596 for (unsigned Idx : MissingLines.set_bits()) 597 dbg() << "WARNING: Missing line " << Idx + 1 << "\n"; 598 599 for (unsigned Idx : MissingVars.set_bits()) 600 dbg() << "WARNING: Missing variable " << Idx + 1 << "\n"; 601 602 // Update DI loss statistics. 603 if (Stats) { 604 Stats->NumDbgLocsExpected += OriginalNumLines; 605 Stats->NumDbgLocsMissing += MissingLines.count(); 606 Stats->NumDbgValuesExpected += OriginalNumVars; 607 Stats->NumDbgValuesMissing += MissingVars.count(); 608 } 609 610 dbg() << Banner; 611 if (!NameOfWrappedPass.empty()) 612 dbg() << " [" << NameOfWrappedPass << "]"; 613 dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n'; 614 615 // Strip debugify metadata if required. 616 if (Strip) 617 return stripDebugifyMetadata(M); 618 619 return false; 620 } 621 622 /// ModulePass for attaching synthetic debug info to everything, used with the 623 /// legacy module pass manager. 624 struct DebugifyModulePass : public ModulePass { 625 bool runOnModule(Module &M) override { 626 return applyDebugify(M, Mode, DIPreservationMap, NameOfWrappedPass); 627 } 628 629 DebugifyModulePass(enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, 630 StringRef NameOfWrappedPass = "", 631 DebugInfoPerPassMap *DIPreservationMap = nullptr) 632 : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass), 633 DIPreservationMap(DIPreservationMap), Mode(Mode) {} 634 635 void getAnalysisUsage(AnalysisUsage &AU) const override { 636 AU.setPreservesAll(); 637 } 638 639 static char ID; // Pass identification. 640 641 private: 642 StringRef NameOfWrappedPass; 643 DebugInfoPerPassMap *DIPreservationMap; 644 enum DebugifyMode Mode; 645 }; 646 647 /// FunctionPass for attaching synthetic debug info to instructions within a 648 /// single function, used with the legacy module pass manager. 649 struct DebugifyFunctionPass : public FunctionPass { 650 bool runOnFunction(Function &F) override { 651 return applyDebugify(F, Mode, DIPreservationMap, NameOfWrappedPass); 652 } 653 654 DebugifyFunctionPass( 655 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, 656 StringRef NameOfWrappedPass = "", 657 DebugInfoPerPassMap *DIPreservationMap = nullptr) 658 : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass), 659 DIPreservationMap(DIPreservationMap), Mode(Mode) {} 660 661 void getAnalysisUsage(AnalysisUsage &AU) const override { 662 AU.setPreservesAll(); 663 } 664 665 static char ID; // Pass identification. 666 667 private: 668 StringRef NameOfWrappedPass; 669 DebugInfoPerPassMap *DIPreservationMap; 670 enum DebugifyMode Mode; 671 }; 672 673 /// ModulePass for checking debug info inserted by -debugify, used with the 674 /// legacy module pass manager. 675 struct CheckDebugifyModulePass : public ModulePass { 676 bool runOnModule(Module &M) override { 677 if (Mode == DebugifyMode::SyntheticDebugInfo) 678 return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass, 679 "CheckModuleDebugify", Strip, StatsMap); 680 return checkDebugInfoMetadata( 681 M, M.functions(), *DIPreservationMap, 682 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass); 683 } 684 685 CheckDebugifyModulePass( 686 bool Strip = false, StringRef NameOfWrappedPass = "", 687 DebugifyStatsMap *StatsMap = nullptr, 688 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, 689 DebugInfoPerPassMap *DIPreservationMap = nullptr) 690 : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass), 691 StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode), 692 Strip(Strip) {} 693 694 void getAnalysisUsage(AnalysisUsage &AU) const override { 695 AU.setPreservesAll(); 696 } 697 698 static char ID; // Pass identification. 699 700 private: 701 StringRef NameOfWrappedPass; 702 DebugifyStatsMap *StatsMap; 703 DebugInfoPerPassMap *DIPreservationMap; 704 enum DebugifyMode Mode; 705 bool Strip; 706 }; 707 708 /// FunctionPass for checking debug info inserted by -debugify-function, used 709 /// with the legacy module pass manager. 710 struct CheckDebugifyFunctionPass : public FunctionPass { 711 bool runOnFunction(Function &F) override { 712 Module &M = *F.getParent(); 713 auto FuncIt = F.getIterator(); 714 if (Mode == DebugifyMode::SyntheticDebugInfo) 715 return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), 716 NameOfWrappedPass, "CheckFunctionDebugify", 717 Strip, StatsMap); 718 return checkDebugInfoMetadata( 719 M, make_range(FuncIt, std::next(FuncIt)), *DIPreservationMap, 720 "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass); 721 } 722 723 CheckDebugifyFunctionPass( 724 bool Strip = false, StringRef NameOfWrappedPass = "", 725 DebugifyStatsMap *StatsMap = nullptr, 726 enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo, 727 DebugInfoPerPassMap *DIPreservationMap = nullptr) 728 : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass), 729 StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode), 730 Strip(Strip) {} 731 732 void getAnalysisUsage(AnalysisUsage &AU) const override { 733 AU.setPreservesAll(); 734 } 735 736 static char ID; // Pass identification. 737 738 private: 739 StringRef NameOfWrappedPass; 740 DebugifyStatsMap *StatsMap; 741 DebugInfoPerPassMap *DIPreservationMap; 742 enum DebugifyMode Mode; 743 bool Strip; 744 }; 745 746 } // end anonymous namespace 747 748 void llvm::exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map) { 749 std::error_code EC; 750 raw_fd_ostream OS{Path, EC}; 751 if (EC) { 752 errs() << "Could not open file: " << EC.message() << ", " << Path << '\n'; 753 return; 754 } 755 756 OS << "Pass Name" << ',' << "# of missing debug values" << ',' 757 << "# of missing locations" << ',' << "Missing/Expected value ratio" << ',' 758 << "Missing/Expected location ratio" << '\n'; 759 for (const auto &Entry : Map) { 760 StringRef Pass = Entry.first; 761 DebugifyStatistics Stats = Entry.second; 762 763 OS << Pass << ',' << Stats.NumDbgValuesMissing << ',' 764 << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ',' 765 << Stats.getEmptyLocationRatio() << '\n'; 766 } 767 } 768 769 ModulePass *createDebugifyModulePass(enum DebugifyMode Mode, 770 llvm::StringRef NameOfWrappedPass, 771 DebugInfoPerPassMap *DIPreservationMap) { 772 if (Mode == DebugifyMode::SyntheticDebugInfo) 773 return new DebugifyModulePass(); 774 assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode"); 775 return new DebugifyModulePass(Mode, NameOfWrappedPass, DIPreservationMap); 776 } 777 778 FunctionPass * 779 createDebugifyFunctionPass(enum DebugifyMode Mode, 780 llvm::StringRef NameOfWrappedPass, 781 DebugInfoPerPassMap *DIPreservationMap) { 782 if (Mode == DebugifyMode::SyntheticDebugInfo) 783 return new DebugifyFunctionPass(); 784 assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode"); 785 return new DebugifyFunctionPass(Mode, NameOfWrappedPass, DIPreservationMap); 786 } 787 788 PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) { 789 applyDebugifyMetadata(M, M.functions(), 790 "ModuleDebugify: ", /*ApplyToMF*/ nullptr); 791 return PreservedAnalyses::all(); 792 } 793 794 ModulePass *createCheckDebugifyModulePass( 795 bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap, 796 enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap) { 797 if (Mode == DebugifyMode::SyntheticDebugInfo) 798 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap); 799 assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode"); 800 return new CheckDebugifyModulePass(false, NameOfWrappedPass, nullptr, Mode, 801 DIPreservationMap); 802 } 803 804 FunctionPass *createCheckDebugifyFunctionPass( 805 bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap, 806 enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap) { 807 if (Mode == DebugifyMode::SyntheticDebugInfo) 808 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap); 809 assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode"); 810 return new CheckDebugifyFunctionPass(false, NameOfWrappedPass, nullptr, Mode, 811 DIPreservationMap); 812 } 813 814 PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M, 815 ModuleAnalysisManager &) { 816 checkDebugifyMetadata(M, M.functions(), "", "CheckModuleDebugify", false, 817 nullptr); 818 return PreservedAnalyses::all(); 819 } 820 821 static bool isIgnoredPass(StringRef PassID) { 822 return isSpecialPass(PassID, {"PassManager", "PassAdaptor", 823 "AnalysisManagerProxy", "PrintFunctionPass", 824 "PrintModulePass", "BitcodeWriterPass", 825 "ThinLTOBitcodeWriterPass", "VerifierPass"}); 826 } 827 828 void DebugifyEachInstrumentation::registerCallbacks( 829 PassInstrumentationCallbacks &PIC) { 830 PIC.registerBeforeNonSkippedPassCallback([](StringRef P, Any IR) { 831 if (isIgnoredPass(P)) 832 return; 833 if (any_isa<const Function *>(IR)) 834 applyDebugify(*const_cast<Function *>(any_cast<const Function *>(IR))); 835 else if (any_isa<const Module *>(IR)) 836 applyDebugify(*const_cast<Module *>(any_cast<const Module *>(IR))); 837 }); 838 PIC.registerAfterPassCallback([this](StringRef P, Any IR, 839 const PreservedAnalyses &PassPA) { 840 if (isIgnoredPass(P)) 841 return; 842 if (any_isa<const Function *>(IR)) { 843 auto &F = *const_cast<Function *>(any_cast<const Function *>(IR)); 844 Module &M = *F.getParent(); 845 auto It = F.getIterator(); 846 checkDebugifyMetadata(M, make_range(It, std::next(It)), P, 847 "CheckFunctionDebugify", /*Strip=*/true, &StatsMap); 848 } else if (any_isa<const Module *>(IR)) { 849 auto &M = *const_cast<Module *>(any_cast<const Module *>(IR)); 850 checkDebugifyMetadata(M, M.functions(), P, "CheckModuleDebugify", 851 /*Strip=*/true, &StatsMap); 852 } 853 }); 854 } 855 856 char DebugifyModulePass::ID = 0; 857 static RegisterPass<DebugifyModulePass> DM("debugify", 858 "Attach debug info to everything"); 859 860 char CheckDebugifyModulePass::ID = 0; 861 static RegisterPass<CheckDebugifyModulePass> 862 CDM("check-debugify", "Check debug info from -debugify"); 863 864 char DebugifyFunctionPass::ID = 0; 865 static RegisterPass<DebugifyFunctionPass> DF("debugify-function", 866 "Attach debug info to a function"); 867 868 char CheckDebugifyFunctionPass::ID = 0; 869 static RegisterPass<CheckDebugifyFunctionPass> 870 CDF("check-debugify-function", "Check debug info from -debugify-function"); 871