LLVM: lib/Transforms/Utils/Debugify.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

19#include "llvm/Config/llvm-config.h"

32#include

33#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN

34

35

37#endif

38

39#define DEBUG_TYPE "debugify"

40

41using namespace llvm;

42

43namespace {

44

46

48 cl::desc("Suppress verbose debugify output"));

49

51 "debugify-func-limit",

52 cl::desc("Set max number of processed functions per pass."),

54

55enum class Level {

56 Locations,

57 LocationsAndVariables

58};

59

61 "debugify-level", cl::desc("Kind of debug info to add"),

63 clEnumValN(Level::LocationsAndVariables, "location+variables",

64 "Locations and Variables")),

65 cl::init(Level::LocationsAndVariables));

66

68

69#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN

70

71

72static SymbolizedAddressMap SymbolizedAddrs;

73static AddressSet UnsymbolizedAddrs;

74

75std::string symbolizeStackTrace(const Instruction *I) {

76

77

78 if (!UnsymbolizedAddrs.empty()) {

79 sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs);

80 UnsymbolizedAddrs.clear();

81 }

82 const DbgLocOrigin::StackTracesTy &OriginStackTraces =

83 I->getDebugLoc().getOriginStackTraces();

84 std::string Result;

86 for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) {

87 if (TraceIdx != 0)

88 OS << "========================================\n";

89 auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];

90 unsigned VirtualFrameNo = 0;

91 for (int Frame = 0; Frame < Depth; ++Frame) {

92 assert(SymbolizedAddrs.contains(StackTrace[Frame]) &&

93 "Expected each address to have been symbolized.");

94 for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) {

96 std::log10(Depth) + 2)

97 << ' ' << SymbolizedFrame << '\n';

98 }

99 }

100 }

101 return Result;

102}

104 auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces();

105 for (auto &[Depth, StackTrace] : OriginStackTraces) {

106 for (int Frame = 0; Frame < Depth; ++Frame) {

107 void *Addr = StackTrace[Frame];

108 if (!SymbolizedAddrs.contains(Addr))

109 UnsymbolizedAddrs.insert(Addr);

110 }

111 }

112}

113#else

115#endif

116

118 return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0;

119}

120

121bool isFunctionSkipped(Function &F) {

122 return F.isDeclaration() || F.hasExactDefinition();

123}

124

125

126

127

128

131 return I;

133 return I;

135}

136}

137

141

142 if (M.getNamedMetadata("llvm.dbg.cu")) {

143 dbg() << Banner << "Skipping module with debug info\n";

144 return false;

145 }

146

150

151

153 auto getCachedDIType = [&](Type *Ty) -> DIType * {

156 if (!DTy) {

159 }

160 return DTy;

161 };

162

163 unsigned NextLine = 1;

164 unsigned NextVar = 1;

167 "debugify", true, "", 0);

168

169

171 if (isFunctionSkipped(F))

172 continue;

173

174 bool InsertedDbgVal = false;

177 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized;

178 if (F.hasPrivateLinkage() || F.hasInternalLinkage())

179 SPFlags |= DISubprogram::SPFlagLocalToUnit;

180 auto SP = DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine,

181 SPType, NextLine, DINode::FlagZero, SPFlags,

182 nullptr, nullptr, nullptr, nullptr, "",

183 ApplyAtomGroups);

184 F.setSubprogram(SP);

185

186

187

188 auto insertDbgVal = [&](Instruction &TemplateInst,

190 std::string Name = utostr(NextVar++);

191 Value *V = &TemplateInst;

193 V = ConstantInt::get(Int32Ty, 0);

196 getCachedDIType(V->getType()),

197 true);

199 InsertPt);

200 };

201

203

205 uint64_t AtomGroup = ApplyAtomGroups ? NextLine : 0;

206 uint8_t AtomRank = ApplyAtomGroups ? 1 : 0;

208 I.setDebugLoc(DILocation::get(Ctx, Line, 1, SP, nullptr, false,

209 AtomGroup, AtomRank));

210 }

211

212 if (DebugifyLevel < Level::LocationsAndVariables)

213 continue;

214

215

216 if (BB.isEHPad())

217 continue;

218

219

220

221 Instruction *LastInst = findTerminatingInstruction(BB);

222 assert(LastInst && "Expected basic block with a terminator");

223

224

225

227 assert(InsertPt != BB.end() && "Expected to find an insertion point");

228

229

230 InsertPt.setHeadBit(false);

231

232

233 for (Instruction *I = &*BB.begin(); I != LastInst; I = I->getNextNode()) {

234

235 if (I->getType()->isVoidTy())

236 continue;

237

238

239

241 InsertPt = std::next(I->getIterator());

242

243 insertDbgVal(*I, InsertPt);

244 InsertedDbgVal = true;

245 }

246 }

247

248

249

250

251

252 if (DebugifyLevel == Level::LocationsAndVariables && !InsertedDbgVal) {

253 auto *Term = findTerminatingInstruction(F.getEntryBlock());

254 insertDbgVal(*Term, Term->getIterator());

255 }

