From de1a8b4efbe17da4f8e1a7180868fd05a039cc97 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 25 Apr 2017 17:22:09 +0000 Subject: [PATCH] Print complete DIExpressions in the assembler output DEBUG_VALUE comments. The previous code was complex, incorrect, and couldn't print everything. llvm-svn: 301333 --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 50 +++++++-------------- llvm/test/DebugInfo/COFF/pieces.ll | 24 +++++----- llvm/test/DebugInfo/X86/debug-loc-asan.ll | 4 +- llvm/test/DebugInfo/X86/op_deref.ll | 2 +- llvm/test/DebugInfo/X86/pieces-4.ll | 4 +- llvm/test/DebugInfo/X86/this-stack_value.ll | 2 +- llvm/test/DebugInfo/X86/vla.ll | 2 +- 7 files changed, 35 insertions(+), 53 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index a8f45db4ad02..d99065b1b67a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -825,43 +825,25 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { OS << Name << ":"; } OS << V->getName(); - - const DIExpression *Expr = MI->getDebugExpression(); - auto Fragment = Expr->getFragmentInfo(); - if (Fragment) - OS << " [fragment offset=" << Fragment->OffsetInBits - << " size=" << Fragment->SizeInBits << "]"; OS << " <- "; // 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(); int64_t Offset = MemLoc ? MI->getOperand(1).getImm() : 0; - for (unsigned i = 0; i < Expr->getNumElements(); ++i) { - uint64_t Op = Expr->getElement(i); - if (Op == dwarf::DW_OP_LLVM_fragment) { - // There can't be any operands after this in a valid expression - break; - } else if (Deref) { - // We currently don't support extra Offsets or derefs after the first - // one. Bail out early instead of emitting an incorrect comment. - OS << " [complex expression]"; - AP.OutStreamer->emitRawComment(OS.str()); - return true; - } else if (Op == dwarf::DW_OP_deref) { - 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; + const DIExpression *Expr = MI->getDebugExpression(); + if (Expr->getNumElements()) { + OS << '['; + bool NeedSep = false; + for (auto Op : Expr->expr_ops()) { + if (NeedSep) + OS << ", "; + else + NeedSep = true; + OS << dwarf::OperationEncodingString(Op.getOp()); + for (unsigned I = 0; I < Op.getNumArgs(); ++I) + OS << ' ' << Op.getArg(I); } + OS << "] "; } // 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(); Offset += TFI->getFrameIndexReference(*AP.MF, MI->getOperand(0).getIndex(), Reg); - Deref = true; + MemLoc = true; } if (Reg == 0) { // Suppress offset, it is not meaningful here. @@ -901,12 +883,12 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { AP.OutStreamer->emitRawComment(OS.str()); return true; } - if (MemLoc || Deref) + if (MemLoc) OS << '['; OS << PrintReg(Reg, AP.MF->getSubtarget().getRegisterInfo()); } - if (MemLoc || Deref) + if (MemLoc) OS << '+' << Offset << ']'; // NOTE: Want this comment at start of line, don't emit with AddComment. diff --git a/llvm/test/DebugInfo/COFF/pieces.ll b/llvm/test/DebugInfo/COFF/pieces.ll index 8252b590fe90..60330e057726 100644 --- a/llvm/test/DebugInfo/COFF/pieces.ll +++ b/llvm/test/DebugInfo/COFF/pieces.ll @@ -35,27 +35,27 @@ ; } ; ASM-LABEL: loop_csr: # @loop_csr -; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=0 size=32] <- 0 -; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=32 size=32] <- 0 +; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] 0 +; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] 0 ; ASM: # BB#2: # %for.body.preheader ; ASM: xorl %edi, %edi ; ASM: xorl %esi, %esi ; ASM: .p2align 4, 0x90 ; ASM: .LBB0_3: # %for.body ; 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: movl %edi, %ecx ; ASM: callq g ; ASM: movl %eax, %edi ; ASM: [[oy_start:\.Ltmp[0-9]+]]: -; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=0 size=32] <- %EDI -; ASM: #DEBUG_VALUE: loop_csr:o [fragment offset=32 size=32] <- %ESI +; ASM: #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] %EDI +; 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: movl %esi, %ecx ; ASM: callq g ; 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: jl .LBB0_3 ; ASM: [[oy_end:\.Ltmp[0-9]+]]: @@ -64,32 +64,32 @@ ; 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: retq ; 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: movl %ecx, %eax ; ASM: retq ; 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: [[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-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: callq g ; ASM: movl %eax, [[offset_o_x:[0-9]+]](%rsp) # 4-byte Spill ; 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: #NO_APP ; ASM: movl [[offset_o_x]](%rsp), %eax # 4-byte Reload diff --git a/llvm/test/DebugInfo/X86/debug-loc-asan.ll b/llvm/test/DebugInfo/X86/debug-loc-asan.ll index e4449a29281c..8f798094dffa 100644 --- a/llvm/test/DebugInfo/X86/debug-loc-asan.ll +++ b/llvm/test/DebugInfo/X86/debug-loc-asan.ll @@ -12,10 +12,10 @@ ; The address of the (potentially now malloc'ed) alloca ends up ; in RDI, after which it is spilled to the stack. We record the ; 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-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. ; CHECK: movq %rbp, %rsp diff --git a/llvm/test/DebugInfo/X86/op_deref.ll b/llvm/test/DebugInfo/X86/op_deref.ll index bfec43757d1d..2d375352f6f7 100644 --- a/llvm/test/DebugInfo/X86/op_deref.ll +++ b/llvm/test/DebugInfo/X86/op_deref.ll @@ -20,7 +20,7 @@ ; 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 ; 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 ; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s --check-prefix=PRETTY-PRINT diff --git a/llvm/test/DebugInfo/X86/pieces-4.ll b/llvm/test/DebugInfo/X86/pieces-4.ll index 124463691e19..121cb7c425c6 100644 --- a/llvm/test/DebugInfo/X86/pieces-4.ll +++ b/llvm/test/DebugInfo/X86/pieces-4.ll @@ -15,8 +15,8 @@ ; CHECK-LABEL: bitpiece_spill: # @bitpiece_spill ; CHECK: callq g ; 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 [fragment offset=0 size=32] <- [%RSP+[[offs]]] +; CHECK: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 32 32] 0 +; CHECK: #DEBUG_VALUE: bitpiece_spill:o <- [DW_OP_LLVM_fragment 0 32] [%RSP+[[offs]]] ; CHECK: #APP ; CHECK: #NO_APP ; CHECK: movl [[offs]](%rsp), %eax # 4-byte Reload diff --git a/llvm/test/DebugInfo/X86/this-stack_value.ll b/llvm/test/DebugInfo/X86/this-stack_value.ll index 0c4db39e8e46..c292b67543d1 100644 --- a/llvm/test/DebugInfo/X86/this-stack_value.ll +++ b/llvm/test/DebugInfo/X86/this-stack_value.ll @@ -17,7 +17,7 @@ ; The inlined A::this pointer has the same location as B::this, but it may not be ; modified by the debugger. ; -; ASM: [stack value] +; ASM: [DW_OP_stack_value] ; CHECK: Location description: 70 00 9f ; rax+0, stack-value source_filename = "ab.cpp" diff --git a/llvm/test/DebugInfo/X86/vla.ll b/llvm/test/DebugInfo/X86/vla.ll index 1c72519ccb8d..17f1c48b6ebb 100644 --- a/llvm/test/DebugInfo/X86/vla.ll +++ b/llvm/test/DebugInfo/X86/vla.ll @@ -1,6 +1,6 @@ ; 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. -; CHECK: ##DEBUG_VALUE: vla:a <- [%RCX+0] +; CHECK: ##DEBUG_VALUE: vla:a <- [DW_OP_deref] [%RCX+0] ; CHECK: DW_OP_breg2 ; rdar://problem/13658587 ;