Home | History | Annotate | Line # | Download | only in CodeGen
      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/MachineFunctionPass.h"
     15 #include "llvm/CodeGen/MachineModuleInfo.h"
     16 #include "llvm/CodeGen/Passes.h"
     17 #include "llvm/IR/DebugInfo.h"
     18 #include "llvm/InitializePasses.h"
     19 #include "llvm/Support/CommandLine.h"
     20 #include "llvm/Transforms/Utils/Debugify.h"
     21 
     22 #define DEBUG_TYPE "mir-check-debugify"
     23 
     24 using namespace llvm;
     25 
     26 namespace {
     27 
     28 struct CheckDebugMachineModule : public ModulePass {
     29   bool runOnModule(Module &M) override {
     30     MachineModuleInfo &MMI =
     31         getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
     32 
     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     auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
     41       return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
     42           ->getZExtValue();
     43     };
     44     assert(NMD->getNumOperands() == 2 &&
     45            "llvm.mir.debugify should have exactly 2 operands!");
     46     unsigned NumLines = getDebugifyOperand(0);
     47     unsigned NumVars = getDebugifyOperand(1);
     48     BitVector MissingLines{NumLines, true};
     49     BitVector MissingVars{NumVars, true};
     50 
     51     for (Function &F : M.functions()) {
     52       MachineFunction *MF = MMI.getMachineFunction(F);
     53       if (!MF)
     54         continue;
     55       for (MachineBasicBlock &MBB : *MF) {
     56         // Find missing lines.
     57         // TODO: Avoid meta instructions other than dbg_val.
     58         for (MachineInstr &MI : MBB) {
     59           if (MI.isDebugValue())
     60             continue;
     61           const DebugLoc DL = MI.getDebugLoc();
     62           if (DL && DL.getLine() != 0) {
     63             MissingLines.reset(DL.getLine() - 1);
     64             continue;
     65           }
     66 
     67           if (!DL) {
     68             errs() << "WARNING: Instruction with empty DebugLoc in function ";
     69             errs() << F.getName() << " --";
     70             MI.print(errs());
     71           }
     72         }
     73 
     74         // Find missing variables.
     75         // TODO: Handle DBG_INSTR_REF which is under an experimental option now.
     76         for (MachineInstr &MI : MBB) {
     77           if (!MI.isDebugValue())
     78             continue;
     79           const DILocalVariable *LocalVar = MI.getDebugVariable();
     80           unsigned Var = ~0U;
     81 
     82           (void)to_integer(LocalVar->getName(), Var, 10);
     83           assert(Var <= NumVars && "Unexpected name for DILocalVariable");
     84           MissingVars.reset(Var - 1);
     85         }
     86       }
     87     }
     88 
     89     bool Fail = false;
     90     for (unsigned Idx : MissingLines.set_bits()) {
     91       errs() << "WARNING: Missing line " << Idx + 1 << "\n";
     92       Fail = true;
     93     }
     94 
     95     for (unsigned Idx : MissingVars.set_bits()) {
     96       errs() << "WARNING: Missing variable " << Idx + 1 << "\n";
     97       Fail = true;
     98     }
     99     errs() << "Machine IR debug info check: ";
    100     errs() << (Fail ? "FAIL" : "PASS") << "\n";
    101 
    102     return false;
    103   }
    104 
    105   CheckDebugMachineModule() : ModulePass(ID) {}
    106 
    107   void getAnalysisUsage(AnalysisUsage &AU) const override {
    108     AU.addRequired<MachineModuleInfoWrapperPass>();
    109     AU.addPreserved<MachineModuleInfoWrapperPass>();
    110     AU.setPreservesCFG();
    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