256 if (ApplyToMF)

257 ApplyToMF(DIB, F);

258 }

260

261

262 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");

263 auto addDebugifyOperand = [&](unsigned N) {

266 };

267 addDebugifyOperand(NextLine - 1);

268 addDebugifyOperand(NextVar - 1);

270 "llvm.debugify should have exactly 2 operands!");

271

272

273 StringRef DIVersionKey = "Debug Info Version";

274 if (!M.getModuleFlag(DIVersionKey))

276

277 return true;

278}

279

282 StringRef NameOfWrappedPass = "") {

283 Module &M = *F.getParent();

284 auto FuncIt = F.getIterator();

287 "FunctionDebugify: ", nullptr);

288 assert(DebugInfoBeforePass && "Missing debug info metadata");

290 "FunctionDebugify (original debuginfo)",

291 NameOfWrappedPass);

292}

293

296 StringRef NameOfWrappedPass = "") {

299 "ModuleDebugify: ", nullptr);

300 assert(DebugInfoBeforePass && "Missing debug info metadata");

302 "ModuleDebugify (original debuginfo)",

303 NameOfWrappedPass);

304}

305

308

309

310 NamedMDNode *DebugifyMD = M.getNamedMetadata("llvm.debugify");

311 if (DebugifyMD) {

312 M.eraseNamedMetadata(DebugifyMD);

314 }

315

316 if (auto *MIRDebugifyMD = M.getNamedMetadata("llvm.mir.debugify")) {

317 M.eraseNamedMetadata(MIRDebugifyMD);

319 }

320

321

322

324

325

327 if (DbgValF) {

329 "Not all debug info stripped?");

332 }

333

334

335

336 NamedMDNode *NMD = M.getModuleFlagsMetadata();

337 if (!NMD)

341 for (MDNode *Flag : Flags) {

343 if (Key->getString() == "Debug Info Version") {

345 continue;

346 }

348 }

349

352

354}

355

358#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE

359 DebugLocKind Kind = I.getDebugLoc().getKind();

360 return Loc || Kind != DebugLocKind::Normal;

361#else

362 return Loc;

363#endif

364}

365

371 LLVM_DEBUG(dbgs() << Banner << ": (before) " << NameOfWrappedPass << '\n');

372

373 if (!M.getNamedMetadata("llvm.dbg.cu")) {

374 dbg() << Banner << ": Skipping module without debug info\n";

375 return false;

376 }

377

379

381

383 continue;

384

385 if (isFunctionSkipped(F))

386 continue;

387

388

389 if (++FunctionsCnt >= DebugifyFunctionsLimit)

390 break;

391

392 auto *SP = F.getSubprogram();

394 if (SP) {

395 LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');

396 for (const DINode *DN : SP->getRetainedNodes()) {

399 }

400 }

401 }

402

404

406

408 continue;

409

410

411 if (DebugifyLevel > Level::Locations) {

413 if (!SP)

414 return;

415

416 if (DbgVar->getDebugLoc().getInlinedAt())

417 return;

418

419 if (DbgVar->isKillLocation())

420 return;

421

422 auto *Var = DbgVar->getVariable();

424 };

426 HandleDbgVariable(&DVR);

427 }

428

429 LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n');

431

432

433 collectStackAddresses(I);

435 }

436 }

437 }

438

439 return true;

440}

441

442

446 StringRef FileNameFromCU, bool ShouldWriteIntoJSON,

448 bool Preserved = true;

449 for (const auto &F : DIFunctionsAfter) {

450 if (F.second)

451 continue;

452 auto SPIt = DIFunctionsBefore.find(F.first);

453 if (SPIt == DIFunctionsBefore.end()) {

454 if (ShouldWriteIntoJSON)

456 {"name", F.first->getName()},

457 {"action", "not-generate"}}));

458 else

459 dbg() << "ERROR: " << NameOfWrappedPass

460 << " did not generate DISubprogram for " << F.first->getName()

461 << " from " << FileNameFromCU << '\n';

462 Preserved = false;

463 } else {

464 auto SP = SPIt->second;

465 if (!SP)

466 continue;

467

468

469 if (ShouldWriteIntoJSON)

471 {"name", F.first->getName()},

472 {"action", "drop"}}));

473 else

474 dbg() << "ERROR: " << NameOfWrappedPass << " dropped DISubprogram of "

475 << F.first->getName() << " from " << FileNameFromCU << '\n';

476 Preserved = false;

477 }

478 }

479

480 return Preserved;

481}

482

483

484

490 bool ShouldWriteIntoJSON,

492 bool Preserved = true;

