Coverage Report

Created: 2024-01-17 10:31

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