27#define DEBUG_TYPE "dwarfdebug"
32 else if (
Value == std::numeric_limits<uint64_t>::max()) {
38 emitOp(dwarf::DW_OP_constu);
44 assert(DwarfReg >= 0 &&
"invalid negative dwarf register number");
46 "location description already locked down");
49 emitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
51 emitOp(dwarf::DW_OP_regx, Comment);
57 assert(DwarfReg >= 0 &&
"invalid negative dwarf register number");
60 emitOp(dwarf::DW_OP_breg0 + DwarfReg);
62 emitOp(dwarf::DW_OP_bregx);
69 emitOp(dwarf::DW_OP_fbreg);
77 const unsigned SizeOfByte = 8;
79 emitOp(dwarf::DW_OP_bit_piece);
83 emitOp(dwarf::DW_OP_piece);
84 unsigned ByteSize = SizeInBits / SizeOfByte;
87 this->OffsetInBits += SizeInBits;
111 int Reg =
TRI.getDwarfRegNum(MachineReg,
false);
122 Reg =
TRI.getDwarfRegNum(SR,
false);
124 unsigned Idx =
TRI.getSubRegIndex(SR, MachineReg);
126 unsigned RegOffset =
TRI.getSubRegIdxOffset(
Idx);
147 unsigned Idx =
TRI.getSubRegIndex(MachineReg, SR);
150 Reg =
TRI.getDwarfRegNum(SR,
false);
161 if (
Offset < MaxSize && CurSubReg.
test(Coverage)) {
165 -1,
Offset - CurPos,
"no DWARF register encoding"));
170 Reg, std::min<unsigned>(
Size, MaxSize -
Offset),
"sub-register"));
182 -1,
RegSize - CurPos,
"no DWARF register encoding"));
188 emitOp(dwarf::DW_OP_stack_value);
194 emitOp(dwarf::DW_OP_consts);
228 if (NumBytes == 4 || NumBytes == 8 ) {
230 emitOp(dwarf::DW_OP_implicit_value);
239 for (
int i = 0; i < NumBytes; ++i) {
247 dbgs() <<
"Skipped DW_OP_implicit_value creation for ConstantFP of size: "
254 unsigned FragmentOffsetInBits) {
256 if (!
addMachineReg(
TRI, MachineReg, Fragment ? Fragment->SizeInBits : ~1U)) {
261 bool HasComplexExpression =
false;
262 auto Op = ExprCursor.
peek();
264 HasComplexExpression =
true;
295 if (Reg.DwarfRegNo >= 0)
296 addReg(Reg.DwarfRegNo, Reg.Comment);
298 if (
RegSize > FragmentInfo->SizeInBits)
310 emitOp(dwarf::DW_OP_stack_value);
316 auto NextOp = ExprCursor.
peek();
326 return Op.getOp() == dwarf::DW_OP_stack_value;
336 LLVM_DEBUG(
dbgs() <<
"TODO: giving up on debug information due to "
337 "multi-register usage.\n");
345 int SignedOffset = 0;
346 assert(!Reg.isSubRegister() &&
"full register expected");
350 if (
Op && (
Op->getOp() == dwarf::DW_OP_plus_uconst)) {
362 if (
Op &&
Op->getOp() == dwarf::DW_OP_constu) {
366 if (
N &&
N->getOp() == dwarf::DW_OP_plus &&
Offset <= IntMax) {
369 }
else if (
N &&
N->getOp() == dwarf::DW_OP_minus &&
371 SignedOffset = -
static_cast<int64_t
>(
Offset);
379 addBReg(Reg.DwarfRegNo, SignedOffset);
384 auto NextOp = ExprCursor.
peek();
409 auto Op = ExprCursor.
take();
414 "Can currently only emit entry values covering a single operation");
427 emitOp(
CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value));
448 "Began emitting entry value block before cancelling entry value");
458 unsigned I = 0, E =
CU.ExprRefedBaseTypes.size();
460 if (
CU.ExprRefedBaseTypes[
I].BitSize == BitSize &&
461 CU.ExprRefedBaseTypes[
I].Encoding == Encoding)
465 CU.ExprRefedBaseTypes.emplace_back(BitSize, Encoding);
473 auto Op = ExprCursor.
take();
474 switch (
Op->getOp()) {
475 case dwarf::DW_OP_deref:
499 std::optional<DIExpression::ExprOperand> PrevConvertOp;
502 auto Op = ExprCursor.take();
505 if (OpNum >= dwarf::DW_OP_reg0 && OpNum <= dwarf::DW_OP_reg31) {
508 }
else if (OpNum >= dwarf::DW_OP_breg0 && OpNum <= dwarf::DW_OP_breg31) {
509 addBReg(OpNum - dwarf::DW_OP_breg0,
Op->getArg(0));
515 if (!InsertArg(
Op->getArg(0), ExprCursor)) {
521 unsigned SizeInBits =
Op->getArg(1);
522 unsigned FragmentOffset =
Op->getArg(0);
552 unsigned SizeInBits =
Op->getArg(1);
553 unsigned BitOffset =
Op->getArg(0);
559 emitOp(dwarf::DW_OP_deref_size);
567 unsigned PtrSizeInBytes =
CU.getAsmPrinter()->MAI->getCodePointerSize();
568 unsigned LeftShift = PtrSizeInBytes * 8 - (SizeInBits + BitOffset);
569 unsigned RightShift = LeftShift + BitOffset;
571 emitOp(dwarf::DW_OP_constu);
575 emitOp(dwarf::DW_OP_constu);
585 case dwarf::DW_OP_plus_uconst:
587 emitOp(dwarf::DW_OP_plus_uconst);
590 case dwarf::DW_OP_plus:
591 case dwarf::DW_OP_minus:
592 case dwarf::DW_OP_mul:
593 case dwarf::DW_OP_div:
594 case dwarf::DW_OP_mod:
595 case dwarf::DW_OP_or:
596 case dwarf::DW_OP_and:
597 case dwarf::DW_OP_xor:
598 case dwarf::DW_OP_shl:
599 case dwarf::DW_OP_shr:
600 case dwarf::DW_OP_shra:
601 case dwarf::DW_OP_lit0:
602 case dwarf::DW_OP_not:
603 case dwarf::DW_OP_dup:
604 case dwarf::DW_OP_push_object_address:
605 case dwarf::DW_OP_over:
606 case dwarf::DW_OP_eq:
607 case dwarf::DW_OP_ne:
608 case dwarf::DW_OP_gt:
609 case dwarf::DW_OP_ge:
610 case dwarf::DW_OP_lt:
611 case dwarf::DW_OP_le:
614 case dwarf::DW_OP_deref:
621 emitOp(dwarf::DW_OP_deref);
623 case dwarf::DW_OP_constu:
627 case dwarf::DW_OP_consts:
629 emitOp(dwarf::DW_OP_consts);
633 unsigned BitSize =
Op->getArg(0);
636 emitOp(dwarf::DW_OP_convert);
645 if (PrevConvertOp && PrevConvertOp->getArg(0) < BitSize) {
646 if (Encoding == dwarf::DW_ATE_signed)
648 else if (Encoding == dwarf::DW_ATE_unsigned)
650 PrevConvertOp = std::nullopt;
657 case dwarf::DW_OP_stack_value:
660 case dwarf::DW_OP_swap:
662 emitOp(dwarf::DW_OP_swap);
664 case dwarf::DW_OP_xderef:
666 emitOp(dwarf::DW_OP_xderef);
668 case dwarf::DW_OP_deref_size:
669 emitOp(dwarf::DW_OP_deref_size);
675 case dwarf::DW_OP_regx:
676 emitOp(dwarf::DW_OP_regx);
679 case dwarf::DW_OP_bregx:
680 emitOp(dwarf::DW_OP_bregx);
722 "overlapping or duplicate fragments");
731 emitOp(dwarf::DW_OP_constu);
734 emitOp(dwarf::DW_OP_lit0);
737 emitOp(dwarf::DW_OP_constu);
746 if (FromBits / 7 < 1+1+1+1+1) {
748 emitOp(dwarf::DW_OP_constu);
756 emitOp(dwarf::DW_OP_lit1);
757 emitOp(dwarf::DW_OP_constu);
760 emitOp(dwarf::DW_OP_lit1);
761 emitOp(dwarf::DW_OP_minus);
767 emitOp(dwarf::DW_OP_WASM_location);
This file implements a class to represent arbitrary precision integral constant values and operations...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static bool isMemoryLocation(DIExpressionCursor ExprCursor)
Assuming a well-formed expression, match "DW_OP_deref* DW_OP_LLVM_fragment?".
This file contains constants used for implementing Dwarf debug support.
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the SmallBitVector class.
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getBitWidth() const
Return the number of bits in the APInt.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This class is intended to be used as a driving class for all asm writers.
const DataLayout & getDataLayout() const
Return information about data layout.
Holds a DIExpression and keeps track of how many operands have been consumed so far.
std::optional< DIExpression::ExprOperand > peekNext() const
Return the next operation.
std::optional< DIExpression::FragmentInfo > getFragmentInfo() const
Retrieve the fragment information, if any.
std::optional< DIExpression::ExprOperand > peek() const
Return the current operation.
void consume(unsigned N)
Consume N operations.
std::optional< DIExpression::ExprOperand > take()
Consume one operation.
A lightweight wrapper around an expression operand.
bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
bool isFragment() const
Return whether this is a piece of an aggregate variable.
static std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)
Retrieve the details of this fragment expression.
This class represents an Operation in the Expression.
void addAnd(unsigned Mask)
Emit a bitwise and dwarf operation.
void setLocation(const MachineLocation &Loc, const DIExpression *DIExpr)
Set the location (Loc) and DIExpression (DIExpr) to describe.
virtual void emitOp(uint8_t Op, const char *Comment=nullptr)=0
Output a dwarf operand and an optional assembler comment.
virtual void disableTemporaryBuffer()=0
Disable emission to the temporary buffer.
bool isUnknownLocation() const
virtual unsigned getTemporaryBufferSize()=0
Return the emitted size, in number of bytes, for the data stored in the temporary buffer.
uint64_t OffsetInBits
Current Fragment Offset in Bits.
virtual bool isFrameRegister(const TargetRegisterInfo &TRI, llvm::Register MachineReg)=0
Return whether the given machine register is the frame register in the current function.
void finalize()
This needs to be called last to commit any pending changes.
void addFragmentOffset(const DIExpression *Expr)
If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to the fragment described by Ex...
void emitLegacySExt(unsigned FromBits)
void cancelEntryValue()
Cancel the emission of an entry value.
bool isRegisterLocation() const
void setMemoryLocationKind()
Lock this down to become a memory location description.
virtual void emitBaseTypeRef(uint64_t Idx)=0
virtual void emitData1(uint8_t Value)=0
bool addMachineReg(const TargetRegisterInfo &TRI, llvm::Register MachineReg, unsigned MaxSize=~1U)
Emit a partial DWARF register operation.
unsigned SavedLocationKind
void addReg(int DwarfReg, const char *Comment=nullptr)
Emit a DW_OP_reg operation.
std::optional< uint8_t > TagOffset
bool isImplicitLocation() const
virtual void emitUnsigned(uint64_t Value)=0
Emit a raw unsigned value.
void addConstantFP(const APFloat &Value, const AsmPrinter &AP)
Emit an floating point constant.
void maskSubRegister()
Add masking operations to stencil out a subregister.
SmallVector< Register, 2 > DwarfRegs
The register location, if any.
bool addMachineRegExpression(const TargetRegisterInfo &TRI, DIExpressionCursor &Expr, llvm::Register MachineReg, unsigned FragmentOffsetInBits=0)
Emit a machine register location.
void addStackValue()
Emit a DW_OP_stack_value, if supported.
void finalizeEntryValue()
Finalize an entry value by emitting its size operand, and committing the DWARF block which has been e...
void addBReg(int DwarfReg, int Offset)
Emit a DW_OP_breg operation.
bool isMemoryLocation() const
void addUnsignedConstant(uint64_t Value)
Emit an unsigned constant.
unsigned SubRegisterSizeInBits
Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
void addFBReg(int Offset)
Emit DW_OP_fbreg <Offset>.
void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits)
Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed to represent a subregister.
void addExpression(DIExpressionCursor &&Expr)
Emit all remaining operations in the DIExpressionCursor.
bool isEntryValue() const
unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding)
Return the index of a base type with the given properties and create one if necessary.
void addSignedConstant(int64_t Value)
Emit a signed constant.
void emitLegacyZExt(unsigned FromBits)
bool IsEmittingEntryValue
Whether we are currently emitting an entry value operation.
virtual void emitSigned(int64_t Value)=0
Emit a raw signed value.
unsigned SubRegisterOffsetInBits
void setEntryValueFlags(const MachineLocation &Loc)
Lock this down to become an entry value location.
virtual void commitTemporaryBuffer()=0
Commit the data stored in the temporary buffer to the main output.
void addShr(unsigned ShiftBy)
Emit a shift-right dwarf operation.
void addWasmLocation(unsigned Index, uint64_t Offset)
Emit location information expressed via WebAssembly location + offset The Index is an identifier for ...
virtual void enableTemporaryBuffer()=0
Start emitting data to the temporary buffer.
void emitConstu(uint64_t Value)
Emit a normalized unsigned constant.
void beginEntryValueExpression(DIExpressionCursor &ExprCursor)
Begin emission of an entry value dwarf operation.
void addOpPiece(unsigned SizeInBits, unsigned OffsetInBits=0)
Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool test(unsigned Idx) const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ DW_OP_LLVM_entry_value
Only used in LLVM metadata.
@ DW_OP_LLVM_extract_bits_zext
Only used in LLVM metadata.
@ DW_OP_LLVM_tag_offset
Only used in LLVM metadata.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ DW_OP_LLVM_arg
Only used in LLVM metadata.
@ DW_OP_LLVM_convert
Only used in LLVM metadata.
@ DW_OP_LLVM_extract_bits_sext
Only used in LLVM metadata.
This is an optimization pass for GlobalISel generic memory operations.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
Holds information about all subregisters comprising a register location.
static Register createRegister(int RegNo, const char *Comment)
Create a full register, no extra DW_OP_piece operators necessary.
static Register createSubRegister(int RegNo, unsigned SizeInBits, const char *Comment)
Create a subregister that needs a DW_OP_piece operator with SizeInBits.