493 for (const auto &L : DILocsAfter) {

494 if (L.second)

495 continue;

496 auto Instr = L.first;

497

498

499

500 auto WeakInstrPtr = InstToDelete.find(Instr);

501 if (WeakInstrPtr != InstToDelete.end() && !WeakInstrPtr->second)

502 continue;

503

504 auto FnName = Instr->getFunction()->getName();

505 auto BB = Instr->getParent();

506 auto BBName = BB->hasName() ? BB->getName() : "no-name";

508

509 auto CreateJSONBugEntry = [&](const char *Action) {

511 {"metadata", "DILocation"},

512 {"fn-name", FnName.str()},

513 {"bb-name", BBName.str()},

514 {"instr", InstName},

515 {"action", Action},

516#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN

517 {"origin", symbolizeStackTrace(Instr)},

518#endif

519 }));

520 };

521

522 auto InstrIt = DILocsBefore.find(Instr);

523 if (InstrIt == DILocsBefore.end()) {

524 if (ShouldWriteIntoJSON)

525 CreateJSONBugEntry("not-generate");

526 else

527 dbg() << "WARNING: " << NameOfWrappedPass

528 << " did not generate DILocation for " << *Instr

529 << " (BB: " << BBName << ", Fn: " << FnName

530 << ", File: " << FileNameFromCU << ")\n";

531 Preserved = false;

532 } else {

533 if (!InstrIt->second)

534 continue;

535

536

537 if (ShouldWriteIntoJSON)

538 CreateJSONBugEntry("drop");

539 else

540 dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of "

541 << *Instr << " (BB: " << BBName << ", Fn: " << FnName

542 << ", File: " << FileNameFromCU << ")\n";

543 Preserved = false;

544 }

545 }

546

547 return Preserved;

548}

549

550

555 bool Preserved = true;

556 for (const auto &V : DIVarsBefore) {

557 auto VarIt = DIVarsAfter.find(V.first);

558 if (VarIt == DIVarsAfter.end())

559 continue;

560

561 unsigned NumOfDbgValsAfter = VarIt->second;

562

563 if (V.second > NumOfDbgValsAfter) {

564 if (ShouldWriteIntoJSON)

566 {{"metadata", "dbg-var-intrinsic"},

567 {"name", V.first->getName()},

568 {"fn-name", V.first->getScope()->getSubprogram()->getName()},

569 {"action", "drop"}}));

570 else

571 dbg() << "WARNING: " << NameOfWrappedPass

572 << " drops dbg.value()/dbg.declare() for " << V.first->getName()

573 << " from "

574 << "function " << V.first->getScope()->getSubprogram()->getName()

575 << " (file " << FileNameFromCU << ")\n";

576 Preserved = false;

577 }

578 }

579

580 return Preserved;

581}

582

583

587 std::error_code EC;

588 raw_fd_ostream OS_FILE{OrigDIVerifyBugsReportFilePath, EC,

590 if (EC) {

591 errs() << "Could not open file: " << EC.message() << ", "

592 << OrigDIVerifyBugsReportFilePath << '\n';

593 return;

594 }

595

596 if (auto L = OS_FILE.lock()) {

597 OS_FILE << "{\"file\":\"" << FileNameFromCU << "\", ";

598

600 NameOfWrappedPass != "" ? NameOfWrappedPass : "no-name";

601 OS_FILE << "\"pass\":\"" << PassName << "\", ";

602

604 OS_FILE << "\"bugs\": " << BugsToPrint;

605

606 OS_FILE << "}\n";

607 }

609}

610

615 StringRef OrigDIVerifyBugsReportFilePath) {

616 LLVM_DEBUG(dbgs() << Banner << ": (after) " << NameOfWrappedPass << '\n');

617

618 if (!M.getNamedMetadata("llvm.dbg.cu")) {

619 dbg() << Banner << ": Skipping module without debug info\n";

620 return false;

621 }

622

623

625

626

628 if (isFunctionSkipped(F))

629 continue;

630

631

633 continue;

634

635

636 auto *SP = F.getSubprogram();

638

639 if (SP) {

640 LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');

641 for (const DINode *DN : SP->getRetainedNodes()) {

644 }

645 }

646 }

647

649

651

653 continue;

654

655

656 if (DebugifyLevel > Level::Locations) {

658 if (!SP)

659 return;

660

661 if (DbgVar->getDebugLoc().getInlinedAt())

662 return;

663

664 if (DbgVar->isKillLocation())

665 return;

666

667 auto *Var = DbgVar->getVariable();

669 };

671 HandleDbgVariable(&DVR);

672 }

673

674 LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n');

675

676

677 collectStackAddresses(I);

679 }

680 }

681 }

682

683

687

688 auto DIFunctionsBefore = DebugInfoBeforePass.DIFunctions;

689 auto DIFunctionsAfter = DebugInfoAfterPass.DIFunctions;

690

691 auto DILocsBefore = DebugInfoBeforePass.DILocations;

692 auto DILocsAfter = DebugInfoAfterPass.DILocations;

693

694 auto InstToDelete = DebugInfoBeforePass.InstToDelete;

695

696 auto DIVarsBefore = DebugInfoBeforePass.DIVariables;

697 auto DIVarsAfter = DebugInfoAfterPass.DIVariables;

