summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorAdrian Prantl <aprantl@apple.com>2016-12-09 20:43:40 +0000
committerAdrian Prantl <aprantl@apple.com>2016-12-09 20:43:40 +0000
commit8fafb8d37861378bfc7432891edd8c75a3589f71 (patch)
tree767b8dd7d993e271d72a45f9332b317f79a6ce20 /llvm/lib
parent34359cf0fa03ba36487390d7c2a98f6a014e3430 (diff)
downloadbcm5719-llvm-8fafb8d37861378bfc7432891edd8c75a3589f71.tar.gz
bcm5719-llvm-8fafb8d37861378bfc7432891edd8c75a3589f71.zip
Fix LLVM's use of DW_OP_bit_piece in DWARF expressions.
LLVM's use of DW_OP_bit_piece is incorrect and a based on a misunderstanding of the wording in the DWARF specification. The offset argument of DW_OP_bit_piece refers to the offset into the location that is on the top of the DWARF expression stack, and not an offset into the source variable. This has since also been clarified in the DWARF specification. This patch fixes all uses of DW_OP_bit_piece to emit the correct offset and simplifies the DwarfExpression class to semi-automaticaly emit empty DW_OP_pieces to adjust the offset of the source variable, thus simplifying the code using DwarfExpression. While this is an incompatible bugfix, in practice I don't expect this to be much of a problem since LLVM's old interpretation and the correct interpretation of DW_OP_bit_piece differ only when there are gaps in the fragmented locations of the described variables or if individual fragments are smaller than a byte. LLDB at least won't interpret locations with gaps in them because is has no way to present undefined bits in a variable, and there is a high probability that an old-form expression will be malformed when interpreted correctly, because the DW_OP_bit_piece offset will be outside of the location at the top of the stack. As a nice side-effect, this patch enables us to use a more efficient encoding for subregisters: In order to express a sub-register at a non-zero offset we now use a DW_OP_bit_piece instead of shifting the value into place manually. This patch also adds missing test coverage for code paths that weren't exercised before. <rdar://problem/29335809> Differential Revision: https://reviews.llvm.org/D27550 llvm-svn: 289266
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp30
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp20
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp46
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp97
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h40
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp39
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h13
7 files changed, 129 insertions, 156 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index c104c3cd948..6c1cc7e519e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -174,36 +174,6 @@ void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntryRef S) const {
EmitInt32(S.getOffset());
}
-/// EmitDwarfRegOp - Emit dwarf register operation.
-void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer,
- const MachineLocation &MLoc) const {
- DebugLocDwarfExpression Expr(getDwarfVersion(), Streamer);
- const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo();
- int Reg = MRI->getDwarfRegNum(MLoc.getReg(), false);
- if (Reg < 0) {
- // We assume that pointers are always in an addressable register.
- if (MLoc.isIndirect())
- // FIXME: We have no reasonable way of handling errors in here. The
- // caller might be in the middle of a dwarf expression. We should
- // probably assert that Reg >= 0 once debug info generation is more
- // mature.
- return Expr.EmitOp(dwarf::DW_OP_nop,
- "nop (could not find a dwarf register number)");
-
- // Attempt to find a valid super- or sub-register.
- if (!Expr.AddMachineRegFragment(*MF->getSubtarget().getRegisterInfo(),
- MLoc.getReg()))
- Expr.EmitOp(dwarf::DW_OP_nop,
- "nop (could not find a dwarf register number)");
- return;
- }
-
- if (MLoc.isIndirect())
- Expr.AddRegIndirect(Reg, MLoc.getOffset());
- else
- Expr.AddReg(Reg);
-}
-
//===----------------------------------------------------------------------===//
// Dwarf Lowering Routines
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index c615cea1d7c..024f6d27836 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -180,7 +180,9 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
if (Expr) {
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+ DwarfExpr.addFragmentOffset(Expr);
DwarfExpr.AddExpression(Expr);
+ DwarfExpr.finalize();
}
}
@@ -498,8 +500,10 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
// If there is an expression, emit raw unsigned bytes.
+ DwarfExpr.addFragmentOffset(Expr);
DwarfExpr.AddUnsignedConstant(DVInsn->getOperand(0).getImm());
DwarfExpr.AddExpression(Expr);
+ DwarfExpr.finalize();
addBlock(*VariableDie, dwarf::DW_AT_location, Loc);
} else
addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType());
@@ -524,11 +528,13 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
assert(Expr != DV.getExpression().end() && "Wrong number of expressions");
+ DwarfExpr.addFragmentOffset(*Expr);
DwarfExpr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
FrameReg, Offset);
DwarfExpr.AddExpression(*Expr);
++Expr;
}
+ DwarfExpr.finalize();
addBlock(*VariableDie, dwarf::DW_AT_location, Loc);
return VariableDie;
@@ -727,16 +733,22 @@ void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die,
void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
const MachineLocation &Location) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression Expr(*Asm, *this, *Loc);
bool validReg;
if (Location.isReg())
- validReg = addRegisterFragment(*Loc, Location.getReg());
+ validReg = Expr.AddMachineReg(*Asm->MF->getSubtarget().getRegisterInfo(),
+ Location.getReg());
else
- validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
+ validReg =
+ Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
+ Location.getReg(), Location.getOffset());
if (!validReg)
return;
+ Expr.finalize();
+
// Now attach the location information to the DIE.
addBlock(Die, Attribute, Loc);
}
@@ -750,9 +762,11 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die,
const MachineLocation &Location) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
- DIExpressionCursor ExprCursor(DV.getSingleExpression());
+ const DIExpression *Expr = DV.getSingleExpression();
+ DIExpressionCursor ExprCursor(Expr);
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
auto Reg = Location.getReg();
+ DwarfExpr.addFragmentOffset(Expr);
bool ValidReg =
Location.getOffset()
? DwarfExpr.AddMachineRegIndirect(TRI, Reg, Location.getOffset())
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 5ad0df76986..12949e0991d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1413,9 +1413,9 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
ByteStreamer &Streamer,
const DebugLocEntry::Value &Value,
- unsigned FragmentOffsetInBits) {
+ DwarfExpression &DwarfExpr) {
DIExpressionCursor ExprCursor(Value.getExpression());
- DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer);
+ DwarfExpr.addFragmentOffset(Value.getExpression());
// Regular entry.
if (Value.isInt()) {
if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
@@ -1425,23 +1425,16 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
DwarfExpr.AddUnsignedConstant(Value.getInt());
} else if (Value.isLocation()) {
MachineLocation Loc = Value.getLoc();
- if (!ExprCursor)
- // Regular entry.
- AP.EmitDwarfRegOp(Streamer, Loc);
- else {
- // Complex address entry.
- const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
- if (Loc.getOffset())
- DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset());
- else
- DwarfExpr.AddMachineRegExpression(TRI, ExprCursor, Loc.getReg(),
- FragmentOffsetInBits);
- }
+ const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
+ if (Loc.getOffset())
+ DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset());
+ else
+ DwarfExpr.AddMachineRegExpression(TRI, ExprCursor, Loc.getReg());
} else if (Value.isConstantFP()) {
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
DwarfExpr.AddUnsignedConstant(RawBytes);
}
- DwarfExpr.AddExpression(std::move(ExprCursor), FragmentOffsetInBits);
+ DwarfExpr.AddExpression(std::move(ExprCursor));
}
void DebugLocEntry::finalize(const AsmPrinter &AP,
@@ -1449,6 +1442,7 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,
const DIBasicType *BT) {
DebugLocStream::EntryBuilder Entry(List, Begin, End);
BufferByteStreamer Streamer = Entry.getStreamer();
+ DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer);
const DebugLocEntry::Value &Value = Values[0];
if (Value.isFragment()) {
// Emit all fragments that belong to the same variable and range.
@@ -1457,27 +1451,15 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,
}) && "all values are expected to be fragments");
assert(std::is_sorted(Values.begin(), Values.end()) &&
"fragments are expected to be sorted");
-
- unsigned Offset = 0;
- for (auto Fragment : Values) {
- const DIExpression *Expr = Fragment.getExpression();
- unsigned FragmentOffset = Expr->getFragmentOffsetInBits();
- unsigned FragmentSize = Expr->getFragmentSizeInBits();
- assert(Offset <= FragmentOffset && "overlapping or duplicate fragments");
- if (Offset < FragmentOffset) {
- // DWARF represents gaps as pieces with no locations.
- DebugLocDwarfExpression Expr(AP.getDwarfVersion(), Streamer);
- Expr.AddOpPiece(FragmentOffset-Offset, 0);
- Offset += FragmentOffset-Offset;
- }
- Offset += FragmentSize;
- emitDebugLocValue(AP, BT, Streamer, Fragment, FragmentOffset);
- }
+ for (auto Fragment : Values)
+ emitDebugLocValue(AP, BT, Streamer, Fragment, DwarfExpr);
+
} else {
assert(Values.size() == 1 && "only fragments may have >1 value");
- emitDebugLocValue(AP, BT, Streamer, Value, 0);
+ emitDebugLocValue(AP, BT, Streamer, Value, DwarfExpr);
}
+ DwarfExpr.finalize();
}
void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index fe999efa2c9..a17776f2ce9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -46,7 +46,9 @@ void DwarfExpression::AddRegIndirect(int DwarfReg, int Offset, bool Deref) {
}
void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) {
- assert(SizeInBits > 0 && "piece has size zero");
+ if (!SizeInBits)
+ return;
+
const unsigned SizeOfByte = 8;
if (OffsetInBits > 0 || SizeInBits % SizeOfByte) {
EmitOp(dwarf::DW_OP_bit_piece);
@@ -57,6 +59,7 @@ void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) {
unsigned ByteSize = SizeInBits / SizeOfByte;
EmitUnsigned(ByteSize);
}
+ this->OffsetInBits += SizeInBits;
}
void DwarfExpression::AddShr(unsigned ShiftBy) {
@@ -82,10 +85,8 @@ bool DwarfExpression::AddMachineRegIndirect(const TargetRegisterInfo &TRI,
return true;
}
-bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI,
- unsigned MachineReg,
- unsigned FragmentSizeInBits,
- unsigned FragmentOffsetInBits) {
+bool DwarfExpression::AddMachineReg(const TargetRegisterInfo &TRI,
+ unsigned MachineReg) {
if (!TRI.isPhysicalRegister(MachineReg))
return false;
@@ -94,8 +95,6 @@ bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI,
// If this is a valid register number, emit it.
if (Reg >= 0) {
AddReg(Reg);
- if (FragmentSizeInBits)
- AddOpPiece(FragmentSizeInBits, FragmentOffsetInBits);
return true;
}
@@ -108,24 +107,15 @@ bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI,
unsigned Size = TRI.getSubRegIdxSize(Idx);
unsigned RegOffset = TRI.getSubRegIdxOffset(Idx);
AddReg(Reg, "super-register");
- if (FragmentOffsetInBits == RegOffset) {
- AddOpPiece(Size, RegOffset);
- } else {
- // If this is part of a variable in a sub-register at a non-zero offset,
- // we need to manually shift the value into place, since the
- // DW_OP_LLVM_fragment describes the part of the variable, not the
- // position of the subregister.
- if (RegOffset)
- AddShr(RegOffset);
- AddOpPiece(Size, FragmentOffsetInBits);
- }
+ // Use a DW_OP_bit_piece to describe the sub-register.
+ setSubRegisterPiece(Size, RegOffset);
return true;
}
}
// Otherwise, attempt to find a covering set of sub-register numbers.
// For example, Q0 on ARM is a composition of D0+D1.
- unsigned CurPos = FragmentOffsetInBits;
+ unsigned CurPos = 0;
// The size of the register in bits, assuming 8 bits per byte.
unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->getSize() * 8;
// Keep track of the bits in the register we already emitted, so we
@@ -147,7 +137,10 @@ bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI,
// its range, emit a DWARF piece for it.
if (Reg >= 0 && Intersection.any()) {
AddReg(Reg, "sub-register");
- AddOpPiece(Size, Offset == CurPos ? 0 : Offset);
+ // Emit a piece for the any gap in the coverage.
+ if (Offset > CurPos)
+ AddOpPiece(Offset - CurPos);
+ AddOpPiece(Size);
CurPos = Offset + Size;
// Mark it as emitted.
@@ -155,7 +148,7 @@ bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI,
}
}
- return CurPos > FragmentOffsetInBits;
+ return CurPos;
}
void DwarfExpression::AddStackValue() {
@@ -191,35 +184,21 @@ void DwarfExpression::AddUnsignedConstant(const APInt &Value) {
}
}
-static unsigned getOffsetOrZero(unsigned OffsetInBits,
- unsigned FragmentOffsetInBits) {
- if (OffsetInBits == FragmentOffsetInBits)
- return 0;
- assert(OffsetInBits >= FragmentOffsetInBits && "overlapping fragments");
- return OffsetInBits;
-}
-
bool DwarfExpression::AddMachineRegExpression(const TargetRegisterInfo &TRI,
DIExpressionCursor &ExprCursor,
unsigned MachineReg,
unsigned FragmentOffsetInBits) {
if (!ExprCursor)
- return AddMachineRegFragment(TRI, MachineReg);
+ return AddMachineReg(TRI, MachineReg);
// Pattern-match combinations for which more efficient representations exist
// first.
bool ValidReg = false;
auto Op = ExprCursor.peek();
switch (Op->getOp()) {
- case dwarf::DW_OP_LLVM_fragment: {
- unsigned OffsetInBits = Op->getArg(0);
- unsigned SizeInBits = Op->getArg(1);
- // Piece always comes at the end of the expression.
- AddMachineRegFragment(TRI, MachineReg, SizeInBits,
- getOffsetOrZero(OffsetInBits, FragmentOffsetInBits));
- ExprCursor.take();
+ default:
+ ValidReg = AddMachineReg(TRI, MachineReg);
break;
- }
case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus: {
// [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset].
@@ -231,7 +210,7 @@ bool DwarfExpression::AddMachineRegExpression(const TargetRegisterInfo &TRI,
TRI, MachineReg, Op->getOp() == dwarf::DW_OP_plus ? Offset : -Offset);
ExprCursor.consume(2);
} else
- ValidReg = AddMachineRegFragment(TRI, MachineReg);
+ ValidReg = AddMachineReg(TRI, MachineReg);
break;
}
case dwarf::DW_OP_deref:
@@ -250,10 +229,25 @@ void DwarfExpression::AddExpression(DIExpressionCursor &&ExprCursor,
auto Op = ExprCursor.take();
switch (Op->getOp()) {
case dwarf::DW_OP_LLVM_fragment: {
- unsigned OffsetInBits = Op->getArg(0);
- unsigned SizeInBits = Op->getArg(1);
- AddOpPiece(SizeInBits,
- getOffsetOrZero(OffsetInBits, FragmentOffsetInBits));
+ unsigned SizeInBits = Op->getArg(1);
+ unsigned FragmentOffset = Op->getArg(0);
+ // The fragment offset must have already been adjusted by emitting an
+ // empty DW_OP_piece / DW_OP_bit_piece before we emitted the base
+ // location.
+ assert(OffsetInBits >= FragmentOffset && "fragment offset not added?");
+
+ // If \a AddMachineReg already emitted DW_OP_piece operations to represent
+ // a super-register by splicing together sub-registers, subtract the size
+ // of the pieces that was already emitted.
+ SizeInBits -= OffsetInBits - FragmentOffset;
+
+ // If \a AddMachineReg requested a DW_OP_bit_piece to stencil out a
+ // sub-register that is smaller than the current fragment's size, use it.
+ if (SubRegisterSizeInBits)
+ SizeInBits = std::min<unsigned>(SizeInBits, SubRegisterSizeInBits);
+
+ AddOpPiece(SizeInBits, SubRegisterOffsetInBits);
+ setSubRegisterPiece(0, 0);
break;
}
case dwarf::DW_OP_plus:
@@ -281,3 +275,20 @@ void DwarfExpression::AddExpression(DIExpressionCursor &&ExprCursor,
}
}
}
+
+void DwarfExpression::finalize() {
+ if (SubRegisterSizeInBits)
+ AddOpPiece(SubRegisterSizeInBits, SubRegisterOffsetInBits);
+}
+
+void DwarfExpression::addFragmentOffset(const DIExpression *Expr) {
+ if (!Expr || !Expr->isFragment())
+ return;
+
+ uint64_t FragmentOffset = Expr->getFragmentOffsetInBits();
+ assert(FragmentOffset >= OffsetInBits &&
+ "overlapping or duplicate fragments");
+ if (FragmentOffset > OffsetInBits)
+ AddOpPiece(FragmentOffset - OffsetInBits);
+ OffsetInBits = FragmentOffset;
+}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index b24074bc918..bebf3db42c6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -39,6 +39,9 @@ public:
End = Expr->expr_op_end();
}
+ DIExpressionCursor(ArrayRef<uint64_t> Expr)
+ : Start(Expr.begin()), End(Expr.end()) {}
+
/// Consume one operation.
Optional<DIExpression::ExprOperand> take() {
if (Start == End)
@@ -77,10 +80,26 @@ public:
class DwarfExpression {
protected:
unsigned DwarfVersion;
+ /// Current Fragment Offset in Bits.
+ uint64_t OffsetInBits = 0;
+
+ /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
+ unsigned SubRegisterSizeInBits = 0;
+ unsigned SubRegisterOffsetInBits = 0;
+
+ /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
+ /// to represent a subregister.
+ void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
+ SubRegisterSizeInBits = SizeInBits;
+ SubRegisterOffsetInBits = OffsetInBits;
+ }
public:
DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {}
- virtual ~DwarfExpression() {}
+ virtual ~DwarfExpression() {};
+
+ /// This needs to be called last to commit any pending changes.
+ void finalize();
/// Output a dwarf operand and an optional assembler comment.
virtual void EmitOp(uint8_t Op, const char *Comment = nullptr) = 0;
@@ -97,9 +116,9 @@ public:
/// Emit an (double-)indirect dwarf register operation.
void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false);
- /// Emit a DW_OP_piece operation for a variable fragment.
- /// \param OffsetInBits This is the offset where the fragment appears
- /// inside the *source variable*.
+ /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
+ /// \param OffsetInBits This is an optional offset into the location that
+ /// is at the top of the DWARF stack.
void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
/// Emit a shift-right dwarf expression.
@@ -125,10 +144,7 @@ public:
/// Emit a partial DWARF register operation.
///
- /// \param MachineReg the register,
- /// \param FragmentSizeInBits size and
- /// \param FragmentOffsetInBits offset of the fragment in bits, if this is
- /// a fragment of an aggregate value.
+ /// \param MachineReg The register number.
///
/// If size and offset is zero an operation for the entire register is
/// emitted: Some targets do not provide a DWARF register number for every
@@ -137,9 +153,7 @@ public:
/// multiple subregisters that alias the register.
///
/// \return false if no DWARF register exists for MachineReg.
- bool AddMachineRegFragment(const TargetRegisterInfo &TRI, unsigned MachineReg,
- unsigned FragmentSizeInBits = 0,
- unsigned FragmentOffsetInBits = 0);
+ bool AddMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg);
/// Emit a signed constant.
void AddSignedConstant(int64_t Value);
@@ -167,6 +181,10 @@ public:
/// fragment inside the entire variable.
void AddExpression(DIExpressionCursor &&Expr,
unsigned FragmentOffsetInBits = 0);
+
+ /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
+ /// the fragment described by \c Expr.
+ void addFragmentOffset(const DIExpression *Expr);
};
/// DwarfExpression implementation for .debug_loc entries.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 68fb5c986f9..4f90245c6d4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -371,22 +371,6 @@ void DwarfUnit::addSourceLine(DIE &Die, const DINamespace *NS) {
addSourceLine(Die, NS->getLine(), NS->getFilename(), NS->getDirectory());
}
-bool DwarfUnit::addRegisterFragment(DIELoc &TheDie, unsigned Reg,
- unsigned SizeInBits,
- unsigned OffsetInBits) {
- DIEDwarfExpression Expr(*Asm, *this, TheDie);
- Expr.AddMachineRegFragment(*Asm->MF->getSubtarget().getRegisterInfo(), Reg,
- SizeInBits, OffsetInBits);
- return true;
-}
-
-bool DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg,
- int64_t Offset) {
- DIEDwarfExpression Expr(*Asm, *this, TheDie);
- return Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
- Reg, Offset);
-}
-
/* Byref variables, in Blocks, are declared by the programmer as "SomeType
VarName;", but the compiler creates a __Block_byref_x_VarName struct, and
gives the variable VarName either the struct, or a pointer to the struct, as
@@ -479,12 +463,17 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
// Decode the original location, and use that as the start of the byref
// variable's location.
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ SmallVector<uint64_t, 6> DIExpr;
+ DIEDwarfExpression Expr(*Asm, *this, *Loc);
bool validReg;
if (Location.isReg())
- validReg = addRegisterFragment(*Loc, Location.getReg());
+ validReg = Expr.AddMachineReg(*Asm->MF->getSubtarget().getRegisterInfo(),
+ Location.getReg());
else
- validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
+ validReg =
+ Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
+ Location.getReg(), Location.getOffset());
if (!validReg)
return;
@@ -492,27 +481,29 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
// If we started with a pointer to the __Block_byref... struct, then
// the first thing we need to do is dereference the pointer (DW_OP_deref).
if (isPointer)
- addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+ DIExpr.push_back(dwarf::DW_OP_deref);
// Next add the offset for the '__forwarding' field:
// DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in
// adding the offset if it's 0.
if (forwardingFieldOffset > 0) {
- addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
- addUInt(*Loc, dwarf::DW_FORM_udata, forwardingFieldOffset);
+ DIExpr.push_back(dwarf::DW_OP_plus);
+ DIExpr.push_back(forwardingFieldOffset);
}
// Now dereference the __forwarding field to get to the real __Block_byref
// struct: DW_OP_deref.
- addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+ DIExpr.push_back(dwarf::DW_OP_deref);
// Now that we've got the real __Block_byref... struct, add the offset
// for the variable's field to get to the location of the actual variable:
// DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0.
if (varFieldOffset > 0) {
- addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
- addUInt(*Loc, dwarf::DW_FORM_udata, varFieldOffset);
+ DIExpr.push_back(dwarf::DW_OP_plus);
+ DIExpr.push_back(varFieldOffset);
}
+ Expr.AddExpression(makeArrayRef(DIExpr));
+ Expr.finalize();
// Now attach the location information to the DIE.
addBlock(Die, Attribute, Loc);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index ed975cc80e1..8654d6f0caf 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -235,19 +235,6 @@ public:
/// Add template parameters in buffer.
void addTemplateParams(DIE &Buffer, DINodeArray TParams);
- /// Add register operand for a source variable fragment of the specified size
- /// and offset.
- ///
- /// \returns false if the register does not exist, e.g., because it was never
- /// materialized.
- bool addRegisterFragment(DIELoc &TheDie, unsigned Reg,
- unsigned SizeInBits = 0, unsigned OffsetInBits = 0);
-
- /// Add register offset.
- /// \returns false if the register does not exist, e.g., because it was never
- /// materialized.
- bool addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset);
-
// FIXME: Should be reformulated in terms of addComplexAddress.
/// Start with the address based on the location provided, and generate the
/// DWARF information necessary to find the actual Block variable (navigating
OpenPOWER on IntegriCloud