llvm.org GIT mirror llvm / 57ed5ff
Debug Info: Move the complex expression handling (=the remainder) of emitDebugLocValue() into DwarfExpression. Ought to be NFC, but it actually uncovered a bug in the debug-loc-asan.ll testcase. The testcase checks that the address of variable "y" is stored at [RSP+16], which also lines up with the comment. It also check(ed) that the *value* of "y" is stored in RDI before that, but that is actually incorrect, since RDI is the very value that is stored in [RSP+16]. Here's the assembler output: movb 2147450880(%rcx), %r8b #DEBUG_VALUE: bar:y <- RDI cmpb $0, %r8b movq %rax, 32(%rsp) # 8-byte Spill movq %rsi, 24(%rsp) # 8-byte Spill movq %rdi, 16(%rsp) # 8-byte Spill .Ltmp3: #DEBUG_VALUE: bar:y <- [RSP+16] Fixed the comment to spell out the correct register and the check to expect an address rather than a value. Note that the range that is emitted for the RDI location was and is still wrong, it claims to begin at the function prologue, but really it should start where RDI is first assigned. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225851 91177308-0d34-0410-b5e6-96231b3b80d8 Adrian Prantl 4 years ago
5 changed file(s) with 97 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
16901690 assert(PieceSize*SizeOfByte != VarSize
16911691 && "piece covers entire variable");
16921692 #endif
1693 if (Piece.isLocation() && Piece.getLoc().isReg())
1694 Asm->EmitDwarfRegOpPiece(Streamer,
1695 Piece.getLoc(),
1696 PieceSize*SizeOfByte);
1697 else {
1698 emitDebugLocValue(Streamer, Piece);
1699 Asm->EmitDwarfOpPiece(Streamer, PieceSize*SizeOfByte);
1700 }
1693
1694 emitDebugLocValue(Streamer, Piece, PieceOffset*SizeOfByte);
17011695 }
17021696 }
17031697
17141708 }
17151709
17161710 void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer,
1717 const DebugLocEntry::Value &Value) {
1711 const DebugLocEntry::Value &Value,
1712 unsigned PieceOffsetInBits) {
17181713 DIVariable DV = Value.getVariable();
1719 DebugLocDwarfExpression Expr(*Asm, Streamer);
1714 DebugLocDwarfExpression DwarfExpr(*Asm, Streamer);
1715
17201716 // Regular entry.
17211717 if (Value.isInt()) {
17221718 DIBasicType BTy(resolve(DV.getType()));
17231719 if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
17241720 BTy.getEncoding() == dwarf::DW_ATE_signed_char))
1725 Expr.AddSignedConstant(Value.getInt());
1721 DwarfExpr.AddSignedConstant(Value.getInt());
17261722 else
1727 Expr.AddUnsignedConstant(Value.getInt());
1723 DwarfExpr.AddUnsignedConstant(Value.getInt());
17281724 } else if (Value.isLocation()) {
17291725 MachineLocation Loc = Value.getLoc();
17301726 DIExpression Expr = Value.getExpression();
1731 if (!Expr)
1727 if (!Expr || (Expr.getNumElements() == 0))
17321728 // Regular entry.
17331729 Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
17341730 else {
17351731 // Complex address entry.
1736 unsigned N = Expr.getNumElements();
1737 unsigned i = 0;
1738 if (N >= 2 && Expr.getElement(0) == dwarf::DW_OP_plus) {
1739 if (Loc.getOffset()) {
1740 i = 2;
1741 Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
1742 Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
1743 Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst");
1744 Streamer.EmitSLEB128(Expr.getElement(1));
1745 } else {
1746 // If first address element is OpPlus then emit
1747 // DW_OP_breg + Offset instead of DW_OP_reg + Offset.
1748 MachineLocation TLoc(Loc.getReg(), Expr.getElement(1));
1749 Asm->EmitDwarfRegOp(Streamer, TLoc, DV.isIndirect());
1750 i = 2;
1751 }
1752 } else {
1753 Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
1754 }
1755
1756 // Emit remaining complex address elements.
1757 for (; i < N; ++i) {
1758 uint64_t Element = Expr.getElement(i);
1759 if (Element == dwarf::DW_OP_plus) {
1760 Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst");
1761 Streamer.EmitULEB128(Expr.getElement(++i));
1762 } else if (Element == dwarf::DW_OP_deref) {
1763 if (!Loc.isReg())
1764 Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
1765 } else if (Element == dwarf::DW_OP_piece) {
1766 i += 3;
1767 // handled in emitDebugLocEntry.
1768 } else
1769 llvm_unreachable("unknown Opcode found in complex address");
1770 }
1732 if (Loc.getOffset()) {
1733 DwarfExpr.AddMachineRegIndirect(Loc.getReg(), Loc.getOffset());
1734 DwarfExpr.AddExpression(Expr, PieceOffsetInBits);
1735 } else
1736 DwarfExpr.AddMachineRegExpression(Expr, Loc.getReg(),
1737 PieceOffsetInBits);
1738 if (DV.isIndirect())
1739 DwarfExpr.EmitOp(dwarf::DW_OP_deref);
17711740 }
17721741 }
17731742 // else ... ignore constant fp. There is not any good way to
564564 void emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry);
565565 /// \brief emit a single value for the debug loc section.
566566 void emitDebugLocValue(ByteStreamer &Streamer,
567 const DebugLocEntry::Value &Value);
567 const DebugLocEntry::Value &Value,
568 unsigned PieceOffsetInBits = 0);
568569 /// Emits an optimal (=sorted) sequence of DW_OP_pieces.
569570 void emitLocPieces(ByteStreamer &Streamer,
570571 const DITypeIdentifierMap &Map,
190190 if (getDwarfVersion() >= 4)
191191 EmitOp(dwarf::DW_OP_stack_value);
192192 }
193
194 static unsigned getOffsetOrZero(unsigned OffsetInBits,
195 unsigned PieceOffsetInBits) {
196 if (OffsetInBits == PieceOffsetInBits)
197 return 0;
198 assert(OffsetInBits >= PieceOffsetInBits && "overlapping pieces");
199 return OffsetInBits;
200 }
201
202 void DwarfExpression::AddMachineRegExpression(DIExpression Expr,
203 unsigned MachineReg,
204 unsigned PieceOffsetInBits) {
205 unsigned N = Expr.getNumElements();
206 unsigned I = 0;
207 // Pattern-match combinations for which more efficient representations exist
208 // first.
209 if (N >= 3 && Expr.getElement(0) == dwarf::DW_OP_piece) {
210 unsigned SizeOfByte = 8;
211 unsigned OffsetInBits = Expr.getElement(1) * SizeOfByte;
212 unsigned SizeInBits = Expr.getElement(2) * SizeOfByte;
213 AddMachineRegPiece(MachineReg, SizeInBits,
214 getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
215 I = 3;
216 } else if (N >= 3 && Expr.getElement(0) == dwarf::DW_OP_plus &&
217 Expr.getElement(2) == dwarf::DW_OP_deref) {
218 // [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] --> [DW_OP_breg,Offset].
219 unsigned Offset = Expr.getElement(1);
220 AddMachineRegIndirect(MachineReg, Offset);
221 I = 3;
222 } else if (N >= 1 && Expr.getElement(0) == dwarf::DW_OP_deref) {
223 // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
224 AddMachineRegIndirect(MachineReg);
225 I = 1;
226 } else
227 AddMachineRegPiece(MachineReg);
228
229 // Emit remaining elements of the expression.
230 AddExpression(Expr, I);
231 }
232
233 void DwarfExpression::AddExpression(DIExpression Expr, unsigned I,
234 unsigned PieceOffsetInBits) {
235 unsigned N = Expr.getNumElements();
236 for (; I < N; ++I) {
237 switch (Expr.getElement(I)) {
238 case dwarf::DW_OP_piece: {
239 unsigned SizeOfByte = 8;
240 unsigned OffsetInBits = Expr.getElement(++I) * SizeOfByte;
241 unsigned SizeInBits = Expr.getElement(++I) * SizeOfByte;
242 AddOpPiece(SizeInBits, getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
243 break;
244 }
245 case dwarf::DW_OP_plus:
246 EmitOp(dwarf::DW_OP_plus_uconst);
247 EmitUnsigned(Expr.getElement(++I));
248 break;
249 case dwarf::DW_OP_deref:
250 EmitOp(dwarf::DW_OP_deref);
251 break;
252 default:
253 llvm_unreachable("unhandled opcode found in DIExpression");
254 }
255 }
256 }
1414 #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
1515
1616 #include "llvm/Support/DataTypes.h"
17 #include "llvm/IR/DebugInfo.h"
1718
1819 namespace llvm {
1920
8081 void AddSignedConstant(int Value);
8182 /// Emit an unsigned constant.
8283 void AddUnsignedConstant(unsigned Value);
84
85 /// Emit an entire DIExpression on top of a machine register location.
86 /// \param PieceOffsetInBits If this is one piece out of a fragmented
87 /// location, this is the offset of the piece inside the entire variable.
88 void AddMachineRegExpression(DIExpression Expr, unsigned MachineReg,
89 unsigned PieceOffsetInBits = 0);
90 /// Emit a the operations in a DIExpression, starting from element I.
91 /// \param PieceOffsetInBits If this is one piece out of a fragmented
92 /// location, this is the offset of the piece inside the entire variable.
93 void AddExpression(DIExpression Expr, unsigned PieceOffsetInBits = 0,
94 unsigned I = 0);
8395 };
84
8596
8697 /// DwarfExpression implementation for .debug_loc entries.
8798 class DebugLocDwarfExpression : public DwarfExpression {
2020 ; CHECK: .Ldebug_loc{{[0-9]+}}:
2121 ; We expect two location ranges for the variable.
2222
23 ; First, it is stored in %rdx:
23 ; First, its address is stored in %rdi:
2424 ; CHECK: .quad .Lfunc_begin0-.Lfunc_begin0
2525 ; CHECK-NEXT: .quad [[START_LABEL]]-.Lfunc_begin0
26 ; CHECK: DW_OP_reg5
26 ; CHECK: DW_OP_breg5
2727
2828 ; Then it's addressed via %rsp:
2929 ; CHECK: .quad [[START_LABEL]]-.Lfunc_begin0