698

699 bool ShouldWriteIntoJSON = !OrigDIVerifyBugsReportFilePath.empty();

701

702 bool ResultForFunc =

703 checkFunctions(DIFunctionsBefore, DIFunctionsAfter, NameOfWrappedPass,

704 FileNameFromCU, ShouldWriteIntoJSON, Bugs);

706 DILocsBefore, DILocsAfter, InstToDelete, NameOfWrappedPass,

707 FileNameFromCU, ShouldWriteIntoJSON, Bugs);

708

709#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE

710

711

712

713 for (auto &L : DILocsAfter)

714 if (!L.second)

716#endif

717

718 bool ResultForVars = checkVars(DIVarsBefore, DIVarsAfter, NameOfWrappedPass,

719 FileNameFromCU, ShouldWriteIntoJSON, Bugs);

720

721 bool Result = ResultForFunc && ResultForInsts && ResultForVars;

722

723 StringRef ResultBanner = NameOfWrappedPass != "" ? NameOfWrappedPass : Banner;

724 if (ShouldWriteIntoJSON && !Bugs.empty())

725 writeJSON(OrigDIVerifyBugsReportFilePath, FileNameFromCU, NameOfWrappedPass,

726 Bugs);

727

728 if (Result)

729 dbg() << ResultBanner << ": PASS\n";

730 else

731 dbg() << ResultBanner << ": FAIL\n";

732

733

734

735

736 DebugInfoBeforePass = DebugInfoAfterPass;

737

739 return Result;

740}

741

742namespace {

743

744template

745bool diagnoseMisSizedDbgValue(Module &M, DbgValTy *DbgVal) {

746

747

748

749

750

751

752

753

754 if (DbgVal->getExpression()->getNumElements())

755 return false;

756

757 Value *V = DbgVal->getVariableLocationOp(0);

758 if (!V)

759 return false;

760

761 Type *Ty = V->getType();

762 uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);

763 std::optional<uint64_t> DbgVarSize = DbgVal->getFragmentSizeInBits();

764 if (!ValueOperandSize || !DbgVarSize)

765 return false;

766

767 bool HasBadSize = false;

768 if (Ty->isIntegerTy()) {

769 auto Signedness = DbgVal->getVariable()->getSignedness();

771 HasBadSize = ValueOperandSize < *DbgVarSize;

772 } else {

773 HasBadSize = ValueOperandSize != *DbgVarSize;

774 }

775

776 if (HasBadSize) {

777 dbg() << "ERROR: dbg.value operand has size " << ValueOperandSize

778 << ", but its variable has size " << *DbgVarSize << ": ";

779 DbgVal->print(dbg());

780 dbg() << "\n";

781 }

782 return HasBadSize;

783}

784

785bool checkDebugifyMetadata(Module &M,

789

790 NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");

791 if (!NMD) {

792 dbg() << Banner << ": Skipping module without debugify metadata\n";

793 return false;

794 }

795

796 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {

798 ->getZExtValue();

799 };

801 "llvm.debugify should have exactly 2 operands!");

802 unsigned OriginalNumLines = getDebugifyOperand(0);

803 unsigned OriginalNumVars = getDebugifyOperand(1);

804 bool HasErrors = false;

805

806

808 if (StatsMap && !NameOfWrappedPass.empty())

809 Stats = &StatsMap->operator[](NameOfWrappedPass);

810

811 BitVector MissingLines{OriginalNumLines, true};

812 BitVector MissingVars{OriginalNumVars, true};

814 if (isFunctionSkipped(F))

815 continue;

816

817

819 auto DL = I.getDebugLoc();

820 if (DL && DL.getLine() != 0) {

821 MissingLines.reset(DL.getLine() - 1);

822 continue;

823 }

824

826 dbg() << "WARNING: Instruction with empty DebugLoc in function ";

827 dbg() << F.getName() << " --";

828 I.print(dbg());

829 dbg() << "\n";

830 }

831 }

832

833

834 auto CheckForMisSized = [&](auto *DbgVal) {

835 unsigned Var = ~0U;

836 (void)to_integer(DbgVal->getVariable()->getName(), Var, 10);

837 assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");

838 bool HasBadSize = diagnoseMisSizedDbgValue(M, DbgVal);

839 if (!HasBadSize)

840 MissingVars.reset(Var - 1);

841 HasErrors |= HasBadSize;

842 };

845 if (DVR.isDbgValue() || DVR.isDbgAssign())

846 CheckForMisSized(&DVR);

847 }

848 }

849

850

851 for (unsigned Idx : MissingLines.set_bits())

852 dbg() << "WARNING: Missing line " << Idx + 1 << "\n";

853

854 for (unsigned Idx : MissingVars.set_bits())

855 dbg() << "WARNING: Missing variable " << Idx + 1 << "\n";

856

857

859 Stats->NumDbgLocsExpected += OriginalNumLines;

860 Stats->NumDbgLocsMissing += MissingLines.count();

