diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 65 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp | 64 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h | 13 | ||||
-rw-r--r-- | llvm/test/DebugInfo/X86/debug-loc-asan.ll | 4 |
5 files changed, 97 insertions, 52 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 1738dce3c4c..3b719b8b961 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1691,14 +1691,8 @@ void DwarfDebug::emitLocPieces(ByteStreamer &Streamer, assert(PieceSize*SizeOfByte != VarSize && "piece covers entire variable"); #endif - if (Piece.isLocation() && Piece.getLoc().isReg()) - Asm->EmitDwarfRegOpPiece(Streamer, - Piece.getLoc(), - PieceSize*SizeOfByte); - else { - emitDebugLocValue(Streamer, Piece); - Asm->EmitDwarfOpPiece(Streamer, PieceSize*SizeOfByte); - } + + emitDebugLocValue(Streamer, Piece, PieceOffset*SizeOfByte); } } @@ -1715,60 +1709,35 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, } void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer, - const DebugLocEntry::Value &Value) { + const DebugLocEntry::Value &Value, + unsigned PieceOffsetInBits) { DIVariable DV = Value.getVariable(); - DebugLocDwarfExpression Expr(*Asm, Streamer); + DebugLocDwarfExpression DwarfExpr(*Asm, Streamer); + // Regular entry. if (Value.isInt()) { DIBasicType BTy(resolve(DV.getType())); if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) - Expr.AddSignedConstant(Value.getInt()); + DwarfExpr.AddSignedConstant(Value.getInt()); else - Expr.AddUnsignedConstant(Value.getInt()); + DwarfExpr.AddUnsignedConstant(Value.getInt()); } else if (Value.isLocation()) { MachineLocation Loc = Value.getLoc(); DIExpression Expr = Value.getExpression(); - if (!Expr) + if (!Expr || (Expr.getNumElements() == 0)) // Regular entry. Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); else { // Complex address entry. - unsigned N = Expr.getNumElements(); - unsigned i = 0; - if (N >= 2 && Expr.getElement(0) == dwarf::DW_OP_plus) { - if (Loc.getOffset()) { - i = 2; - Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); - Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); - Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); - Streamer.EmitSLEB128(Expr.getElement(1)); - } else { - // If first address element is OpPlus then emit - // DW_OP_breg + Offset instead of DW_OP_reg + Offset. - MachineLocation TLoc(Loc.getReg(), Expr.getElement(1)); - Asm->EmitDwarfRegOp(Streamer, TLoc, DV.isIndirect()); - i = 2; - } - } else { - Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); - } - - // Emit remaining complex address elements. - for (; i < N; ++i) { - uint64_t Element = Expr.getElement(i); - if (Element == dwarf::DW_OP_plus) { - Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); - Streamer.EmitULEB128(Expr.getElement(++i)); - } else if (Element == dwarf::DW_OP_deref) { - if (!Loc.isReg()) - Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); - } else if (Element == dwarf::DW_OP_piece) { - i += 3; - // handled in emitDebugLocEntry. - } else - llvm_unreachable("unknown Opcode found in complex address"); - } + if (Loc.getOffset()) { + DwarfExpr.AddMachineRegIndirect(Loc.getReg(), Loc.getOffset()); + DwarfExpr.AddExpression(Expr, PieceOffsetInBits); + } else + DwarfExpr.AddMachineRegExpression(Expr, Loc.getReg(), + PieceOffsetInBits); + if (DV.isIndirect()) + DwarfExpr.EmitOp(dwarf::DW_OP_deref); } } // else ... ignore constant fp. There is not any good way to diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index d2dab370ec0..5d1fbb5a7a9 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -565,7 +565,8 @@ public: void emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry); /// \brief emit a single value for the debug loc section. void emitDebugLocValue(ByteStreamer &Streamer, - const DebugLocEntry::Value &Value); + const DebugLocEntry::Value &Value, + unsigned PieceOffsetInBits = 0); /// Emits an optimal (=sorted) sequence of DW_OP_pieces. void emitLocPieces(ByteStreamer &Streamer, const DITypeIdentifierMap &Map, diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index a3cd000b871..4c16ae70d1f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -191,3 +191,67 @@ void DwarfExpression::AddUnsignedConstant(unsigned Value) { if (getDwarfVersion() >= 4) EmitOp(dwarf::DW_OP_stack_value); } + +static unsigned getOffsetOrZero(unsigned OffsetInBits, + unsigned PieceOffsetInBits) { + if (OffsetInBits == PieceOffsetInBits) + return 0; + assert(OffsetInBits >= PieceOffsetInBits && "overlapping pieces"); + return OffsetInBits; +} + +void DwarfExpression::AddMachineRegExpression(DIExpression Expr, + unsigned MachineReg, + unsigned PieceOffsetInBits) { + unsigned N = Expr.getNumElements(); + unsigned I = 0; + // Pattern-match combinations for which more efficient representations exist + // first. + if (N >= 3 && Expr.getElement(0) == dwarf::DW_OP_piece) { + unsigned SizeOfByte = 8; + unsigned OffsetInBits = Expr.getElement(1) * SizeOfByte; + unsigned SizeInBits = Expr.getElement(2) * SizeOfByte; + AddMachineRegPiece(MachineReg, SizeInBits, + getOffsetOrZero(OffsetInBits, PieceOffsetInBits)); + I = 3; + } else if (N >= 3 && Expr.getElement(0) == dwarf::DW_OP_plus && + Expr.getElement(2) == dwarf::DW_OP_deref) { + // [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] --> [DW_OP_breg,Offset]. + unsigned Offset = Expr.getElement(1); + AddMachineRegIndirect(MachineReg, Offset); + I = 3; + } else if (N >= 1 && Expr.getElement(0) == dwarf::DW_OP_deref) { + // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg]. + AddMachineRegIndirect(MachineReg); + I = 1; + } else + AddMachineRegPiece(MachineReg); + + // Emit remaining elements of the expression. + AddExpression(Expr, I); +} + +void DwarfExpression::AddExpression(DIExpression Expr, unsigned I, + unsigned PieceOffsetInBits) { + unsigned N = Expr.getNumElements(); + for (; I < N; ++I) { + switch (Expr.getElement(I)) { + case dwarf::DW_OP_piece: { + unsigned SizeOfByte = 8; + unsigned OffsetInBits = Expr.getElement(++I) * SizeOfByte; + unsigned SizeInBits = Expr.getElement(++I) * SizeOfByte; + AddOpPiece(SizeInBits, getOffsetOrZero(OffsetInBits, PieceOffsetInBits)); + break; + } + case dwarf::DW_OP_plus: + EmitOp(dwarf::DW_OP_plus_uconst); + EmitUnsigned(Expr.getElement(++I)); + break; + case dwarf::DW_OP_deref: + EmitOp(dwarf::DW_OP_deref); + break; + default: + llvm_unreachable("unhandled opcode found in DIExpression"); + } + } +} diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h index 870b9716039..f164f1c8513 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -15,6 +15,7 @@ #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H #include "llvm/Support/DataTypes.h" +#include "llvm/IR/DebugInfo.h" namespace llvm { @@ -81,8 +82,18 @@ public: void AddSignedConstant(int Value); /// Emit an unsigned constant. void AddUnsignedConstant(unsigned Value); -}; + /// Emit an entire DIExpression on top of a machine register location. + /// \param PieceOffsetInBits If this is one piece out of a fragmented + /// location, this is the offset of the piece inside the entire variable. + void AddMachineRegExpression(DIExpression Expr, unsigned MachineReg, + unsigned PieceOffsetInBits = 0); + /// Emit a the operations in a DIExpression, starting from element I. + /// \param PieceOffsetInBits If this is one piece out of a fragmented + /// location, this is the offset of the piece inside the entire variable. + void AddExpression(DIExpression Expr, unsigned PieceOffsetInBits = 0, + unsigned I = 0); +}; /// DwarfExpression implementation for .debug_loc entries. class DebugLocDwarfExpression : public DwarfExpression { diff --git a/llvm/test/DebugInfo/X86/debug-loc-asan.ll b/llvm/test/DebugInfo/X86/debug-loc-asan.ll index f288343c272..0e7ebca7a38 100644 --- a/llvm/test/DebugInfo/X86/debug-loc-asan.ll +++ b/llvm/test/DebugInfo/X86/debug-loc-asan.ll @@ -21,10 +21,10 @@ ; CHECK: .Ldebug_loc{{[0-9]+}}: ; We expect two location ranges for the variable. -; First, it is stored in %rdx: +; First, its address is stored in %rdi: ; CHECK: .quad .Lfunc_begin0-.Lfunc_begin0 ; CHECK-NEXT: .quad [[START_LABEL]]-.Lfunc_begin0 -; CHECK: DW_OP_reg5 +; CHECK: DW_OP_breg5 ; Then it's addressed via %rsp: ; CHECK: .quad [[START_LABEL]]-.Lfunc_begin0 |