aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineInstr.cpp
diff options
context:
space:
mode:
authorgbtozers <stephen.tozer@sony.com>2020-09-11 15:58:01 +0100
committerStephen Tozer <Stephen.Tozer@Sony.com>2021-03-04 11:45:35 +0000
commitd07f106f4a48b6e941266525b6f7177834d7b74e (patch)
treec431b88aa92371156c8cd32835f4fd3914f74b37 /llvm/lib/CodeGen/MachineInstr.cpp
parent1562e4552cd1b3d2eadd956c966f8a60e928b8ca (diff)
downloadllvm-d07f106f4a48b6e941266525b6f7177834d7b74e.zip
llvm-d07f106f4a48b6e941266525b6f7177834d7b74e.tar.gz
llvm-d07f106f4a48b6e941266525b6f7177834d7b74e.tar.bz2
[DebugInfo] Add new instruction and DIExpression operator for variadic debug values
This patch adds a new instruction that can represent variadic debug values, DBG_VALUE_VAR. This patch alone covers the addition of the instruction and a set of basic code changes in MachineInstr and a few adjacent areas, but does not correctly handle variadic debug values outside of these areas, nor does it generate them at any point. The new instruction is similar to the existing DBG_VALUE instruction, with the following differences: the operands are in a different order, any number of values may be used in the instruction following the Variable and Expression operands (these are referred to in code as “debug operands”) and are indexed from 0 so that getDebugOperand(X) == getOperand(X+2), and the Expression in a DBG_VALUE_VAR must use the DW_OP_LLVM_arg operator to pass arguments into the expression. The new DW_OP_LLVM_arg operator is only valid in expressions appearing in a DBG_VALUE_VAR; it takes a single argument and pushes the debug operand at the index given by the argument onto the Expression stack. For example the sub-expression `DW_OP_LLVM_arg, 0` has the meaning “Push the debug operand at index 0 onto the expression stack.” Differential Revision: https://reviews.llvm.org/D82363
Diffstat (limited to 'llvm/lib/CodeGen/MachineInstr.cpp')
-rw-r--r--llvm/lib/CodeGen/MachineInstr.cpp126
1 files changed, 94 insertions, 32 deletions
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 94afaff..c1b04d7 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -841,28 +841,35 @@ const DILabel *MachineInstr::getDebugLabel() const {
}
const MachineOperand &MachineInstr::getDebugVariableOp() const {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return getOperand(2);
+ assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*");
+ unsigned VariableOp = isDebugValueList() ? 0 : 2;
+ return getOperand(VariableOp);
}
MachineOperand &MachineInstr::getDebugVariableOp() {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return getOperand(2);
+ assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*");
+ unsigned VariableOp = isDebugValueList() ? 0 : 2;
+ return getOperand(VariableOp);
}
const DILocalVariable *MachineInstr::getDebugVariable() const {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return cast<DILocalVariable>(getOperand(2).getMetadata());
+ return cast<DILocalVariable>(getDebugVariableOp().getMetadata());
+}
+
+const MachineOperand &MachineInstr::getDebugExpressionOp() const {
+ assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*");
+ unsigned ExpressionOp = isDebugValueList() ? 1 : 3;
+ return getOperand(ExpressionOp);
}
MachineOperand &MachineInstr::getDebugExpressionOp() {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return getOperand(3);
+ assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE*");
+ unsigned ExpressionOp = isDebugValueList() ? 1 : 3;
+ return getOperand(ExpressionOp);
}
const DIExpression *MachineInstr::getDebugExpression() const {
- assert((isDebugValue() || isDebugRef()) && "not a DBG_VALUE");
- return cast<DIExpression>(getOperand(3).getMetadata());
+ return cast<DIExpression>(getDebugExpressionOp().getMetadata());
}
bool MachineInstr::isDebugEntryValue() const {
@@ -1712,7 +1719,7 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
OS << " ";
if (isDebugValue() && MO.isMetadata()) {
- // Pretty print DBG_VALUE instructions.
+ // Pretty print DBG_VALUE* instructions.
auto *DIV = dyn_cast<DILocalVariable>(MO.getMetadata());
if (DIV && !DIV->getName().empty())
OS << "!\"" << DIV->getName() << '\"';
@@ -2116,8 +2123,8 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID, bool IsIndirect,
- MachineOperand &MO, const MDNode *Variable,
- const MDNode *Expr) {
+ const MachineOperand &MO,
+ const MDNode *Variable, const MDNode *Expr) {
assert(isa<DILocalVariable>(Variable) && "not a variable");
assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
@@ -2131,7 +2138,28 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
else
MIB.addReg(0U, RegState::Debug);
return MIB.addMetadata(Variable).addMetadata(Expr);
- }
+}
+
+MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
+ const MCInstrDesc &MCID, bool IsIndirect,
+ ArrayRef<MachineOperand> MOs,
+ const MDNode *Variable, const MDNode *Expr) {
+ assert(isa<DILocalVariable>(Variable) && "not a variable");
+ assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
+ assert(cast<DILocalVariable>(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(), RegState::Debug);
+ else
+ MIB.add(MO);
+ return MIB;
+}
MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
@@ -2155,10 +2183,22 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MF, *MI);
}
+MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
+ MachineBasicBlock::iterator I,
+ const DebugLoc &DL, const MCInstrDesc &MCID,
+ bool IsIndirect, ArrayRef<MachineOperand> MOs,
+ const MDNode *Variable, const MDNode *Expr) {
+ MachineFunction &MF = *BB.getParent();
+ MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, MOs, Variable, Expr);
+ BB.insert(I, MI);
+ return MachineInstrBuilder(MF, *MI);
+}
+
/// Compute the new DIExpression to use with a DBG_VALUE for a spill slot.
/// This prepends DW_OP_deref when spilling an indirect DBG_VALUE.
-static const DIExpression *computeExprForSpill(const MachineInstr &MI) {
- assert(MI.getOperand(0).isReg() && "can't spill non-register");
+static const DIExpression *computeExprForSpill(const MachineInstr &MI,
+ Register SpillReg) {
+ assert(MI.hasDebugOperandForReg(SpillReg) && "Spill Reg is not used in MI.");
assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
"Expected inlined-at fields to agree");
@@ -2167,6 +2207,14 @@ static const DIExpression *computeExprForSpill(const MachineInstr &MI) {
assert(MI.getDebugOffset().getImm() == 0 &&
"DBG_VALUE with nonzero offset");
Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore);
+ } else if (MI.isDebugValueList()) {
+ // We will replace the spilled register with a frame index, so
+ // immediately deref all references to the spilled register.
+ std::array<uint64_t, 1> Ops{{dwarf::DW_OP_deref}};
+ for (const MachineOperand &Op : MI.getDebugOperandsForReg(SpillReg)) {
+ unsigned OpIdx = MI.getDebugOperandIndex(&Op);
+ Expr = DIExpression::appendOpsToArg(Expr, Ops, OpIdx);
+ }
}
return Expr;
}
@@ -2174,19 +2222,32 @@ static const DIExpression *computeExprForSpill(const MachineInstr &MI) {
MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
const MachineInstr &Orig,
- int FrameIndex) {
- const DIExpression *Expr = computeExprForSpill(Orig);
- return BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc())
- .addFrameIndex(FrameIndex)
- .addImm(0U)
- .addMetadata(Orig.getDebugVariable())
- .addMetadata(Expr);
-}
-
-void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex) {
- const DIExpression *Expr = computeExprForSpill(Orig);
- Orig.getDebugOperand(0).ChangeToFrameIndex(FrameIndex);
- Orig.getDebugOffset().ChangeToImmediate(0U);
+ int FrameIndex, Register SpillReg) {
+ const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
+ MachineInstrBuilder NewMI =
+ BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
+ // Non-Variadic Operands: Location, Offset, Variable, Expression
+ // Variadic Operands: Variable, Expression, Locations...
+ if (Orig.isNonListDebugValue())
+ NewMI.addFrameIndex(FrameIndex).addImm(0U);
+ NewMI.addMetadata(Orig.getDebugVariable()).addMetadata(Expr);
+ if (Orig.isDebugValueList()) {
+ for (const MachineOperand &Op : Orig.debug_operands())
+ if (Op.isReg() && Op.getReg() == SpillReg)
+ NewMI.addFrameIndex(FrameIndex);
+ else
+ NewMI.add(MachineOperand(Op));
+ }
+ return NewMI;
+}
+
+void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex,
+ Register Reg) {
+ const DIExpression *Expr = computeExprForSpill(Orig, Reg);
+ if (Orig.isNonListDebugValue())
+ Orig.getDebugOffset().ChangeToImmediate(0U);
+ for (MachineOperand &Op : Orig.getDebugOperandsForReg(Reg))
+ Op.ChangeToFrameIndex(FrameIndex);
Orig.getDebugExpressionOp().setMetadata(Expr);
}
@@ -2201,7 +2262,7 @@ void MachineInstr::collectDebugValues(
DI != DE; ++DI) {
if (!DI->isDebugValue())
return;
- if (DI->getDebugOperandForReg(MI.getOperand(0).getReg()))
+ if (DI->hasDebugOperandForReg(MI.getOperand(0).getReg()))
DbgValues.push_back(&*DI);
}
}
@@ -2219,14 +2280,15 @@ void MachineInstr::changeDebugValuesDefReg(Register Reg) {
auto *DI = MO.getParent();
if (!DI->isDebugValue())
continue;
- if (DI->getDebugOperandForReg(DefReg)) {
+ if (DI->hasDebugOperandForReg(DefReg)) {
DbgValues.push_back(DI);
}
}
// Propagate Reg to debug value instructions.
for (auto *DBI : DbgValues)
- DBI->getDebugOperandForReg(DefReg)->setReg(Reg);
+ for (MachineOperand &Op : DBI->getDebugOperandsForReg(DefReg))
+ Op.setReg(Reg);
}
using MMOList = SmallVector<const MachineMemOperand *, 2>;