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