diff --git a/llvm/docs/MIRLangRef.rst b/llvm/docs/MIRLangRef.rst --- a/llvm/docs/MIRLangRef.rst +++ b/llvm/docs/MIRLangRef.rst @@ -460,7 +460,7 @@ Machine Operands ---------------- -There are seventeen different kinds of machine operands, and all of them can be +There are eighteen different kinds of machine operands, and all of them can be serialized. Immediate Operands @@ -736,6 +736,19 @@ EH_LABEL +Debug Instruction Reference Operands +^^^^^^^^^^^^^^^^^ + +A debug instruction reference operand is a pair of indices, referring to an +instruction and an operand within that instruction respectively; see +:ref:`Instruction referencing locations `. + +The example below uses a reference to Instruction 1, Operand 0: + +.. code-block:: text + + DBG_INSTR_REF !123, !DIExpression(), dbg-instr-ref(1, 0), debug-location !456 + CFIIndex Operands ^^^^^^^^^^^^^^^^^ @@ -886,6 +899,8 @@ All additional qualifiers for the variable location should be made through the expression metadata. +.. _instruction-referencing-locations: + Instruction referencing locations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -898,16 +913,16 @@ .. code-block:: text $rbp = MOV64ri 0, debug-instr-number 1, debug-location !12 - DBG_INSTR_REF 1, 0, !123, !DIExpression(), debug-location !456 + DBG_INSTR_REF !123, !DIExpression(), dbg-instr-ref(1, 0), debug-location !456 Instruction numbers are directly attached to machine instructions with an optional ``debug-instr-number`` attachment, before the optional ``debug-location`` attachment. The value defined in ``$rbp`` in the code above would be identified by the pair ``<1, 0>``. -The first two operands of the ``DBG_INSTR_REF`` above record the instruction +The 3rd operand of the ``DBG_INSTR_REF`` above records the instruction and operand number ``<1, 0>``, identifying the value defined by the ``MOV64ri``. -The additional operands to ``DBG_INSTR_REF`` are identical to ``DBG_VALUE``, +The first two operands to ``DBG_INSTR_REF`` are identical to ``DBG_VALUE_LIST``, and the ``DBG_INSTR_REF`` s position records where the variable takes on the designated value in the same way. diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -661,17 +661,17 @@ /// Returns a range over all operands that are used to determine the variable /// location for this DBG_VALUE instruction. iterator_range debug_operands() { - assert(isDebugValue() && "Must be a debug value instruction."); - return isDebugValueList() - ? make_range(operands_begin() + 2, operands_end()) - : make_range(operands_begin(), operands_begin() + 1); + assert((isDebugValueLike()) && "Must be a debug value instruction."); + return isNonListDebugValue() + ? make_range(operands_begin(), operands_begin() + 1) + : make_range(operands_begin() + 2, operands_end()); } /// \copydoc debug_operands() iterator_range debug_operands() const { - assert(isDebugValue() && "Must be a debug value instruction."); - return isDebugValueList() - ? make_range(operands_begin() + 2, operands_end()) - : make_range(operands_begin(), operands_begin() + 1); + assert((isDebugValueLike()) && "Must be a debug value instruction."); + return isNonListDebugValue() + ? make_range(operands_begin(), operands_begin() + 1) + : make_range(operands_begin() + 2, operands_end()); } /// Returns a range over all explicit operands that are register definitions. /// Implicit definition are not included! @@ -1261,8 +1261,9 @@ bool isDebugValue() const { return isNonListDebugValue() || isDebugValueList(); } - bool isDebugLabel() const { return getOpcode() == TargetOpcode::DBG_LABEL; } bool isDebugRef() const { return getOpcode() == TargetOpcode::DBG_INSTR_REF; } + bool isDebugValueLike() const { return isDebugValue() || isDebugRef(); } + bool isDebugLabel() const { return getOpcode() == TargetOpcode::DBG_LABEL; } bool isDebugPHI() const { return getOpcode() == TargetOpcode::DBG_PHI; } bool isDebugInstr() const { return isDebugValue() || isDebugLabel() || isDebugRef() || isDebugPHI(); diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h --- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -235,7 +235,7 @@ const MachineInstrBuilder &addMetadata(const MDNode *MD) const { MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); - assert((MI->isDebugValue() ? static_cast(MI->getDebugVariable()) + assert((MI->isDebugValueLike() ? static_cast(MI->getDebugVariable()) : true) && "first MDNode argument of a DBG_VALUE not a variable"); assert((MI->isDebugLabel() ? static_cast(MI->getDebugLabel()) @@ -484,13 +484,6 @@ Register Reg, const MDNode *Variable, const MDNode *Expr); -/// This version of the builder builds a DBG_VALUE intrinsic -/// for a MachineOperand. -MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - const MachineOperand &MO, const MDNode *Variable, - const MDNode *Expr); - /// This version of the builder builds a DBG_VALUE or DBG_VALUE_LIST intrinsic /// for a MachineOperand. MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, @@ -507,16 +500,8 @@ Register Reg, const MDNode *Variable, const MDNode *Expr); -/// This version of the builder builds a DBG_VALUE intrinsic -/// for a machine operand and inserts it at position I. -MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - MachineOperand &MO, const MDNode *Variable, - const MDNode *Expr); - -/// This version of the builder builds a DBG_VALUE or DBG_VALUE_LIST intrinsic -/// for a machine operand and inserts it at position I. +/// This version of the builder builds a DBG_VALUE, DBG_INSTR_REF, or +/// DBG_VALUE_LIST intrinsic for a machine operand and inserts it at position I. MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, const DebugLoc &DL, const MCInstrDesc &MCID, bool IsIndirect, diff --git a/llvm/include/llvm/CodeGen/MachineOperand.h b/llvm/include/llvm/CodeGen/MachineOperand.h --- a/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/llvm/include/llvm/CodeGen/MachineOperand.h @@ -64,6 +64,7 @@ MO_RegisterLiveOut, ///< Mask of live-out registers. MO_Metadata, ///< Metadata reference (for debug info) MO_MCSymbol, ///< MCSymbol reference (for debug/eh info) + MO_DbgInstrRef, ///< Integer indices referring to an instruction+operand MO_CFIIndex, ///< MCCFIInstruction index. MO_IntrinsicID, ///< Intrinsic ID for ISel MO_Predicate, ///< Generic predicate for ISel @@ -184,6 +185,11 @@ MachineOperand *Next; } Reg; + struct { // For MO_DbgInstrRef. + unsigned InstrIdx; + unsigned OpIdx; + } InstrRef; + /// OffsetedInfo - This struct contains the offset and an object identifier. /// this represent the object as with an optional offset from it. struct { @@ -347,6 +353,7 @@ /// isMetadata - Tests if this is a MO_Metadata operand. bool isMetadata() const { return OpKind == MO_Metadata; } bool isMCSymbol() const { return OpKind == MO_MCSymbol; } + bool isDbgInstrRef() const { return OpKind == MO_DbgInstrRef; } bool isCFIIndex() const { return OpKind == MO_CFIIndex; } bool isIntrinsicID() const { return OpKind == MO_IntrinsicID; } bool isPredicate() const { return OpKind == MO_Predicate; } @@ -584,6 +591,16 @@ return Contents.Sym; } + unsigned getInstrIdx() const { + assert(isDbgInstrRef() && "Wrong MachineOperand accessor"); + return Contents.InstrRef.InstrIdx; + } + + unsigned getOpIdx() const { + assert(isDbgInstrRef() && "Wrong MachineOperand accessor"); + return Contents.InstrRef.OpIdx; + } + unsigned getCFIIndex() const { assert(isCFIIndex() && "Wrong MachineOperand accessor"); return Contents.CFIIndex; @@ -695,6 +712,15 @@ Contents.MD = MD; } + void setInstrIdx(unsigned InstrIdx) { + assert(isDbgInstrRef() && "Wrong MachineOperand mutator"); + Contents.InstrRef.InstrIdx = InstrIdx; + } + void setOpIdx(unsigned OpIdx) { + assert(isDbgInstrRef() && "Wrong MachineOperand mutator"); + Contents.InstrRef.OpIdx = OpIdx; + } + void setMBB(MachineBasicBlock *MBB) { assert(isMBB() && "Wrong MachineOperand mutator"); Contents.MBB = MBB; @@ -763,6 +789,10 @@ void ChangeToTargetIndex(unsigned Idx, int64_t Offset, unsigned TargetFlags = 0); + /// Replace this operand with an Instruction Reference. + void ChangeToDbgInstrRef(unsigned InstrIdx, unsigned OpIdx, + unsigned TargetFlags = 0); + /// ChangeToRegister - Replace this operand with a new register operand of /// the specified value. If an operand is known to be an register already, /// the setReg method should be used. @@ -919,6 +949,13 @@ return Op; } + static MachineOperand CreateDbgInstrRef(unsigned InstrIdx, unsigned OpIdx) { + MachineOperand Op(MachineOperand::MO_DbgInstrRef); + Op.Contents.InstrRef.InstrIdx = InstrIdx; + Op.Contents.InstrRef.OpIdx = OpIdx; + return Op; + } + static MachineOperand CreateCFIIndex(unsigned CFIIndex) { MachineOperand Op(MachineOperand::MO_CFIIndex); Op.Contents.CFIIndex = CFIIndex; diff --git a/llvm/lib/CodeGen/InlineSpiller.cpp b/llvm/lib/CodeGen/InlineSpiller.cpp --- a/llvm/lib/CodeGen/InlineSpiller.cpp +++ b/llvm/lib/CodeGen/InlineSpiller.cpp @@ -1063,6 +1063,7 @@ for (MachineInstr &MI : llvm::make_early_inc_range(MRI.reg_bundles(Reg))) { // Debug values are not allowed to affect codegen. if (MI.isDebugValue()) { + assert(!MI.isDebugRef() && "Debug Instr Ref should not use spilled reg"); // Modify DBG_VALUE now that the value is in a spill slot. MachineBasicBlock *MBB = MI.getParent(); LLVM_DEBUG(dbgs() << "Modifying debug info due to spill:\t" << MI); diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h @@ -978,7 +978,7 @@ void defVar(const MachineInstr &MI, const DbgValueProperties &Properties, const SmallVectorImpl &DebugOps) { - assert(MI.isDebugValue() || MI.isDebugRef()); + assert(MI.isDebugValueLike()); DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), MI.getDebugLoc()->getInlinedAt()); DbgValue Rec = (DebugOps.size() > 0) diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -1321,7 +1321,6 @@ bool InstrRefBasedLDV::transferDebugValue(const MachineInstr &MI) { if (!MI.isDebugValue()) return false; - const DILocalVariable *Var = MI.getDebugVariable(); const DIExpression *Expr = MI.getDebugExpression(); const DILocation *DebugLoc = MI.getDebugLoc(); @@ -1385,8 +1384,8 @@ if (!VTracker && !TTracker) return false; - unsigned InstNo = MI.getOperand(0).getImm(); - unsigned OpNo = MI.getOperand(1).getImm(); + unsigned InstNo = MI.getDebugOperand(0).getInstrIdx(); + unsigned OpNo = MI.getDebugOperand(0).getOpIdx(); const DILocalVariable *Var = MI.getDebugVariable(); const DIExpression *Expr = MI.getDebugExpression(); @@ -2076,7 +2075,7 @@ /// \param MI A previously unprocessed debug instruction to analyze for /// fragment usage. void InstrRefBasedLDV::accumulateFragmentMap(MachineInstr &MI) { - assert(MI.isDebugValue() || MI.isDebugRef()); + assert(MI.isDebugValueLike()); DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(), MI.getDebugLoc()->getInlinedAt()); FragmentInfo ThisFragment = MIVar.getFragmentOrDefault(); @@ -2181,7 +2180,7 @@ process(MI, nullptr, nullptr); // Also accumulate fragment map. - if (MI.isDebugValue() || MI.isDebugRef()) + if (MI.isDebugValueLike()) accumulateFragmentMap(MI); // Create a map from the instruction number (if present) to the diff --git a/llvm/lib/CodeGen/LiveDebugVariables.cpp b/llvm/lib/CodeGen/LiveDebugVariables.cpp --- a/llvm/lib/CodeGen/LiveDebugVariables.cpp +++ b/llvm/lib/CodeGen/LiveDebugVariables.cpp @@ -873,12 +873,16 @@ MachineBasicBlock::iterator LDVImpl::handleDebugInstr(MachineInstr &MI, SlotIndex Idx) { - assert(MI.isDebugValue() || MI.isDebugRef() || MI.isDebugPHI()); + assert(MI.isDebugValueLike() || MI.isDebugPHI()); // In instruction referencing mode, there should be no DBG_VALUE instructions // that refer to virtual registers. They might still refer to constants. - if (MI.isDebugValue()) - assert(!MI.getOperand(0).isReg() || !MI.getOperand(0).getReg().isVirtual()); + if (MI.isDebugValueLike()) + assert(none_of(MI.debug_operands(), + [](const MachineOperand &MO) { + return MO.isReg() && MO.getReg().isVirtual(); + }) && + "MIs should not refer to Virtual Registers in InstrRef mode."); // Unlink the instruction, store it in the debug instructions collection. auto NextInst = std::next(MI.getIterator()); diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -75,6 +75,7 @@ kw_nofpexcept, kw_debug_location, kw_debug_instr_number, + kw_dbg_instr_ref, kw_cfi_same_value, kw_cfi_offset, kw_cfi_rel_offset, diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -217,6 +217,7 @@ .Case("nofpexcept", MIToken::kw_nofpexcept) .Case("debug-location", MIToken::kw_debug_location) .Case("debug-instr-number", MIToken::kw_debug_instr_number) + .Case("dbg-instr-ref", MIToken::kw_dbg_instr_ref) .Case("same_value", MIToken::kw_cfi_same_value) .Case("offset", MIToken::kw_cfi_offset) .Case("rel_offset", MIToken::kw_cfi_rel_offset) @@ -277,7 +278,8 @@ .Case("unknown-address", MIToken::kw_unknown_address) .Case("distinct", MIToken::kw_distinct) .Case("ir-block-address-taken", MIToken::kw_ir_block_address_taken) - .Case("machine-block-address-taken", MIToken::kw_machine_block_address_taken) + .Case("machine-block-address-taken", + MIToken::kw_machine_block_address_taken) .Default(MIToken::Identifier); } diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -485,6 +485,7 @@ bool parsePredicateOperand(MachineOperand &Dest); bool parseShuffleMaskOperand(MachineOperand &Dest); bool parseTargetIndexOperand(MachineOperand &Dest); + bool parseDbgInstrRefOperand(MachineOperand &Dest); bool parseCustomRegisterMaskOperand(MachineOperand &Dest); bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest); bool parseMachineOperand(const unsigned OpCode, const unsigned OpIdx, @@ -2715,6 +2716,35 @@ return false; } +bool MIParser::parseDbgInstrRefOperand(MachineOperand &Dest) { + assert(Token.is(MIToken::kw_dbg_instr_ref)); + // TODO: Do we need to verify that the values passed are able to fit inside an + // unsigned? + + lex(); + if (expectAndConsume(MIToken::lparen)) + return error("expected syntax dbg-instr-ref(, )"); + + if (Token.isNot(MIToken::IntegerLiteral) || Token.integerValue().isNegative()) + return error("expected unsigned integer for instruction index"); + unsigned InstrIdx = Token.integerValue().getZExtValue(); + lex(); + + if (expectAndConsume(MIToken::comma)) + return error("expected syntax dbg-instr-ref(, )"); + + if (Token.isNot(MIToken::IntegerLiteral) || Token.integerValue().isNegative()) + return error("expected unsigned integer for operand index"); + unsigned OpIdx = Token.integerValue().getZExtValue(); + lex(); + + if (expectAndConsume(MIToken::rparen)) + return error("expected syntax dbg-instr-ref(, )"); + + Dest = MachineOperand::CreateDbgInstrRef(InstrIdx, OpIdx); + return false; +} + bool MIParser::parseTargetIndexOperand(MachineOperand &Dest) { assert(Token.is(MIToken::kw_target_index)); lex(); @@ -2866,6 +2896,8 @@ return parsePredicateOperand(Dest); case MIToken::kw_shufflemask: return parseShuffleMaskOperand(Dest); + case MIToken::kw_dbg_instr_ref: + return parseDbgInstrRefOperand(Dest); case MIToken::Error: return true; case MIToken::Identifier: diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -910,6 +910,7 @@ case MachineOperand::MO_IntrinsicID: case MachineOperand::MO_Predicate: case MachineOperand::MO_BlockAddress: + case MachineOperand::MO_DbgInstrRef: case MachineOperand::MO_ShuffleMask: { unsigned TiedOperandIdx = 0; if (ShouldPrintRegisterTies && Op.isReg() && Op.isTied() && !Op.isDef()) diff --git a/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp b/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp --- a/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp +++ b/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp @@ -112,6 +112,7 @@ case MachineOperand::MO_Metadata: case MachineOperand::MO_MCSymbol: case MachineOperand::MO_ShuffleMask: + case MachineOperand::MO_DbgInstrRef: return 0; } llvm_unreachable("Unexpected MachineOperandType."); diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -1189,19 +1189,18 @@ auto *TII = getSubtarget().getInstrInfo(); auto MakeUndefDbgValue = [&](MachineInstr &MI) { - const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_VALUE); + const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_VALUE_LIST); MI.setDesc(RefII); - MI.getOperand(0).setReg(0); - MI.getOperand(1).ChangeToRegister(0, false); + MI.getDebugOperand(0).setReg(0); }; DenseMap ArgDbgPHIs; for (auto &MBB : *this) { for (auto &MI : MBB) { - if (!MI.isDebugRef() || !MI.getOperand(0).isReg()) + if (!MI.isDebugRef() || !MI.getDebugOperand(0).isReg()) continue; - Register Reg = MI.getOperand(0).getReg(); + Register Reg = MI.getDebugOperand(0).getReg(); // Some vregs can be deleted as redundant in the meantime. Mark those // as DBG_VALUE $noreg. Additionally, some normal instructions are @@ -1219,8 +1218,7 @@ // for why this is important. if (DefMI.isCopyLike() || TII->isCopyInstr(DefMI)) { auto Result = salvageCopySSA(DefMI, ArgDbgPHIs); - MI.getOperand(0).ChangeToImmediate(Result.first); - MI.getOperand(1).setImm(Result.second); + MI.getDebugOperand(0).ChangeToDbgInstrRef(Result.first, Result.second); } else { // Otherwise, identify the operand number that the VReg refers to. unsigned OperandIdx = 0; @@ -1233,8 +1231,7 @@ // Morph this instr ref to point at the given instruction and operand. unsigned ID = DefMI.getDebugInstrNum(); - MI.getOperand(0).ChangeToImmediate(ID); - MI.getOperand(1).setImm(OperandIdx); + MI.getDebugOperand(0).ChangeToDbgInstrRef(ID, OperandIdx); } } } diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -828,14 +828,14 @@ } const MachineOperand &MachineInstr::getDebugVariableOp() const { - assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*"); - unsigned VariableOp = isDebugValueList() ? 0 : 2; + assert((isDebugValueLike()) && "not a DBG_VALUE*"); + unsigned VariableOp = isNonListDebugValue() ? 2 : 0; return getOperand(VariableOp); } MachineOperand &MachineInstr::getDebugVariableOp() { - assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*"); - unsigned VariableOp = isDebugValueList() ? 0 : 2; + assert((isDebugValueLike()) && "not a DBG_VALUE*"); + unsigned VariableOp = isNonListDebugValue() ? 2 : 0; return getOperand(VariableOp); } @@ -844,14 +844,14 @@ } const MachineOperand &MachineInstr::getDebugExpressionOp() const { - assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*"); - unsigned ExpressionOp = isDebugValueList() ? 1 : 3; + assert((isDebugValueLike()) && "not a DBG_VALUE*"); + unsigned ExpressionOp = isNonListDebugValue() ? 3 : 1; return getOperand(ExpressionOp); } MachineOperand &MachineInstr::getDebugExpressionOp() { - assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*"); - unsigned ExpressionOp = isDebugValueList() ? 1 : 3; + assert((isDebugValueLike()) && "not a DBG_VALUE*"); + unsigned ExpressionOp = isNonListDebugValue() ? 3 : 1; return getOperand(ExpressionOp); } @@ -2112,16 +2112,21 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID, bool IsIndirect, - const MachineOperand &MO, + ArrayRef DebugOps, const MDNode *Variable, const MDNode *Expr) { assert(isa(Variable) && "not a variable"); assert(cast(Expr)->isValid() && "not an expression"); assert(cast(Variable)->isValidLocationForIntrinsic(DL) && "Expected inlined-at fields to agree"); - if (MO.isReg()) - return BuildMI(MF, DL, MCID, IsIndirect, MO.getReg(), Variable, Expr); - - auto MIB = BuildMI(MF, DL, MCID).add(MO); + if (MCID.Opcode == TargetOpcode::DBG_VALUE) { + assert(DebugOps.size() == 1 && + "DBG_VALUE must contain exactly one debug operand"); + MachineOperand DebugOp = DebugOps[0]; + if (DebugOp.isReg()) + return BuildMI(MF, DL, MCID, IsIndirect, DebugOp.getReg(), Variable, + Expr); + + auto MIB = BuildMI(MF, DL, MCID).add(DebugOp); if (IsIndirect) MIB.addImm(0U); else @@ -2129,24 +2134,13 @@ return MIB.addMetadata(Variable).addMetadata(Expr); } -MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL, - const MCInstrDesc &MCID, bool IsIndirect, - ArrayRef MOs, - const MDNode *Variable, const MDNode *Expr) { - assert(isa(Variable) && "not a variable"); - assert(cast(Expr)->isValid() && "not an expression"); - assert(cast(Variable)->isValidLocationForIntrinsic(DL) && - "Expected inlined-at fields to agree"); - if (MCID.Opcode == TargetOpcode::DBG_VALUE) - return BuildMI(MF, DL, MCID, IsIndirect, MOs[0], Variable, Expr); - auto MIB = BuildMI(MF, DL, MCID); MIB.addMetadata(Variable).addMetadata(Expr); - for (const MachineOperand &MO : MOs) - if (MO.isReg()) - MIB.addReg(MO.getReg()); + for (const MachineOperand &DebugOp : DebugOps) + if (DebugOp.isReg()) + MIB.addReg(DebugOp.getReg()); else - MIB.add(MO); + MIB.add(DebugOp); return MIB; } @@ -2164,21 +2158,12 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, const DebugLoc &DL, const MCInstrDesc &MCID, - bool IsIndirect, MachineOperand &MO, - const MDNode *Variable, const MDNode *Expr) { - MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, MO, Variable, Expr); - BB.insert(I, MI); - return MachineInstrBuilder(MF, *MI); -} - -MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - const DebugLoc &DL, const MCInstrDesc &MCID, - bool IsIndirect, ArrayRef MOs, + bool IsIndirect, + ArrayRef DebugOps, const MDNode *Variable, const MDNode *Expr) { MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, MOs, Variable, Expr); + MachineInstr *MI = + BuildMI(MF, DL, MCID, IsIndirect, DebugOps, Variable, Expr); BB.insert(I, MI); return MachineInstrBuilder(MF, *MI); } @@ -2220,6 +2205,8 @@ MachineBasicBlock::iterator I, const MachineInstr &Orig, int FrameIndex, Register SpillReg) { + assert(!Orig.isDebugRef() && + "DBG_INSTR_REF should not reference a virtual register."); const DIExpression *Expr = computeExprForSpill(Orig, SpillReg); MachineInstrBuilder NewMI = BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc()); diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp --- a/llvm/lib/CodeGen/MachineOperand.cpp +++ b/llvm/lib/CodeGen/MachineOperand.cpp @@ -235,6 +235,19 @@ setTargetFlags(TargetFlags); } +void MachineOperand::ChangeToDbgInstrRef(unsigned InstrIdx, unsigned OpIdx, + unsigned TargetFlags) { + assert((!isReg() || !isTied()) && + "Cannot change a tied operand into a DbgInstrRef"); + + removeRegFromUses(); + + OpKind = MO_DbgInstrRef; + setInstrIdx(InstrIdx); + setOpIdx(OpIdx); + setTargetFlags(TargetFlags); +} + /// ChangeToRegister - Replace this operand with a new register operand of /// the specified value. If an operand is known to be an register already, /// the setReg method should be used. @@ -336,6 +349,9 @@ } case MachineOperand::MO_MCSymbol: return getMCSymbol() == Other.getMCSymbol(); + case MachineOperand::MO_DbgInstrRef: + return getInstrIdx() == Other.getInstrIdx() && + getOpIdx() == Other.getOpIdx(); case MachineOperand::MO_CFIIndex: return getCFIIndex() == Other.getCFIIndex(); case MachineOperand::MO_Metadata: @@ -400,6 +416,9 @@ return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata()); case MachineOperand::MO_MCSymbol: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol()); + case MachineOperand::MO_DbgInstrRef: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getInstrIdx(), + MO.getOpIdx()); case MachineOperand::MO_CFIIndex: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex()); case MachineOperand::MO_IntrinsicID: @@ -940,6 +959,10 @@ case MachineOperand::MO_MCSymbol: printSymbol(OS, *getMCSymbol()); break; + case MachineOperand::MO_DbgInstrRef: { + OS << "dbg-instr-ref(" << getInstrIdx() << ", " << getOpIdx() << ')'; + break; + } case MachineOperand::MO_CFIIndex: { if (const MachineFunction *MF = getMFIfAvailable(*this)) printCFI(OS, MF->getFrameInstructions()[getCFIIndex()], TRI); diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp --- a/llvm/lib/CodeGen/MachineSink.cpp +++ b/llvm/lib/CodeGen/MachineSink.cpp @@ -568,6 +568,10 @@ // we know what to sink if the vreg def sinks. assert(MI.isDebugValue() && "Expected DBG_VALUE for processing"); + // DBG_INSTR_REF should not contain any virtual registers. + if (MI.isDebugRef()) + return; + DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), MI.getDebugLoc()->getInlinedAt()); bool SeenBefore = SeenDbgVars.contains(Var); @@ -1779,7 +1783,7 @@ // We must sink this DBG_VALUE if its operand is sunk. To avoid searching // for DBG_VALUEs later, record them when they're encountered. - if (MI.isDebugValue()) { + if (MI.isDebugValue() && !MI.isDebugRef()) { SmallDenseMap, 4> MIUnits; bool IsValid = true; for (MachineOperand &MO : MI.debug_operands()) { diff --git a/llvm/lib/CodeGen/MachineStableHash.cpp b/llvm/lib/CodeGen/MachineStableHash.cpp --- a/llvm/lib/CodeGen/MachineStableHash.cpp +++ b/llvm/lib/CodeGen/MachineStableHash.cpp @@ -165,6 +165,8 @@ case MachineOperand::MO_Predicate: return stable_hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate()); + case MachineOperand::MO_DbgInstrRef: + return stable_hash_combine(MO.getType(), MO.getInstrIdx(), MO.getOpIdx()); } llvm_unreachable("Invalid machine operand type"); } diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1252,22 +1252,21 @@ if (Op) { assert(DI->getVariable()->isValidLocationForIntrinsic(MIMD.getDL()) && "Expected inlined-at fields to agree"); + if (!UseInstrRefDebugInfo || !Op->isReg()) { // A dbg.declare describes the address of a source variable, so lower it // into an indirect DBG_VALUE. - auto Builder = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD.getDL(), TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true, *Op, DI->getVariable(), DI->getExpression()); - - // If using instruction referencing, mutate this into a DBG_INSTR_REF, + } else { + // If using instruction referencing, produce this as a DBG_INSTR_REF, // to be later patched up by finalizeDebugInstrRefs. Tack a deref onto // the expression, we don't have an "indirect" flag in DBG_INSTR_REF. - if (UseInstrRefDebugInfo && Op->isReg()) { - Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF)); - Builder->getOperand(1).ChangeToImmediate(0); auto *NewExpr = DIExpression::prepend(DI->getExpression(), DIExpression::DerefBefore); - Builder->getOperand(3).setMetadata(NewExpr); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD.getDL(), + TII.get(TargetOpcode::DBG_INSTR_REF), /*IsIndirect*/ false, *Op, + DI->getVariable(), NewExpr); } } else { // We can't yet handle anything else here because it would require @@ -1314,16 +1313,21 @@ .addMetadata(DI->getExpression()); } else if (Register Reg = lookUpRegForValue(V)) { // FIXME: This does not handle register-indirect values at offset 0. + if (!UseInstrRefDebugInfo) { bool IsIndirect = false; - auto Builder = - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD.getDL(), II, - IsIndirect, Reg, DI->getVariable(), DI->getExpression()); - - // If using instruction referencing, mutate this into a DBG_INSTR_REF, + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD.getDL(), II, IsIndirect, + Reg, DI->getVariable(), DI->getExpression()); + } else { + // If using instruction referencing, produce this as a DBG_INSTR_REF, // to be later patched up by finalizeDebugInstrRefs. - if (UseInstrRefDebugInfo) { - Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF)); - Builder->getOperand(1).ChangeToImmediate(0); + SmallVector MOs({MachineOperand::CreateReg( + /* Reg */ Reg, /* isDef */ false, /* isImp */ false, + /* isKill */ false, /* isDead */ false, + /* isUndef */ false, /* isEarlyClobber */ false, + /* SubReg */ 0, /* isDebug */ true)}); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD.getDL(), + TII.get(TargetOpcode::DBG_INSTR_REF), /*IsIndirect*/ false, MOs, + DI->getVariable(), DI->getExpression()); } } else { // We don't know how to handle other cases, so we drop. diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp --- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -795,12 +795,12 @@ // i.e., point the instruction at the vreg, and patch it up later in // MachineFunction::finalizeDebugInstrRefs. auto EmitHalfDoneInstrRef = [&](unsigned VReg) -> MachineInstr * { - auto MIB = BuildMI(*MF, DL, RefII); - MIB.addReg(VReg); - MIB.addImm(0); - MIB.addMetadata(Var); - MIB.addMetadata(Expr); - return MIB; + SmallVector MOs({MachineOperand::CreateReg( + /* Reg */ VReg, /* isDef */ false, /* isImp */ false, + /* isKill */ false, /* isDead */ false, + /* isUndef */ false, /* isEarlyClobber */ false, + /* SubReg */ 0, /* isDebug */ true)}); + return BuildMI(*MF, DL, RefII, false, MOs, Var, Expr); }; // Try to find both the defined register and the instruction defining it. @@ -843,8 +843,6 @@ if (DefMI->isCopyLike() || TII->isCopyInstr(*DefMI)) return EmitHalfDoneInstrRef(VReg); - auto MIB = BuildMI(*MF, DL, RefII); - // Find the operand number which defines the specified VReg. unsigned OperandIdx = 0; for (const auto &MO : DefMI->operands()) { @@ -856,11 +854,9 @@ // Make the DBG_INSTR_REF refer to that instruction, and that operand. unsigned InstrNum = DefMI->getDebugInstrNum(); - MIB.addImm(InstrNum); - MIB.addImm(OperandIdx); - MIB.addMetadata(Var); - MIB.addMetadata(Expr); - return &*MIB; + SmallVector MOs( + {MachineOperand::CreateDbgInstrRef(InstrNum, OperandIdx)}); + return BuildMI(*MF, DL, RefII, false, MOs, Var, Expr); } MachineInstr *InstrEmitter::EmitDbgNoLocation(SDDbgValue *SD) { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5552,17 +5552,18 @@ // For VRegs, in instruction referencing mode, create a DBG_INSTR_REF // pointing at the VReg, which will be patched up later. auto &Inst = TII->get(TargetOpcode::DBG_INSTR_REF); - auto MIB = BuildMI(MF, DL, Inst); - MIB.addReg(Reg); - MIB.addImm(0); - MIB.addMetadata(Variable); + SmallVector MOs({MachineOperand::CreateReg( + /* Reg */ Reg, /* isDef */ false, /* isImp */ false, + /* isKill */ false, /* isDead */ false, + /* isUndef */ false, /* isEarlyClobber */ false, + /* SubReg */ 0, /* isDebug */ true)}); + auto *NewDIExpr = FragExpr; // We don't have an "Indirect" field in DBG_INSTR_REF, fold that into // the DIExpression. if (Indirect) NewDIExpr = DIExpression::prepend(FragExpr, DIExpression::DerefBefore); - MIB.addMetadata(NewDIExpr); - return MIB; + return BuildMI(MF, DL, Inst, false, MOs, Variable, NewDIExpr); } else { // Create a completely standard DBG_VALUE. auto &Inst = TII->get(TargetOpcode::DBG_VALUE); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -535,9 +535,9 @@ MachineInstr *MI = FuncInfo->ArgDbgValues[e - i - 1]; assert(MI->getOpcode() != TargetOpcode::DBG_VALUE_LIST && "Function parameters should not be described by DBG_VALUE_LIST."); - bool hasFI = MI->getOperand(0).isFI(); + bool hasFI = MI->getDebugOperand(0).isFI(); Register Reg = - hasFI ? TRI.getFrameRegister(*MF) : MI->getOperand(0).getReg(); + hasFI ? TRI.getFrameRegister(*MF) : MI->getDebugOperand(0).getReg(); if (Register::isPhysicalRegister(Reg)) EntryMBB->insert(EntryMBB->begin(), MI); else { @@ -567,7 +567,7 @@ DebugLoc DL = MI->getDebugLoc(); bool IsIndirect = MI->isIndirectDebugValue(); if (IsIndirect) - assert(MI->getOperand(1).getImm() == 0 && + assert(MI->getDebugOffset().getImm() == 0 && "DBG_VALUE with nonzero offset"); assert(cast(Variable)->isValidLocationForIntrinsic(DL) && "Expected inlined-at fields to agree"); diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -953,6 +953,7 @@ case MachineOperand::MO_Metadata: case MachineOperand::MO_MCSymbol: return true; + case MachineOperand::MO_DbgInstrRef: case MachineOperand::MO_CFIIndex: return false; case MachineOperand::MO_IntrinsicID: