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