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