1 //===- MachineCheckDebugify.cpp - Check debug info ------------------------===// 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 This checks debug info after mir-debugify (+ pass-to-test). Currently 10 /// it simply checks the integrity of line info in DILocation and 11 /// DILocalVariable which mir-debugifiy generated before. 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ADT/StringExtras.h" 15 #include "llvm/CodeGen/MachineBasicBlock.h" 16 #include "llvm/CodeGen/MachineFunction.h" 17 #include "llvm/CodeGen/MachineModuleInfo.h" 18 #include "llvm/CodeGen/Passes.h" 19 #include "llvm/IR/Constants.h" 20 #include "llvm/IR/DebugInfoMetadata.h" 21 #include "llvm/InitializePasses.h" 22 #include "llvm/Pass.h" 23 24 #define DEBUG_TYPE "mir-check-debugify" 25 26 using namespace llvm; 27 28 namespace { 29 30 struct CheckDebugMachineModule : public ModulePass { 31 bool runOnModule(Module &M) override { 32 NamedMDNode *NMD = M.getNamedMetadata("llvm.mir.debugify"); 33 if (!NMD) { 34 errs() << "WARNING: Please run mir-debugify to generate " 35 "llvm.mir.debugify metadata first.\n"; 36 return false; 37 } 38 39 MachineModuleInfo &MMI = 40 getAnalysis<MachineModuleInfoWrapperPass>().getMMI(); 41 42 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned { 43 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0)) 44 ->getZExtValue(); 45 }; 46 assert(NMD->getNumOperands() == 2 && 47 "llvm.mir.debugify should have exactly 2 operands!"); 48 unsigned NumLines = getDebugifyOperand(0); 49 unsigned NumVars = getDebugifyOperand(1); 50 BitVector MissingLines{NumLines, true}; 51 BitVector MissingVars{NumVars, true}; 52 53 for (Function &F : M.functions()) { 54 MachineFunction *MF = MMI.getMachineFunction(F); 55 if (!MF) 56 continue; 57 for (MachineBasicBlock &MBB : *MF) { 58 // Find missing lines. 59 // TODO: Avoid meta instructions other than dbg_val. 60 for (MachineInstr &MI : MBB) { 61 if (MI.isDebugValue()) 62 continue; 63 const DebugLoc DL = MI.getDebugLoc(); 64 if (DL && DL.getLine() != 0) { 65 MissingLines.reset(DL.getLine() - 1); 66 continue; 67 } 68 69 if (!DL) { 70 errs() << "WARNING: Instruction with empty DebugLoc in function "; 71 errs() << F.getName() << " --"; 72 MI.print(errs()); 73 } 74 } 75 76 // Find missing variables. 77 // TODO: Handle DBG_INSTR_REF which is under an experimental option now. 78 for (MachineInstr &MI : MBB) { 79 if (!MI.isDebugValue()) 80 continue; 81 const DILocalVariable *LocalVar = MI.getDebugVariable(); 82 unsigned Var = ~0U; 83 84 (void)to_integer(LocalVar->getName(), Var, 10); 85 assert(Var <= NumVars && "Unexpected name for DILocalVariable"); 86 MissingVars.reset(Var - 1); 87 } 88 } 89 } 90 91 bool Fail = false; 92 for (unsigned Idx : MissingLines.set_bits()) { 93 errs() << "WARNING: Missing line " << Idx + 1 << "\n"; 94 Fail = true; 95 } 96 97 for (unsigned Idx : MissingVars.set_bits()) { 98 errs() << "WARNING: Missing variable " << Idx + 1 << "\n"; 99 Fail = true; 100 } 101 errs() << "Machine IR debug info check: "; 102 errs() << (Fail ? "FAIL" : "PASS") << "\n"; 103 104 return false; 105 } 106 107 CheckDebugMachineModule() : ModulePass(ID) {} 108 109 void getAnalysisUsage(AnalysisUsage &AU) const override { 110 AU.addRequired<MachineModuleInfoWrapperPass>(); 111 AU.setPreservesAll(); 112 } 113 114 static char ID; // Pass identification. 115 }; 116 char CheckDebugMachineModule::ID = 0; 117 118 } // end anonymous namespace 119 120 INITIALIZE_PASS_BEGIN(CheckDebugMachineModule, DEBUG_TYPE, 121 "Machine Check Debug Module", false, false) 122 INITIALIZE_PASS_END(CheckDebugMachineModule, DEBUG_TYPE, 123 "Machine Check Debug Module", false, false) 124 125 ModulePass *llvm::createCheckDebugMachineModulePass() { 126 return new CheckDebugMachineModule(); 127 } 128