Print complete DIExpressions in the assembler output DEBUG_VALUE comments.

The previous code was complex, incorrect, and couldn't print everything.

llvm-svn: 301333
This commit is contained in:
Adrian Prantl 2017-04-25 17:22:09 +00:00
parent b04562a990
commit de1a8b4efb
7 changed files with 35 additions and 53 deletions

View File

@ -825,43 +825,25 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
OS << Name << ":"; OS << Name << ":";
} }
OS << V->getName(); OS << V->getName();
const DIExpression *Expr = MI->getDebugExpression();
auto Fragment = Expr->getFragmentInfo();
if (Fragment)
OS << " [fragment offset=" << Fragment->OffsetInBits
<< " size=" << Fragment->SizeInBits << "]";
OS << " <- "; OS << " <- ";
// The second operand is only an offset if it's an immediate. // The second operand is only an offset if it's an immediate.
bool Deref = false;
bool MemLoc = MI->getOperand(0).isReg() && MI->getOperand(1).isImm(); bool MemLoc = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
int64_t Offset = MemLoc ? MI->getOperand(1).getImm() : 0; int64_t Offset = MemLoc ? MI->getOperand(1).getImm() : 0;
for (unsigned i = 0; i < Expr->getNumElements(); ++i) { const DIExpression *Expr = MI->getDebugExpression();
uint64_t Op = Expr->getElement(i); if (Expr->getNumElements()) {
if (Op == dwarf::DW_OP_LLVM_fragment) { OS << '[';
// There can't be any operands after this in a valid expression bool NeedSep = false;
break; for (auto Op : Expr->expr_ops()) {
} else if (Deref) { if (NeedSep)
// We currently don't support extra Offsets or derefs after the first OS << ", ";
// one. Bail out early instead of emitting an incorrect comment. else
OS << " [complex expression]"; NeedSep = true;
AP.OutStreamer->emitRawComment(OS.str()); OS << dwarf::OperationEncodingString(Op.getOp());
return true; for (unsigned I = 0; I < Op.getNumArgs(); ++I)
} else if (Op == dwarf::DW_OP_deref) { OS << ' ' << Op.getArg(I);
Deref = true;
continue;
}
uint64_t ExtraOffset = Expr->getElement(i++);
if (Op == dwarf::DW_OP_plus)
Offset += ExtraOffset;
else if (Op == dwarf::DW_OP_stack_value)
OS << " [stack value]";
else {
assert(Op == dwarf::DW_OP_minus);
Offset -= ExtraOffset;
} }
OS << "] ";
} }
// Register or immediate value. Register 0 means undef. // Register or immediate value. Register 0 means undef.
@ -892,7 +874,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
const TargetFrameLowering *TFI = AP.MF->getSubtarget().getFrameLowering(); const TargetFrameLowering *TFI = AP.MF->getSubtarget().getFrameLowering();
Offset += TFI->getFrameIndexReference(*AP.MF, Offset += TFI->getFrameIndexReference(*AP.MF,
MI->getOperand(0).getIndex(), Reg); MI->getOperand(0).getIndex(), Reg);
Deref = true; MemLoc = true;
} }
if (Reg == 0) { if (Reg == 0) {
// Suppress offset, it is not meaningful here. // Suppress offset, it is not meaningful here.
@ -901,12 +883,12 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
AP.OutStreamer->emitRawComment(OS.str()); AP.OutStreamer->emitRawComment(OS.str());
return true; return true;
} }
if (MemLoc || Deref) if (MemLoc)
OS << '['; OS << '[';
OS << PrintReg(Reg, AP.MF->getSubtarget().getRegisterInfo()); OS << PrintReg(Reg, AP.MF->getSubtarget().getRegisterInfo());
} }
if (MemLoc || Deref) if (MemLoc)
OS << '+' << Offset << ']'; OS << '+' << Offset << ']';
// NOTE: Want this comment at start of line, don't emit with AddComment. // NOTE: Want this comment at start of line, don't emit with AddComment.

View File