861 Stats->NumDbgValuesExpected += OriginalNumVars;

862 Stats->NumDbgValuesMissing += MissingVars.count();

863 }

864

865 dbg() << Banner;

866 if (!NameOfWrappedPass.empty())

867 dbg() << " [" << NameOfWrappedPass << "]";

868 dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n';

869

870

871 bool Ret = false;

872 if (Strip)

874

875 return Ret;

876}

877

878

879

880struct DebugifyModulePass : public ModulePass {

881 bool runOnModule(Module &M) override {

883 applyDebugify(M, Mode, DebugInfoBeforePass, NameOfWrappedPass);

885 }

886

888 StringRef NameOfWrappedPass = "",

889 DebugInfoPerPass *DebugInfoBeforePass = nullptr)

890 : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),

891 DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}

892

893 void getAnalysisUsage(AnalysisUsage &AU) const override {

895 }

896

897 static char ID;

898

899private:

900 StringRef NameOfWrappedPass;

901 DebugInfoPerPass *DebugInfoBeforePass;

903};

904

905

906

907struct DebugifyFunctionPass : public FunctionPass {

910 applyDebugify(F, Mode, DebugInfoBeforePass, NameOfWrappedPass);

912 }

913

914 DebugifyFunctionPass(

916 StringRef NameOfWrappedPass = "",

917 DebugInfoPerPass *DebugInfoBeforePass = nullptr)

918 : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),

919 DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}

920

921 void getAnalysisUsage(AnalysisUsage &AU) const override {

923 }

924

925 static char ID;

926

927private:

928 StringRef NameOfWrappedPass;

929 DebugInfoPerPass *DebugInfoBeforePass;

931};

932

933

934

935struct CheckDebugifyModulePass : public ModulePass {

936 bool runOnModule(Module &M) override {

939 Result = checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,

940 "CheckModuleDebugify", Strip, StatsMap);

941 else

943 M, M.functions(), *DebugInfoBeforePass,

944 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,

945 OrigDIVerifyBugsReportFilePath);

946

948 }

949

950 CheckDebugifyModulePass(

951 bool Strip = false, StringRef NameOfWrappedPass = "",

954 DebugInfoPerPass *DebugInfoBeforePass = nullptr,

955 StringRef OrigDIVerifyBugsReportFilePath = "")

956 : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),

957 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),

958 StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),

959 Strip(Strip) {}

960

961 void getAnalysisUsage(AnalysisUsage &AU) const override {

963 }

964

965 static char ID;

966

967private:

968 StringRef NameOfWrappedPass;

969 StringRef OrigDIVerifyBugsReportFilePath;

971 DebugInfoPerPass *DebugInfoBeforePass;

973 bool Strip;

974};

975

976

977

978struct CheckDebugifyFunctionPass : public FunctionPass {

981 auto FuncIt = F.getIterator();

984 Result = checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),

985 NameOfWrappedPass, "CheckFunctionDebugify",

986 Strip, StatsMap);

987 else

989 M, make_range(FuncIt, std::next(FuncIt)), *DebugInfoBeforePass,

990 "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass,

991 OrigDIVerifyBugsReportFilePath);

992

994 }

995

996 CheckDebugifyFunctionPass(

997 bool Strip = false, StringRef NameOfWrappedPass = "",

1000 DebugInfoPerPass *DebugInfoBeforePass = nullptr,

1001 StringRef OrigDIVerifyBugsReportFilePath = "")

1002 : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),

1003 OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),

1004 StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),

1005 Strip(Strip) {}

1006

1007 void getAnalysisUsage(AnalysisUsage &AU) const override {

1009 }

1010

1011 static char ID;

1012

1013private:

1014 StringRef NameOfWrappedPass;

1015 StringRef OrigDIVerifyBugsReportFilePath;

1017 DebugInfoPerPass *DebugInfoBeforePass;

1019 bool Strip;

1020};

1021

1022}

1023

1025 std::error_code EC;

1027 if (EC) {

1028 errs() << "Could not open file: " << EC.message() << ", " << Path << '\n';

1029 return;

1030 }

1031

1032 OS << "Pass Name" << ',' << "# of missing debug values" << ','

1033 << "# of missing locations" << ',' << "Missing/Expected value ratio" << ','

1034 << "Missing/Expected location ratio" << '\n';

1035 for (const auto &Entry : Map) {

1038

1039 OS << Pass << ',' << Stats.NumDbgValuesMissing << ','

1040 << Stats.NumDbgLocsMissing << ',' << Stats.getMissingValueRatio() << ','

1041 << Stats.getEmptyLocationRatio() << '\n';

1042 }

1043}

1044

1049 return new DebugifyModulePass();

1051 return new DebugifyModulePass(Mode, NameOfWrappedPass, DebugInfoBeforePass);

1052}

1053

1059 return new DebugifyFunctionPass();

1061 return new DebugifyFunctionPass(Mode, NameOfWrappedPass, DebugInfoBeforePass);

