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