From d3af441dfeb69d4c2a91b427e3d7a57e04c59201 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Mon, 14 Sep 2020 09:55:38 +0100 Subject: [PATCH] [DebugInstrRef][1/9] Add fields for instr-ref variable locations Add a DBG_INSTR_REF instruction and a "debug instruction number" field to MachineInstr. The two allow variable values to be specified by identifying where the value is computed, rather than the register it lies in, like so: %0 = fooinst, debug-instr-number 1 [...] DBG_INSTR_REF 1, 0 See the original RFC for motivation: http://lists.llvm.org/pipermail/llvm-dev/2020-February/139440.html This patch is NFCI; it only adds fields and other boiler plate. Differential Revision: https://reviews.llvm.org/D85741 --- llvm/include/llvm/CodeGen/MachineFunction.h | 9 ++++++++ llvm/include/llvm/CodeGen/MachineInstr.h | 18 +++++++++++++++- llvm/include/llvm/Support/TargetOpcodes.def | 4 ++++ llvm/include/llvm/Target/Target.td | 6 ++++++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 5 +++++ llvm/lib/CodeGen/MachineInstr.cpp | 32 +++++++++++++++++++++-------- 6 files changed, 64 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index 0ea2da9..247716d 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -431,6 +431,11 @@ public: using VariableDbgInfoMapTy = SmallVector; VariableDbgInfoMapTy VariableDbgInfos; + /// A count of how many instructions in the function have had numbers + /// assigned to them. Used for debug value tracking, to determine the + /// next instruction number. + unsigned DebugInstrNumberingCount = 0; + MachineFunction(Function &F, const LLVMTargetMachine &Target, const TargetSubtargetInfo &STI, unsigned FunctionNum, MachineModuleInfo &MMI); @@ -1076,6 +1081,10 @@ public: /// the same callee. void moveCallSiteInfo(const MachineInstr *Old, const MachineInstr *New); + + unsigned getNewDebugInstrNum() { + return ++DebugInstrNumberingCount; + } }; //===--------------------------------------------------------------------===// diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h index 2c912b1..957ec21 100644 --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -249,6 +249,10 @@ private: DebugLoc debugLoc; // Source line information. + /// Unique instruction number. Used by DBG_INSTR_REFs to refer to the values + /// defined by this instruction. + unsigned DebugInstrNum; + // Intrusive list support friend struct ilist_traits; friend struct ilist_callback_traits; @@ -444,6 +448,14 @@ public: /// this DBG_LABEL instruction. const DILabel *getDebugLabel() const; + /// Fetch the instruction number of this MachineInstr. If it does not have + /// one already, a new and unique number will be assigned. + unsigned getDebugInstrNum(); + + /// Examine the instruction number of this MachineInstr. May be zero if + /// it hasn't been assigned a number yet. + unsigned peekDebugInstrNum() const { return DebugInstrNum; } + /// Emit an error referring to the source location of this instruction. /// This should only be used for inline assembly that is somehow /// impossible to compile. Other errors should have been handled much @@ -1145,7 +1157,10 @@ public: bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } bool isDebugLabel() const { return getOpcode() == TargetOpcode::DBG_LABEL; } - bool isDebugInstr() const { return isDebugValue() || isDebugLabel(); } + bool isDebugRef() const { return getOpcode() == TargetOpcode::DBG_INSTR_REF; } + bool isDebugInstr() const { + return isDebugValue() || isDebugLabel() || isDebugRef(); + } bool isDebugOffsetImm() const { return getDebugOffset().isImm(); } @@ -1238,6 +1253,7 @@ public: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: case TargetOpcode::DBG_VALUE: + case TargetOpcode::DBG_INSTR_REF: case TargetOpcode::DBG_LABEL: case TargetOpcode::LIFETIME_START: case TargetOpcode::LIFETIME_END: diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index db36fc4..2e464b3 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -77,6 +77,10 @@ HANDLE_TARGET_OPCODE(SUBREG_TO_REG) /// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic HANDLE_TARGET_OPCODE(DBG_VALUE) +/// DBG_INSTR_REF - A mapping of llvm.dbg.value referring to the instruction +/// that defines the value, rather than a virtual register. +HANDLE_TARGET_OPCODE(DBG_INSTR_REF) + /// DBG_LABEL - a mapping of the llvm.dbg.label intrinsic HANDLE_TARGET_OPCODE(DBG_LABEL) diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index e569275..8fba826 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -1100,6 +1100,12 @@ def DBG_VALUE : StandardPseudoInstruction { let AsmString = "DBG_VALUE"; let hasSideEffects = 0; } +def DBG_INSTR_REF : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = "DBG_INSTR_REF"; + let hasSideEffects = 0; +} def DBG_LABEL : StandardPseudoInstruction { let OutOperandList = (outs); let InOperandList = (ins unknown:$label); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index cdacedc..7a14181 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1142,6 +1142,11 @@ void AsmPrinter::emitFunctionBody() { emitInstruction(&MI); } break; + case TargetOpcode::DBG_INSTR_REF: + // This instruction reference will have been resolved to a machine + // location, and a nearby DBG_VALUE created. We can safely ignore + // the instruction reference. + break; case TargetOpcode::DBG_LABEL: if (isVerbose()) { if (!emitDebugLabelComment(&MI, *this)) diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index 457db8d..ebae5eb 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -116,7 +116,7 @@ void MachineInstr::addImplicitDefUseOperands(MachineFunction &MF) { /// the MCInstrDesc. MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid, DebugLoc dl, bool NoImp) - : MCID(&tid), debugLoc(std::move(dl)) { + : MCID(&tid), debugLoc(std::move(dl)), DebugInstrNum(0) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); // Reserve space for the expected number of operands. @@ -130,10 +130,12 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid, addImplicitDefUseOperands(MF); } -/// MachineInstr ctor - Copies MachineInstr arg exactly -/// +/// MachineInstr ctor - Copies MachineInstr arg exactly. +/// Does not copy the number from debug instruction numbering, to preserve +/// uniqueness. MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) - : MCID(&MI.getDesc()), Info(MI.Info), debugLoc(MI.getDebugLoc()) { + : MCID(&MI.getDesc()), Info(MI.Info), debugLoc(MI.getDebugLoc()), + DebugInstrNum(0) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); CapOperands = OperandCapacity::get(MI.getNumOperands()); @@ -839,27 +841,27 @@ const DILabel *MachineInstr::getDebugLabel() const { } const MachineOperand &MachineInstr::getDebugVariableOp() const { - assert(isDebugValue() && "not a DBG_VALUE"); + assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE"); return getOperand(2); } MachineOperand &MachineInstr::getDebugVariableOp() { - assert(isDebugValue() && "not a DBG_VALUE"); + assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE"); return getOperand(2); } const DILocalVariable *MachineInstr::getDebugVariable() const { - assert(isDebugValue() && "not a DBG_VALUE"); + assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE"); return cast(getOperand(2).getMetadata()); } MachineOperand &MachineInstr::getDebugExpressionOp() { - assert(isDebugValue() && "not a DBG_VALUE"); + assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE"); return getOperand(3); } const DIExpression *MachineInstr::getDebugExpression() const { - assert(isDebugValue() && "not a DBG_VALUE"); + assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE"); return cast(getOperand(3).getMetadata()); } @@ -1757,6 +1759,12 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, HeapAllocMarker->printAsOperand(OS, MST); } + if (DebugInstrNum) { + if (!FirstOp) + OS << ","; + OS << " debug-instr-number " << DebugInstrNum; + } + if (!SkipDebugLoc) { if (const DebugLoc &DL = getDebugLoc()) { if (!FirstOp) @@ -2231,3 +2239,9 @@ MachineInstr::getFoldedRestoreSize(const TargetInstrInfo *TII) const { return getSpillSlotSize(Accesses, getMF()->getFrameInfo()); return None; } + +unsigned MachineInstr::getDebugInstrNum() { + if (DebugInstrNum == 0) + DebugInstrNum = getParent()->getParent()->getNewDebugInstrNum(); + return DebugInstrNum; +} -- 2.7.4