1062}

1063

1067 "ModuleDebugify: ", nullptr);

1068 else

1070 "ModuleDebugify (original debuginfo)",

1071 NameOfWrappedPass);

1072

1075 return PA;

1076}

1077

1081 StringRef OrigDIVerifyBugsReportFilePath) {

1083 return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);

1085 return new CheckDebugifyModulePass(false, NameOfWrappedPass, nullptr, Mode,

1086 DebugInfoBeforePass,

1087 OrigDIVerifyBugsReportFilePath);

1088}

1089

1093 StringRef OrigDIVerifyBugsReportFilePath) {

1095 return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);

1097 return new CheckDebugifyFunctionPass(false, NameOfWrappedPass, nullptr, Mode,

1098 DebugInfoBeforePass,

1099 OrigDIVerifyBugsReportFilePath);

1100}

1101

1105 checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,

1106 "CheckModuleDebugify", Strip, StatsMap);

1107 else

1109 M, M.functions(), *DebugInfoBeforePass,

1110 "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,

1111 OrigDIVerifyBugsReportFilePath);

1112

1114}

1115

1117 return isSpecialPass(PassID, {"PassManager", "PassAdaptor",

1118 "AnalysisManagerProxy", "PrintFunctionPass",

1119 "PrintModulePass", "BitcodeWriterPass",

1120 "ThinLTOBitcodeWriterPass", "VerifierPass"});

1121}

1122

1127 return;

1134 .getManager()

1135 .invalidate(F, PA);

1139 MAM.invalidate(M, PA);

1140 }

1141 });

1142 PIC.registerAfterPassCallback(

1145 return;

1149 auto &F = *const_cast<Function *>(*CF);

1150 Module &M = *F.getParent();

1151 auto It = F.getIterator();

1153 checkDebugifyMetadata(M, make_range(It, std::next(It)), P,

1154 "CheckFunctionDebugify", true,

1155 DIStatsMap);

1156 else

1158 *DebugInfoBeforePass,

1159 "CheckModuleDebugify (original debuginfo)",

1160 P, OrigDIVerifyBugsReportFilePath);

1162 .getManager()

1163 .invalidate(F, PA);

1167 checkDebugifyMetadata(M, M.functions(), P, "CheckModuleDebugify",

1168 true, DIStatsMap);

1169 else

1171 "CheckModuleDebugify (original debuginfo)",

1172 P, OrigDIVerifyBugsReportFilePath);

1173 MAM.invalidate(M, PA);

1174 }

1175 });

1176}

1177

1178char DebugifyModulePass::ID = 0;

1180 "Attach debug info to everything");

1181

1182char CheckDebugifyModulePass::ID = 0;

1184 CDM("check-debugify", "Check debug info from -debugify");

1185

1186char DebugifyFunctionPass::ID = 0;

1188 "Attach debug info to a function");

1189

1190char CheckDebugifyFunctionPass::ID = 0;

1192 CDF("check-debugify-function", "Check debug info from -debugify-function");

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

Expand Atomic instructions

This file implements the BitVector class.

#define clEnumValN(ENUMVAL, FLAGNAME, DESC)

static RegisterPass< CheckDebugifyModulePass > CDM("check-debugify", "Check debug info from -debugify")

ModulePass * createDebugifyModulePass(enum DebugifyMode Mode, llvm::StringRef NameOfWrappedPass, DebugInfoPerPass *DebugInfoBeforePass)

Definition Debugify.cpp:1045

bool hasLoc(const Instruction &I)

Definition Debugify.cpp:356

FunctionPass * createDebugifyFunctionPass(enum DebugifyMode Mode, llvm::StringRef NameOfWrappedPass, DebugInfoPerPass *DebugInfoBeforePass)

Definition Debugify.cpp:1055

static bool isIgnoredPass(StringRef PassID)

Definition Debugify.cpp:1116

static bool applyDebugify(Function &F, enum DebugifyMode Mode, DebugInfoPerPass *DebugInfoBeforePass, StringRef NameOfWrappedPass="")

Definition Debugify.cpp:280

ModulePass * createCheckDebugifyModulePass(bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap, enum DebugifyMode Mode, DebugInfoPerPass *DebugInfoBeforePass, StringRef OrigDIVerifyBugsReportFilePath)

Definition Debugify.cpp:1078

static void writeJSON(StringRef OrigDIVerifyBugsReportFilePath, StringRef FileNameFromCU, StringRef NameOfWrappedPass, llvm::json::Array &Bugs)

Definition Debugify.cpp:584

static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")

static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")

static bool checkFunctions(const DebugFnMap &DIFunctionsBefore, const DebugFnMap &DIFunctionsAfter, StringRef NameOfWrappedPass, StringRef FileNameFromCU, bool ShouldWriteIntoJSON, llvm::json::Array &Bugs)

Definition Debugify.cpp:443

static RegisterPass< CheckDebugifyFunctionPass > CDF("check-debugify-function", "Check debug info from -debugify-function")

