[DWARF] Fix a few corner cases in expression emission
Summary: I noticed an object file with `DW_OP_reg4 DW_OP_breg4 0` as a DWARF expression,
which I traced to a missing break (and `++I`) in this code snippet.
While I was at it, I also added support for a few other corner cases
along the same lines that I could think of.
Test Plan: Hand-crafted test case to exercises these cases is included.
Reviewers: echristo, dblaikie, aprantl
Reviewed By: aprantl
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D10302
llvm-svn: 239380
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index a2799b8..d569827 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -65,6 +65,11 @@
EmitOp(dwarf::DW_OP_shr);
}
+void DwarfExpression::AddOpStackValue() {
+ if (DwarfVersion >= 4)
+ EmitOp(dwarf::DW_OP_stack_value);
+}
+
bool DwarfExpression::AddMachineRegIndirect(unsigned MachineReg, int Offset) {
if (isFrameRegister(MachineReg)) {
// If variable offset is based in frame register then use fbreg.
@@ -172,16 +177,14 @@
// value, so the producers and consumers started to rely on heuristics
// to disambiguate the value vs. location status of the expression.
// See PR21176 for more details.
- if (DwarfVersion >= 4)
- EmitOp(dwarf::DW_OP_stack_value);
+ AddOpStackValue();
}
void DwarfExpression::AddUnsignedConstant(unsigned Value) {
EmitOp(dwarf::DW_OP_constu);
EmitUnsigned(Value);
// cf. comment in DwarfExpression::AddSignedConstant().
- if (DwarfVersion >= 4)
- EmitOp(dwarf::DW_OP_stack_value);
+ AddOpStackValue();
}
static unsigned getOffsetOrZero(unsigned OffsetInBits,
@@ -212,15 +215,30 @@
getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
}
case dwarf::DW_OP_plus: {
- // [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] --> [DW_OP_breg,Offset].
auto N = I.getNext();
+ unsigned Offset = I->getArg(0);
+ // First combine all DW_OP_plus until we hit either a DW_OP_deref or a
+ // DW_OP_bit_piece
+ while (N != E && N->getOp() == dwarf::DW_OP_plus) {
+ Offset += N->getArg(0);
+ ++I;
+ N = I.getNext();
+ }
if (N != E && N->getOp() == dwarf::DW_OP_deref) {
- unsigned Offset = I->getArg(0);
+ // [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] --> [DW_OP_breg,Offset].
ValidReg = AddMachineRegIndirect(MachineReg, Offset);
std::advance(I, 2);
- break;
- } else
- ValidReg = AddMachineRegPiece(MachineReg);
+ } else {
+ assert ((N == E) || (N->getOp() == dwarf::DW_OP_bit_piece));
+ if (Offset == 0) {
+ ValidReg = AddMachineRegPiece(MachineReg);
+ } else {
+ ValidReg = AddMachineRegIndirect(MachineReg, Offset);
+ AddOpStackValue();
+ }
+ ++I;
+ }
+ break;
}
case dwarf::DW_OP_deref: {
// [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
@@ -237,6 +255,7 @@
// Emit remaining elements of the expression.
AddExpression(I, E, PieceOffsetInBits);
+
return true;
}