129 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file This checks debug info after mir-debugify (+ pass-to-test). Currently10/// it simply checks the integrity of line info in DILocation and11/// 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/IR/Module.h"22#include "llvm/InitializePasses.h"23#include "llvm/Pass.h"24 25#define DEBUG_TYPE "mir-check-debugify"26 27using namespace llvm;28 29namespace {30 31struct CheckDebugMachineModule : public ModulePass {32 bool runOnModule(Module &M) override {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 MachineModuleInfo &MMI =41 getAnalysis<MachineModuleInfoWrapperPass>().getMMI();42 43 auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {44 return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))45 ->getZExtValue();46 };47 assert(NMD->getNumOperands() == 2 &&48 "llvm.mir.debugify should have exactly 2 operands!");49 unsigned NumLines = getDebugifyOperand(0);50 unsigned NumVars = getDebugifyOperand(1);51 BitVector MissingLines{NumLines, true};52 BitVector MissingVars{NumVars, true};53 54 for (Function &F : M.functions()) {55 MachineFunction *MF = MMI.getMachineFunction(F);56 if (!MF)57 continue;58 for (MachineBasicBlock &MBB : *MF) {59 // Find missing lines.60 // TODO: Avoid meta instructions other than dbg_val.61 for (MachineInstr &MI : MBB) {62 if (MI.isDebugValue())63 continue;64 const DebugLoc DL = MI.getDebugLoc();65 if (DL && DL.getLine() != 0) {66 MissingLines.reset(DL.getLine() - 1);67 continue;68 }69 70 if (!DL) {71 errs() << "WARNING: Instruction with empty DebugLoc in function ";72 errs() << F.getName() << " --";73 MI.print(errs());74 }75 }76 77 // Find missing variables.78 // TODO: Handle DBG_INSTR_REF which is under an experimental option now.79 for (MachineInstr &MI : MBB) {80 if (!MI.isDebugValue())81 continue;82 const DILocalVariable *LocalVar = MI.getDebugVariable();83 unsigned Var = ~0U;84 85 (void)to_integer(LocalVar->getName(), Var, 10);86 assert(Var <= NumVars && "Unexpected name for DILocalVariable");87 MissingVars.reset(Var - 1);88 }89 }90 }91 92 bool Fail = false;93 for (unsigned Idx : MissingLines.set_bits()) {94 errs() << "WARNING: Missing line " << Idx + 1 << "\n";95 Fail = true;96 }97 98 for (unsigned Idx : MissingVars.set_bits()) {99 errs() << "WARNING: Missing variable " << Idx + 1 << "\n";100 Fail = true;101 }102 errs() << "Machine IR debug info check: ";103 errs() << (Fail ? "FAIL" : "PASS") << "\n";104 105 return false;106 }107 108 CheckDebugMachineModule() : ModulePass(ID) {}109 110 void getAnalysisUsage(AnalysisUsage &AU) const override {111 AU.addRequired<MachineModuleInfoWrapperPass>();112 AU.setPreservesAll();113 }114 115 static char ID; // Pass identification.116};117char CheckDebugMachineModule::ID = 0;118 119} // end anonymous namespace120 121INITIALIZE_PASS_BEGIN(CheckDebugMachineModule, DEBUG_TYPE,122 "Machine Check Debug Module", false, false)123INITIALIZE_PASS_END(CheckDebugMachineModule, DEBUG_TYPE,124 "Machine Check Debug Module", false, false)125 126ModulePass *llvm::createCheckDebugMachineModulePass() {127 return new CheckDebugMachineModule();128}129