2015-01-13 06:19:22 +08:00
|
|
|
//===-- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ---*- C++ -*--===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains support for writing dwarf compile unit.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
|
|
|
|
#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
|
|
|
|
|
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.
llvm-svn: 225851
2015-01-14 07:39:11 +08:00
|
|
|
#include "llvm/IR/DebugInfo.h"
|
2015-01-14 19:23:27 +08:00
|
|
|
#include "llvm/Support/DataTypes.h"
|
2015-01-13 06:19:22 +08:00
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
2015-01-13 07:36:56 +08:00
|
|
|
class AsmPrinter;
|
2015-01-13 08:04:06 +08:00
|
|
|
class ByteStreamer;
|
2015-01-13 07:36:56 +08:00
|
|
|
class TargetRegisterInfo;
|
2015-01-14 09:01:22 +08:00
|
|
|
class DwarfUnit;
|
|
|
|
class DIELoc;
|
2015-01-13 06:19:22 +08:00
|
|
|
|
2016-11-03 00:12:20 +08:00
|
|
|
/// Holds a DIExpression and keeps track of how many operands have been consumed
|
|
|
|
/// so far.
|
|
|
|
class DIExpressionCursor {
|
|
|
|
DIExpression::expr_op_iterator Start, End;
|
|
|
|
public:
|
|
|
|
DIExpressionCursor(const DIExpression *Expr) {
|
|
|
|
if (!Expr) {
|
|
|
|
assert(Start == End);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Start = Expr->expr_op_begin();
|
|
|
|
End = Expr->expr_op_end();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consume one operation.
|
|
|
|
Optional<DIExpression::ExprOperand> take() {
|
|
|
|
if (Start == End)
|
|
|
|
return None;
|
|
|
|
return *(Start++);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consume N operations.
|
|
|
|
void consume(unsigned N) { std::advance(Start, N); }
|
|
|
|
|
|
|
|
/// Return the current operation.
|
|
|
|
Optional<DIExpression::ExprOperand> peek() const {
|
|
|
|
if (Start == End)
|
|
|
|
return None;
|
|
|
|
return *(Start);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the next operation.
|
|
|
|
Optional<DIExpression::ExprOperand> peekNext() const {
|
|
|
|
if (Start == End)
|
|
|
|
return None;
|
|
|
|
|
|
|
|
auto Next = Start.getNext();
|
|
|
|
if (Next == End)
|
|
|
|
return None;
|
|
|
|
|
|
|
|
return *Next;
|
|
|
|
}
|
2016-11-03 00:20:37 +08:00
|
|
|
/// Determine whether there are any operations left in this expression.
|
2016-11-03 00:12:20 +08:00
|
|
|
operator bool() const { return Start != End; }
|
|
|
|
};
|
|
|
|
|
2015-01-13 06:19:22 +08:00
|
|
|
/// Base class containing the logic for constructing DWARF expressions
|
|
|
|
/// independently of whether they are emitted into a DIE or into a .debug_loc
|
|
|
|
/// entry.
|
|
|
|
class DwarfExpression {
|
2015-01-13 06:19:26 +08:00
|
|
|
protected:
|
2015-01-13 07:36:56 +08:00
|
|
|
// Various convenience accessors that extract things out of AsmPrinter.
|
2015-03-03 06:02:33 +08:00
|
|
|
unsigned DwarfVersion;
|
2015-01-13 07:36:56 +08:00
|
|
|
|
2015-01-13 06:19:22 +08:00
|
|
|
public:
|
2016-05-21 03:35:17 +08:00
|
|
|
DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {}
|
2015-01-13 07:36:50 +08:00
|
|
|
virtual ~DwarfExpression() {}
|
2015-01-13 06:19:22 +08:00
|
|
|
|
2015-01-14 07:11:07 +08:00
|
|
|
/// Output a dwarf operand and an optional assembler comment.
|
|
|
|
virtual void EmitOp(uint8_t Op, const char *Comment = nullptr) = 0;
|
|
|
|
/// Emit a raw signed value.
|
2015-03-11 03:23:37 +08:00
|
|
|
virtual void EmitSigned(int64_t Value) = 0;
|
2015-01-14 07:11:07 +08:00
|
|
|
/// Emit a raw unsigned value.
|
2015-03-11 03:23:37 +08:00
|
|
|
virtual void EmitUnsigned(uint64_t Value) = 0;
|
2015-01-14 07:11:07 +08:00
|
|
|
/// Return whether the given machine register is the frame register in the
|
|
|
|
/// current function.
|
2016-05-21 03:35:17 +08:00
|
|
|
virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0;
|
2015-01-13 06:19:26 +08:00
|
|
|
|
2015-01-13 06:19:22 +08:00
|
|
|
/// Emit a dwarf register operation.
|
2015-01-14 07:11:07 +08:00
|
|
|
void AddReg(int DwarfReg, const char *Comment = nullptr);
|
2015-01-13 06:19:22 +08:00
|
|
|
/// Emit an (double-)indirect dwarf register operation.
|
|
|
|
void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false);
|
|
|
|
|
2016-11-03 00:20:37 +08:00
|
|
|
/// Emit DW_OP_piece operation.
|
2015-01-13 06:19:22 +08:00
|
|
|
void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
|
|
|
|
/// Emit a shift-right dwarf expression.
|
|
|
|
void AddShr(unsigned ShiftBy);
|
2016-04-08 08:38:37 +08:00
|
|
|
/// Emit a DW_OP_stack_value, if supported.
|
|
|
|
///
|
2016-11-03 00:20:37 +08:00
|
|
|
/// The proper way to describe a constant value is DW_OP_constu <const>,
|
|
|
|
/// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available
|
|
|
|
/// until DWARF 4, so we will continue to generate DW_OP_constu <const> for
|
|
|
|
/// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const
|
|
|
|
/// <const> actually describes a value at a constant addess, not a constant
|
|
|
|
/// value. However, in the past there was no better way to describe a
|
|
|
|
/// constant 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.
|
2016-04-08 08:38:37 +08:00
|
|
|
void AddStackValue();
|
2015-01-13 06:19:22 +08:00
|
|
|
|
2015-01-13 06:19:26 +08:00
|
|
|
/// Emit an indirect dwarf register operation for the given machine register.
|
2015-01-14 09:01:28 +08:00
|
|
|
/// \return false if no DWARF register exists for MachineReg.
|
2016-05-21 03:35:17 +08:00
|
|
|
bool AddMachineRegIndirect(const TargetRegisterInfo &TRI, unsigned MachineReg,
|
|
|
|
int Offset = 0);
|
2015-01-13 06:19:26 +08:00
|
|
|
|
2016-11-03 00:12:20 +08:00
|
|
|
/// Emit a partial DWARF register operation.
|
2015-01-14 07:11:07 +08:00
|
|
|
/// \param MachineReg the register
|
|
|
|
/// \param PieceSizeInBits size and
|
|
|
|
/// \param PieceOffsetInBits offset of the piece in bits, if this is one
|
|
|
|
/// piece of an aggregate value.
|
2015-01-13 06:19:22 +08:00
|
|
|
///
|
|
|
|
/// 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 register. If this is the case, this
|
|
|
|
/// function will attempt to emit a DWARF register by emitting a
|
|
|
|
/// piece of a super-register or by piecing together multiple
|
|
|
|
/// subregisters that alias the register.
|
2015-01-14 09:01:28 +08:00
|
|
|
///
|
|
|
|
/// \return false if no DWARF register exists for MachineReg.
|
2016-05-21 03:35:17 +08:00
|
|
|
bool AddMachineRegPiece(const TargetRegisterInfo &TRI, unsigned MachineReg,
|
|
|
|
unsigned PieceSizeInBits = 0,
|
2015-01-13 06:19:22 +08:00
|
|
|
unsigned PieceOffsetInBits = 0);
|
2015-01-13 08:04:06 +08:00
|
|
|
|
|
|
|
/// Emit a signed constant.
|
2016-06-25 05:35:09 +08:00
|
|
|
void AddSignedConstant(int64_t Value);
|
2015-01-13 08:04:06 +08:00
|
|
|
/// Emit an unsigned constant.
|
2016-06-25 05:35:09 +08:00
|
|
|
void AddUnsignedConstant(uint64_t Value);
|
2016-04-08 08:38:37 +08:00
|
|
|
/// Emit an unsigned constant.
|
2016-06-09 03:09:22 +08:00
|
|
|
void AddUnsignedConstant(const APInt &Value);
|
2015-01-13 08:04:06 +08:00
|
|
|
|
2016-11-03 00:20:37 +08:00
|
|
|
/// Emit a machine register location. As an optimization this may also consume
|
|
|
|
/// the prefix of a DwarfExpression if a more efficient representation for
|
|
|
|
/// combining the register location and the first operation exists.
|
2015-04-22 02:44:06 +08:00
|
|
|
///
|
2016-11-03 00:12:20 +08:00
|
|
|
/// \param PieceOffsetInBits If this is one piece out of a fragmented
|
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.
llvm-svn: 225851
2015-01-14 07:39:11 +08:00
|
|
|
/// location, this is the offset of the piece inside the entire variable.
|
2015-01-14 09:01:28 +08:00
|
|
|
/// \return false if no DWARF register exists for MachineReg.
|
2016-05-21 03:35:17 +08:00
|
|
|
bool AddMachineRegExpression(const TargetRegisterInfo &TRI,
|
2016-11-03 00:12:20 +08:00
|
|
|
DIExpressionCursor &Expr, unsigned MachineReg,
|
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.
llvm-svn: 225851
2015-01-14 07:39:11 +08:00
|
|
|
unsigned PieceOffsetInBits = 0);
|
2016-11-03 00:12:20 +08:00
|
|
|
/// Emit all remaining operations in the DIExpressionCursor.
|
|
|
|
/// \param PieceOffsetInBits If this is one piece out of a fragmented
|
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.
llvm-svn: 225851
2015-01-14 07:39:11 +08:00
|
|
|
/// location, this is the offset of the piece inside the entire variable.
|
2016-11-03 00:12:20 +08:00
|
|
|
void AddExpression(DIExpressionCursor &&Expr,
|
2015-02-18 06:30:56 +08:00
|
|
|
unsigned PieceOffsetInBits = 0);
|
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.
llvm-svn: 225851
2015-01-14 07:39:11 +08:00
|
|
|
};
|
2015-01-13 08:04:06 +08:00
|
|
|
|
|
|
|
/// DwarfExpression implementation for .debug_loc entries.
|
|
|
|
class DebugLocDwarfExpression : public DwarfExpression {
|
|
|
|
ByteStreamer &BS;
|
|
|
|
|
|
|
|
public:
|
2016-05-21 03:35:17 +08:00
|
|
|
DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS)
|
|
|
|
: DwarfExpression(DwarfVersion), BS(BS) {}
|
2015-01-13 08:04:06 +08:00
|
|
|
|
2015-01-14 07:11:07 +08:00
|
|
|
void EmitOp(uint8_t Op, const char *Comment = nullptr) override;
|
2015-03-11 03:23:37 +08:00
|
|
|
void EmitSigned(int64_t Value) override;
|
|
|
|
void EmitUnsigned(uint64_t Value) override;
|
2016-05-21 03:35:17 +08:00
|
|
|
bool isFrameRegister(const TargetRegisterInfo &TRI,
|
|
|
|
unsigned MachineReg) override;
|
2015-01-13 06:19:22 +08:00
|
|
|
};
|
2015-01-14 09:01:22 +08:00
|
|
|
|
|
|
|
/// DwarfExpression implementation for singular DW_AT_location.
|
|
|
|
class DIEDwarfExpression : public DwarfExpression {
|
2015-03-03 06:02:33 +08:00
|
|
|
const AsmPrinter &AP;
|
2015-01-14 09:01:22 +08:00
|
|
|
DwarfUnit &DU;
|
|
|
|
DIELoc &DIE;
|
|
|
|
|
|
|
|
public:
|
2015-03-03 06:02:33 +08:00
|
|
|
DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE);
|
2015-01-14 09:01:22 +08:00
|
|
|
void EmitOp(uint8_t Op, const char *Comment = nullptr) override;
|
2015-03-11 03:23:37 +08:00
|
|
|
void EmitSigned(int64_t Value) override;
|
|
|
|
void EmitUnsigned(uint64_t Value) override;
|
2016-05-21 03:35:17 +08:00
|
|
|
bool isFrameRegister(const TargetRegisterInfo &TRI,
|
|
|
|
unsigned MachineReg) override;
|
2015-01-14 09:01:22 +08:00
|
|
|
};
|
2015-06-23 17:49:53 +08:00
|
|
|
}
|
2015-01-13 06:19:22 +08:00
|
|
|
|
|
|
|
#endif
|