FunctionPass * createCheckDebugifyFunctionPass(bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap, enum DebugifyMode Mode, DebugInfoPerPass *DebugInfoBeforePass, StringRef OrigDIVerifyBugsReportFilePath)

Definition Debugify.cpp:1090

static bool checkVars(const DebugVarMap &DIVarsBefore, const DebugVarMap &DIVarsAfter, StringRef NameOfWrappedPass, StringRef FileNameFromCU, bool ShouldWriteIntoJSON, llvm::json::Array &Bugs)

Definition Debugify.cpp:551

static bool checkInstructions(const DebugInstMap &DILocsBefore, const DebugInstMap &DILocsAfter, const WeakInstValueMap &InstToDelete, StringRef NameOfWrappedPass, StringRef FileNameFromCU, bool ShouldWriteIntoJSON, llvm::json::Array &Bugs)

Definition Debugify.cpp:485

DebugifyMode

Used to check whether we track synthetic or original debug info.

llvm::MapVector< const llvm::Function *, const llvm::DISubprogram * > DebugFnMap

llvm::MapVector< llvm::StringRef, DebugifyStatistics > DebugifyStatsMap

Map pass names to a per-pass DebugifyStatistics instance.

llvm::MapVector< const llvm::Instruction *, bool > DebugInstMap

llvm::MapVector< const llvm::Instruction *, llvm::WeakVH > WeakInstValueMap

llvm::MapVector< const llvm::DILocalVariable *, unsigned > DebugVarMap

static bool runOnFunction(Function &F, bool PostInlining)

static SmallString< 128 > getFilename(const DIScope *SP, vfs::FileSystem &VFS)

Extract a filename for a DIScope.

Module.h This file contains the declarations for the Module class.

This file supports working with JSON data.

Legalize the Machine IR a function s Machine IR

block placement Basic Block Placement Stats

Machine Check Debug Module

ModuleAnalysisManager MAM

PassInstrumentationCallbacks PIC

This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...

static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))

static const char PassName[]

LLVM_ABI llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM)

Definition Debugify.cpp:1102

LLVM_ABI llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM)

Definition Debugify.cpp:1064

void setPreservesAll()

Set by analyses that do not transform their input at all.

LLVM Basic Block Representation.

LLVM_ABI const CallInst * getTerminatingDeoptimizeCall() const

Returns the call instruction calling @llvm.experimental.deoptimize prior to the terminating return in...

InstListType::iterator iterator

Instruction iterators...

LLVM_ABI const CallInst * getTerminatingMustTailCall() const

Returns the call instruction marked 'musttail' prior to the terminating return instruction of this ba...

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

size_type count() const

count - Returns the number of bits which are set.

iterator_range< const_set_bits_iterator > set_bits() const

Represents analyses that only rely on functions' control flow.

LLVM_ABI void finalize()

Construct any deferred debug info descriptors.

LLVM_ABI DISubroutineType * createSubroutineType(DITypeRefArray ParameterTypes, DINode::DIFlags Flags=DINode::FlagZero, unsigned CC=0)

Create subroutine type.

LLVM_ABI DISubprogram * createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags=DINode::FlagZero, DISubprogram::DISPFlags SPFlags=DISubprogram::SPFlagZero, DITemplateParameterArray TParams=nullptr, DISubprogram *Decl=nullptr, DITypeArray ThrownTypes=nullptr, DINodeArray Annotations=nullptr, StringRef TargetFuncName="", bool UseKeyInstructions=false)

Create a new descriptor for the specified subprogram.

LLVM_ABI DbgInstPtr insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, InsertPosition InsertPt)

Insert a new llvm.dbg.value intrinsic call.

LLVM_ABI DIBasicType * createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, DINode::DIFlags Flags=DINode::FlagZero, uint32_t NumExtraInhabitants=0, uint32_t DataSizeInBits=0)

Create debugging information entry for a basic type.

LLVM_ABI DITypeRefArray getOrCreateTypeArray(ArrayRef< Metadata * > Elements)

Get a DITypeRefArray, create one if required.

LLVM_ABI DICompileUnit * createCompileUnit(DISourceLanguageName Lang, DIFile *File, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName=StringRef(), DICompileUnit::DebugEmissionKind Kind=DICompileUnit::DebugEmissionKind::FullDebug, uint64_t DWOId=0, bool SplitDebugInlining=true, bool DebugInfoForProfiling=false, DICompileUnit::DebugNameTableKind NameTableKind=DICompileUnit::DebugNameTableKind::Default, bool RangesBaseAddress=false, StringRef SysRoot={}, StringRef SDK={})

A CompileUnit provides an anchor for all debugging information generated during this instance of comp...

LLVM_ABI DIExpression * createExpression(ArrayRef< uint64_t > Addr={})

Create a new descriptor for the specified variable which has a complex address expression for its add...

