diff options
author | Reid Kleckner <rnk@google.com> | 2017-09-15 21:49:56 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2017-09-15 21:49:56 +0000 |
commit | 9e6c309ef343acc13a14ca97f370e35079fbea1f (patch) | |
tree | 72a3937bb888c2a47ae4f66224fb092ba9d68bfb /llvm/lib/CodeGen/MachineInstr.cpp | |
parent | ab211df5de42bf2b2f45fc73134c76f24835b47a (diff) | |
download | bcm5719-llvm-9e6c309ef343acc13a14ca97f370e35079fbea1f.tar.gz bcm5719-llvm-9e6c309ef343acc13a14ca97f370e35079fbea1f.zip |
[DebugInfo] Add missing DW_OP_deref when an NRVO pointer is spilled
Summary:
Fixes PR34513.
Indirect DBG_VALUEs typically come from dbg.declares of non-trivially
copyable C++ objects that must be passed by address. We were already
handling the case where the virtual register gets allocated to a
physical register and is later spilled. That's what usually happens for
normal parameters that aren't NRVO variables: they usually appear in
physical register parameters, and are spilled later in the function,
which would correctly add deref.
NRVO variables are different because the dbg.declare can come much later
after earlier instructions cause the incoming virtual register to be
spilled.
Also, clean up this code. We only need to look at the first operand of a
DBG_VALUE, which eliminates the operand loop.
Reviewers: aprantl, dblaikie, probinson
Subscribers: MatzeB, qcolombet, llvm-commits, hiraditya
Differential Revision: https://reviews.llvm.org/D37929
llvm-svn: 313399
Diffstat (limited to 'llvm/lib/CodeGen/MachineInstr.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineInstr.cpp | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index 6684f4e5d1c..66de99156b4 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -2408,26 +2408,36 @@ MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB, 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"); + assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) && + "Expected inlined-at fields to agree"); + + const DIExpression *Expr = MI.getDebugExpression(); + if (MI.isIndirectDebugValue()) { + assert(MI.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset"); + Expr = DIExpression::prepend(Expr, DIExpression::WithDeref); + } + return Expr; +} + MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB, MachineBasicBlock::iterator I, const MachineInstr &Orig, int FrameIndex) { - const MDNode *Var = Orig.getDebugVariable(); - const auto *Expr = cast_or_null<DIExpression>(Orig.getDebugExpression()); - bool IsIndirect = Orig.isIndirectDebugValue(); - if (IsIndirect) - assert(Orig.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset"); - DebugLoc DL = Orig.getDebugLoc(); - assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) && - "Expected inlined-at fields to agree"); - // If the DBG_VALUE already was a memory location, add an extra - // DW_OP_deref. Otherwise just turning this from a register into a - // memory/indirect location is sufficient. - if (IsIndirect) - Expr = DIExpression::prepend(Expr, DIExpression::WithDeref); - return BuildMI(BB, I, DL, Orig.getDesc()) + const DIExpression *Expr = computeExprForSpill(Orig); + return BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc()) .addFrameIndex(FrameIndex) .addImm(0U) - .addMetadata(Var) + .addMetadata(Orig.getDebugVariable()) .addMetadata(Expr); } + +void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex) { + const DIExpression *Expr = computeExprForSpill(Orig); + Orig.getOperand(0).ChangeToFrameIndex(FrameIndex); + Orig.getOperand(1).ChangeToImmediate(0U); + Orig.getOperand(3).setMetadata(Expr); +} |