//===--- SIDebuggerInsertNops.cpp - Inserts nops for debugger usage -------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // /// \file /// \brief Inserts one nop instruction for each high level source statement for /// debugger usage. /// /// Tools, such as a debugger, need to pause execution based on user input (i.e. /// breakpoint). In order to do this, one nop instruction is inserted before the /// first isa instruction of each high level source statement. Further, the /// debugger may replace nop instructions with trap instructions based on user /// input. // //===----------------------------------------------------------------------===// #include "SIInstrInfo.h" #include "AMDGPUSubtarget.h" #include "llvm/ADT/DenseSet.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" using namespace llvm; #define DEBUG_TYPE "si-debugger-insert-nops" #define PASS_NAME "SI Debugger Insert Nops" namespace { class SIDebuggerInsertNops : public MachineFunctionPass { public: static char ID; SIDebuggerInsertNops() : MachineFunctionPass(ID) { } StringRef getPassName() const override { return PASS_NAME; } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); MachineFunctionPass::getAnalysisUsage(AU); } bool runOnMachineFunction(MachineFunction &MF) override; }; } // anonymous namespace INITIALIZE_PASS(SIDebuggerInsertNops, DEBUG_TYPE, PASS_NAME, false, false) char SIDebuggerInsertNops::ID = 0; char &llvm::SIDebuggerInsertNopsID = SIDebuggerInsertNops::ID; FunctionPass *llvm::createSIDebuggerInsertNopsPass() { return new SIDebuggerInsertNops(); } bool SIDebuggerInsertNops::runOnMachineFunction(MachineFunction &MF) { // Skip this pass if "amdgpu-debugger-insert-nops" attribute was not // specified. const SISubtarget &ST = MF.getSubtarget(); if (!ST.debuggerInsertNops()) return false; // Skip machine functions without debug info. if (!MF.getMMI().hasDebugInfo()) return false; // Target instruction info. const SIInstrInfo *TII = ST.getInstrInfo(); // Set containing line numbers that have nop inserted. DenseSet NopInserted; for (auto &MBB : MF) { for (auto MI = MBB.begin(); MI != MBB.end(); ++MI) { // Skip DBG_VALUE instructions and instructions without location. if (MI->isDebugValue() || !MI->getDebugLoc()) continue; // Insert nop instruction if line number does not have nop inserted. auto DL = MI->getDebugLoc(); if (NopInserted.find(DL.getLine()) == NopInserted.end()) { BuildMI(MBB, *MI, DL, TII->get(AMDGPU::S_NOP)) .addImm(0); NopInserted.insert(DL.getLine()); } } } return true; }