LLVM_ABI DILocalVariable * createAutoVariable(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, DIType *Ty, bool AlwaysPreserve=false, DINode::DIFlags Flags=DINode::FlagZero, uint32_t AlignInBits=0)

Create a new descriptor for an auto variable.

LLVM_ABI DIFile * createFile(StringRef Filename, StringRef Directory, std::optional< DIFile::ChecksumInfo< StringRef > > Checksum=std::nullopt, std::optional< StringRef > Source=std::nullopt)

Create a file descriptor to hold debugging information for a file.

Tagged DWARF-like metadata node.

Wrapper structure that holds a language name and its version.

DISPFlags

Debug info subprogram flags.

Record of a variable value-assignment, aka a non instruction representation of the dbg....

LLVM_ABI DILocation * get() const

Get the underlying DILocation.

static DebugLoc getUnknown()

LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)

Definition Debugify.cpp:1123

FunctionPass class - This class is used to implement most global optimizations.

const Function & getFunction() const

void eraseFromParent()

eraseFromParent - This method unlinks 'this' from the containing module and deletes it.

LLVM_ABI bool isDeclaration() const

Return true if the primary definition of this global value is outside of the current translation unit...

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

const char * getOpcodeName() const

This is an important class for using LLVM in a threaded context.

const MDOperand & getOperand(unsigned I) const

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

size_type count(const KeyT &Key) const

iterator find(const KeyT &Key)

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...

A Module instance is used to store all the information related to an LLVM module.

@ Warning

Emits a warning if two values disagree.

LLVM_ABI void eraseFromParent()

Drop all references and remove the node from parent module.

LLVM_ABI MDNode * getOperand(unsigned i) const

LLVM_ABI unsigned getNumOperands() const

LLVM_ABI void clearOperands()

Drop all references to this node's operands.

iterator_range< op_iterator > operands()

LLVM_ABI void addOperand(MDNode *M)

This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...

Pass interface - Implemented by all 'passes'.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

PreservedAnalyses & preserveSet()

Mark an analysis set as preserved.

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

constexpr bool empty() const

empty - Check if the string is empty.

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

bool isVoidTy() const

Return true if this is 'void'.

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

A range adaptor for a pair of iterators.

An Array is a JSON array, which contains heterogeneous JSON values.

void push_back(const Value &E)

An Object is a JSON object, which maps strings to heterogenous JSON values.

A Value is an JSON value of unknown type.

A raw_ostream that writes to a file descriptor.

void close()

Manually flush the stream and close the file.

Expected< sys::fs::FileLocker > lock()

Locks the underlying file.

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an std::string.

ValuesClass values(OptsTy... Options)

Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...

initializer< Ty > init(const Ty &Val)

std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)

Extract a Value from Metadata.

@ OF_TextWithCRLF

The file should be opened in text mode and use a carriage linefeed '\r '.

@ OF_Append

The file should be opened in append mode.

This is an optimization pass for GlobalISel generic memory operations.

T any_cast(const Any &Value)

FormattedString right_justify(StringRef Str, unsigned Width)

right_justify - add spaces before string so total output is Width characters.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy

Provide the FunctionAnalysisManager to Module proxy.

std::string utostr(uint64_t X, bool isNeg=false)

LLVM_ABI bool stripDebugifyMetadata(Module &M)

Strip out all of the metadata and debug info inserted by debugify.

Definition Debugify.cpp:306

LLVM_ABI void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map)

Definition Debugify.cpp:1024

LLVM_ABI bool applyDebugifyMetadata(Module &M, iterator_range< Module::iterator > Functions, StringRef Banner, std::function< bool(DIBuilder &, Function &)> ApplyToMF)

Add synthesized debug information to a module.

LLVM_ABI bool collectDebugInfoMetadata(Module &M, iterator_range< Module::iterator > Functions, DebugInfoPerPass &DebugInfoBeforePass, StringRef Banner, StringRef NameOfWrappedPass)

Collect original debug information before a pass.

Definition Debugify.cpp:366

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

LLVM_ABI bool checkDebugInfoMetadata(Module &M, iterator_range< Module::iterator > Functions, DebugInfoPerPass &DebugInfoBeforePass, StringRef Banner, StringRef NameOfWrappedPass, StringRef OrigDIVerifyBugsReportFilePath)

Check original debug information after a pass.

Definition Debugify.cpp:611

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

LLVM_ABI bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)

LLVM_ABI raw_ostream & nulls()

This returns a reference to a raw_ostream which simply discards output.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

LLVM_ABI bool StripDebugInfo(Module &M)

Strip debug info in the module if it exists.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

bool to_integer(StringRef S, N &Num, unsigned Base=0)

Convert the string S to an integer of the specified type using the radix Base. If Base is 0,...

static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)

Filter the DbgRecord range to DbgVariableRecord types only and downcast.

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

Used to track the Debug Info Metadata information.

WeakInstValueMap InstToDelete

Track how much debugify information (in the synthetic mode only) has been lost.

RegisterPass template - This template class is used to notify the system that a Pass is available ...