xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/MachineCheckDebugify.cpp (revision a7beca6fb113986839de73b7cf73d933464898c6)
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