@ -35,27 +35,27 @@
; } ; }
; ASM-LABEL: loop_csr: # @loop_csr ; ASM-LABEL: loop_csr: # @loop_csr
; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=0 size=32] <- 0 ; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] 0
; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=32 size=32] <- 0 ; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] 0
; ASM: # BB#2: # %for.body.preheader ; ASM: # BB#2: # %for.body.preheader
; ASM: xorl %edi, %edi ; ASM: xorl %edi, %edi
; ASM: xorl %esi, %esi ; ASM: xorl %esi, %esi
; ASM: .p2align 4, 0x90 ; ASM: .p2align 4, 0x90
; ASM: .LBB0_3: # %for.body ; ASM: .LBB0_3: # %for.body
; ASM: [[ox_start:\.Ltmp[0-9]+]]: ; ASM: [[ox_start:\.Ltmp[0-9]+]]:
; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=0 size=32] <- %EDI ; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] %EDI
; ASM: .cv_loc 0 1 13 11 # t.c:13:11 ; ASM: .cv_loc 0 1 13 11 # t.c:13:11
; ASM: movl %edi, %ecx ; ASM: movl %edi, %ecx
; ASM: callq g ; ASM: callq g
; ASM: movl %eax, %edi ; ASM: movl %eax, %edi
; ASM: [[oy_start:\.Ltmp[0-9]+]]: ; ASM: [[oy_start:\.Ltmp[0-9]+]]:
; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=0 size=32] <- %EDI ; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] %EDI
; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=32 size=32] <- %ESI ; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] %ESI
; ASM: .cv_loc 0 1 14 11 # t.c:14:11 ; ASM: .cv_loc 0 1 14 11 # t.c:14:11
; ASM: movl %esi, %ecx ; ASM: movl %esi, %ecx
; ASM: callq g ; ASM: callq g
; ASM: movl %eax, %esi ; ASM: movl %eax, %esi
; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=32 size=32] <- %ESI ; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] %ESI
; ASM: cmpl n(%rip), %eax ; ASM: cmpl n(%rip), %eax
; ASM: jl .LBB0_3 ; ASM: jl .LBB0_3
; ASM: [[oy_end:\.Ltmp[0-9]+]]: ; ASM: [[oy_end:\.Ltmp[0-9]+]]:
@ -64,32 +64,32 @@
; ASM-LABEL: pad_right: # @pad_right ; ASM-LABEL: pad_right: # @pad_right
; ASM: #DEBUG_VALUE: pad_right:o [fragment offset=32 size=32] <- %ECX ; ASM: #DEBUG_VALUE: pad_right:o <- [DW_OP_LLVM_fragment 32 32] %ECX
; ASM: movl %ecx, %eax ; ASM: movl %ecx, %eax
; ASM: retq ; ASM: retq
; ASM-LABEL: pad_left: # @pad_left ; ASM-LABEL: pad_left: # @pad_left
; ASM: #DEBUG_VALUE: pad_left:o [fragment offset=0 size=32] <- %ECX ; ASM: #DEBUG_VALUE: pad_left:o <- [DW_OP_LLVM_fragment 0 32] %ECX
; ASM: .cv_loc 2 1 24 3 # t.c:24:3 ; ASM: .cv_loc 2 1 24 3 # t.c:24:3
; ASM: movl %ecx, %eax ; ASM: movl %ecx, %eax
; ASM: retq ; ASM: retq
; ASM-LABEL: nested: # @nested ; ASM-LABEL: nested: # @nested
; ASM: #DEBUG_VALUE: nested:o <- [%RCX+0] ; ASM: #DEBUG_VALUE: nested:o <- [DW_OP_deref] [%RCX+0]
; ASM: movl 12(%rcx), %eax ; ASM: movl 12(%rcx), %eax
; ASM: [[p_start:\.Ltmp[0-9]+]]: ; ASM: [[p_start:\.Ltmp[0-9]+]]:
; ASM: #DEBUG_VALUE: nested:p [fragment offset=32 size=32] <- %EAX ; ASM: #DEBUG_VALUE: nested:p <- [DW_OP_LLVM_fragment 32 32] %EAX
; ASM: retq ; ASM: retq
; ASM-LABEL: bitpiece_spill: # @bitpiece_spill ; ASM-LABEL: bitpiece_spill: # @bitpiece_spill
; ASM: #DEBUG_VALUE: bitpiece_spill:o [fragment offset=0 size=32] <- 0 ; ASM: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 0 32] 0
; ASM: xorl %ecx, %ecx ; ASM: xorl %ecx, %ecx
; ASM: callq g ; ASM: callq g
; ASM: movl %eax, [[offset_o_x:[0-9]+]](%rsp) # 4-byte Spill ; ASM: movl %eax, [[offset_o_x:[0-9]+]](%rsp) # 4-byte Spill
; ASM: [[spill_o_x_start:\.Ltmp[0-9]+]]: ; ASM: [[spill_o_x_start:\.Ltmp[0-9]+]]:
; ASM: #DEBUG_VALUE: bitpiece_spill:o [fragment offset=32 size=32] <- [%RSP+[[offset_o_x]]] ; ASM: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 32 32] [%RSP+[[offset_o_x]]]
; ASM: #APP ; ASM: #APP
; ASM: #NO_APP ; ASM: #NO_APP
; ASM: movl [[offset_o_x]](%rsp), %eax # 4-byte Reload ; ASM: movl [[offset_o_x]](%rsp), %eax # 4-byte Reload

View File

@ -12,10 +12,10 @@
; The address of the (potentially now malloc'ed) alloca ends up ; The address of the (potentially now malloc'ed) alloca ends up
; in RDI, after which it is spilled to the stack. We record the ; in RDI, after which it is spilled to the stack. We record the
; spill OFFSET on the stack for checking the debug info below. ; spill OFFSET on the stack for checking the debug info below.
; CHECK: #DEBUG_VALUE: bar:y <- [%RDI+0] ; CHECK: #DEBUG_VALUE: bar:y <- [DW_OP_deref] [%RDI+0]
; CHECK: movq %rdi, [[OFFSET:[0-9]+]](%rsp) ; CHECK: movq %rdi, [[OFFSET:[0-9]+]](%rsp)
; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]] ; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]]
; CHECK-NEXT: #DEBUG_VALUE: bar:y <- [complex expression] ; CHECK-NEXT: #DEBUG_VALUE: bar:y <- [DW_OP_deref, DW_OP_deref]
; This location should be valid until the end of the function. ; This location should be valid until the end of the function.
; CHECK: movq %rbp, %rsp ; CHECK: movq %rbp, %rsp

View File

@ -20,7 +20,7 @@
; right now, so we check the asm output: ; right now, so we check the asm output:
; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o - -filetype=asm | FileCheck %s -check-prefix=ASM-CHECK ; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o - -filetype=asm | FileCheck %s -check-prefix=ASM-CHECK
; vla should have a register-indirect address at one point. ; vla should have a register-indirect address at one point.
; ASM-CHECK: DEBUG_VALUE: vla <- [%RCX+0] ; ASM-CHECK: DEBUG_VALUE: vla <- [DW_OP_deref] [%RCX+0]
; ASM-CHECK: DW_OP_breg2 ; ASM-CHECK: DW_OP_breg2
; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s --check-prefix=PRETTY-PRINT ; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s --check-prefix=PRETTY-PRINT

View File

@ -15,8 +15,8 @@
; CHECK-LABEL: bitpiece_spill: # @bitpiece_spill ; CHECK-LABEL: bitpiece_spill: # @bitpiece_spill
; CHECK: callq g ; CHECK: callq g
; CHECK: movl %eax, [[offs:[0-9]+]](%rsp) # 4-byte Spill ; CHECK: movl %eax, [[offs:[0-9]+]](%rsp) # 4-byte Spill
; CHECK: #DEBUG_VALUE: bitpiece_spill:o [fragment offset=32 size=32] <- 0 ; CHECK: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 32 32] 0
; CHECK: #DEBUG_VALUE: bitpiece_spill:o [fragment offset=0 size=32] <- [%RSP+[[offs]]] ; CHECK: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 0 32] [%RSP+[[offs]]]
; CHECK: #APP ; CHECK: #APP
; CHECK: #NO_APP ; CHECK: #NO_APP
; CHECK: movl [[offs]](%rsp), %eax # 4-byte Reload ; CHECK: movl [[offs]](%rsp), %eax # 4-byte Reload

View File

@ -17,7 +17,7 @@
; The inlined A::this pointer has the same location as B::this, but it may not be ; The inlined A::this pointer has the same location as B::this, but it may not be
; modified by the debugger. ; modified by the debugger.
; ;
; ASM: [stack value] ; ASM: [DW_OP_stack_value]
; CHECK: Location description: 70 00 9f ; CHECK: Location description: 70 00 9f
; rax+0, stack-value ; rax+0, stack-value
source_filename = "ab.cpp" source_filename = "ab.cpp"

View File

@ -1,6 +1,6 @@
; RUN: llc -O0 -mtriple=x86_64-apple-darwin -filetype=asm %s -o - | FileCheck %s ; RUN: llc -O0 -mtriple=x86_64-apple-darwin -filetype=asm %s -o - | FileCheck %s
; Ensure that we generate an indirect location for the variable length array a. ; Ensure that we generate an indirect location for the variable length array a.
; CHECK: ##DEBUG_VALUE: vla:a <- [%RCX+0] ; CHECK: ##DEBUG_VALUE: vla:a <- [DW_OP_deref] [%RCX+0]
; CHECK: DW_OP_breg2 ; CHECK: DW_OP_breg2
; rdar://problem/13658587 ; rdar://problem/13658587
; ;