Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 41 additions & 19 deletions llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,32 +566,54 @@ bool DwarfExpression::addExpression(
case dwarf::DW_OP_LLVM_extract_bits_zext: {
unsigned SizeInBits = Op->getArg(1);
unsigned BitOffset = Op->getArg(0);
unsigned DerefSize = 0;
// Operations are done in the DWARF "generic type" whose size
// is the size of a pointer.
unsigned PtrSizeInBytes = CU.getAsmPrinter()->MAI->getCodePointerSize();

// If we have a memory location then dereference to get the value, though
// we have to make sure we don't dereference any bytes past the end of the
// object.
if (isMemoryLocation()) {
emitOp(dwarf::DW_OP_deref_size);
emitUnsigned(alignTo(BitOffset + SizeInBits, 8) / 8);
DerefSize = alignTo(BitOffset + SizeInBits, 8) / 8;
if (DerefSize == PtrSizeInBytes) {
emitOp(dwarf::DW_OP_deref);
} else {
emitOp(dwarf::DW_OP_deref_size);
emitUnsigned(DerefSize);
}
}

// Extract the bits by a shift left (to shift out the bits after what we
// want to extract) followed by shift right (to shift the bits to position
// 0 and also sign/zero extend). These operations are done in the DWARF
// "generic type" whose size is the size of a pointer.
unsigned PtrSizeInBytes = CU.getAsmPrinter()->MAI->getCodePointerSize();
unsigned LeftShift = PtrSizeInBytes * 8 - (SizeInBits + BitOffset);
unsigned RightShift = LeftShift + BitOffset;
if (LeftShift) {
emitOp(dwarf::DW_OP_constu);
emitUnsigned(LeftShift);
emitOp(dwarf::DW_OP_shl);
}
if (RightShift) {
emitOp(dwarf::DW_OP_constu);
emitUnsigned(RightShift);
emitOp(OpNum == dwarf::DW_OP_LLVM_extract_bits_sext ? dwarf::DW_OP_shra
: dwarf::DW_OP_shr);
// If a dereference was emitted for an unsigned value, and
// there's no bit offset, then a bit of optimization is
// possible.
if (OpNum == dwarf::DW_OP_LLVM_extract_bits_zext && BitOffset == 0) {
if (8 * DerefSize == SizeInBits) {
// The correct value is already on the stack.
} else {
// No need to shift, we can just mask off the desired bits.
emitOp(dwarf::DW_OP_constu);
emitUnsigned((1u << SizeInBits) - 1);
emitOp(dwarf::DW_OP_and);
}
} else {
// Extract the bits by a shift left (to shift out the bits after what we
// want to extract) followed by shift right (to shift the bits to
// position 0 and also sign/zero extend).
unsigned LeftShift = PtrSizeInBytes * 8 - (SizeInBits + BitOffset);
unsigned RightShift = LeftShift + BitOffset;
if (LeftShift) {
emitOp(dwarf::DW_OP_constu);
emitUnsigned(LeftShift);
emitOp(dwarf::DW_OP_shl);
}
if (RightShift) {
emitOp(dwarf::DW_OP_constu);
emitUnsigned(RightShift);
emitOp(OpNum == dwarf::DW_OP_LLVM_extract_bits_sext
? dwarf::DW_OP_shra
: dwarf::DW_OP_shr);
}
}

// The value is now at the top of the stack, so set the location to
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/DebugInfo/X86/DW_OP_LLVM_extract_bits.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
; CHECK-LABEL: DW_TAG_subprogram
; CHECK: DW_AT_name ("test1")
; CHECK: DW_TAG_variable
; CHECK: DW_AT_location (DW_OP_fbreg -1, DW_OP_deref_size 0x1, DW_OP_constu 0x3d, DW_OP_shl, DW_OP_constu 0x3d, DW_OP_shr, DW_OP_stack_value)
; CHECK: DW_AT_location (DW_OP_fbreg -1, DW_OP_deref_size 0x1, DW_OP_constu 0x7, DW_OP_and, DW_OP_stack_value)
; CHECK: DW_AT_name ("x")
; CHECK: DW_TAG_variable
; CHECK: DW_AT_location (DW_OP_fbreg -1, DW_OP_deref_size 0x1, DW_OP_constu 0x39, DW_OP_shl, DW_OP_constu 0x3c, DW_OP_shra, DW_OP_stack_value)
Expand All @@ -25,7 +25,7 @@ entry:
; CHECK-LABEL: DW_TAG_subprogram
; CHECK: DW_AT_name ("test2")
; CHECK: DW_TAG_variable
; CHECK: DW_AT_location (DW_OP_breg0 {{R[^+]+}}+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_constu 0x3d, DW_OP_shl, DW_OP_constu 0x3d, DW_OP_shr, DW_OP_stack_value)
; CHECK: DW_AT_location (DW_OP_breg0 {{R[^+]+}}+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_constu 0x7, DW_OP_and, DW_OP_stack_value)
; CHECK: DW_AT_name ("x")
; CHECK: DW_TAG_variable
; CHECK: DW_AT_location (DW_OP_breg0 {{R[^+]+}}+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_constu 0x39, DW_OP_shl, DW_OP_constu 0x3c, DW_OP_shra, DW_OP_stack_value)
Expand Down Expand Up @@ -67,7 +67,7 @@ entry:
; CHECK: DW_TAG_variable
; CHECK: DW_AT_location (DW_OP_fbreg -4, DW_OP_plus_uconst 0x3, DW_OP_deref_size 0x1, DW_OP_constu 0x38, DW_OP_shl, DW_OP_constu 0x39, DW_OP_shr, DW_OP_stack_value)
; CHECK: DW_AT_name ("z")
; CHECK: DW_AT_location (DW_OP_fbreg -4, DW_OP_deref_size 0x8, DW_OP_stack_value)
; CHECK: DW_AT_location (DW_OP_fbreg -4, DW_OP_deref, DW_OP_stack_value)
; CHECK: DW_AT_name ("q")

define i32 @test4() !dbg !28 {
Expand Down