diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -276,6 +276,9 @@ /// DWARF block which has been emitted to the temporary buffer. void finalizeEntryValue(); + /// Cancel the emission of an entry value. + void cancelEntryValue(); + ~DwarfExpression() = default; public: diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -237,8 +237,17 @@ // If the register can only be described by a complex expression (i.e., // multiple subregisters) it doesn't safely compose with another complex // expression. For example, it is not possible to apply a DW_OP_deref - // operation to multiple DW_OP_pieces. - if (HasComplexExpression && DwarfRegs.size() > 1) { + // operation to multiple DW_OP_pieces, since composite location descriptions + // do not push anything on the DWARF stack. + // + // DW_OP_entry_value operations can only hold a DWARF expression or a + // register location description, so we can't emit a single entry value + // covering a composite location description. In the future we may want to + // emit entry value operations for each register location in the composite + // location, but until that is supported do not emit anything. + if ((HasComplexExpression || IsEmittingEntryValue) && DwarfRegs.size() > 1) { + if (IsEmittingEntryValue) + cancelEntryValue(); DwarfRegs.clear(); LocationKind = Unknown; return false; @@ -349,7 +358,6 @@ assert(Op->getArg(0) == 1 && "Can currently only emit entry values covering a single operation"); - emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value)); IsEmittingEntryValue = true; enableTemporaryBuffer(); } @@ -358,6 +366,8 @@ assert(IsEmittingEntryValue && "Entry value not open?"); disableTemporaryBuffer(); + emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value)); + // Emit the entry value's size operand. unsigned Size = getTemporaryBufferSize(); emitUnsigned(Size); @@ -368,6 +378,18 @@ IsEmittingEntryValue = false; } +void DwarfExpression::cancelEntryValue() { + assert(IsEmittingEntryValue && "Entry value not open?"); + disableTemporaryBuffer(); + + // The temporary buffer can't be emptied, so for now just assert that nothing + // has been emitted to it. + assert(getTemporaryBufferSize() == 0 && + "Began emitting entry value block before cancelling entry value"); + + IsEmittingEntryValue = false; +} + unsigned DwarfExpression::getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding) { // Reuse the base_type if we already have one in this CU otherwise we @@ -401,6 +423,10 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, unsigned FragmentOffsetInBits) { + // Entry values can currently only cover the initial register location, + // and not any other parts of the following DWARF expression. + assert(!IsEmittingEntryValue && "Can't emit entry value around expression"); + // If we need to mask out a subregister, do it now, unless the next // operation would emit an OpPiece anyway. auto N = ExprCursor.peek(); diff --git a/llvm/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll b/llvm/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll --- a/llvm/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll +++ b/llvm/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll @@ -1,11 +1,14 @@ ; RUN: llc -debug-entry-values -filetype=asm -o - %s | FileCheck %s -; Verify that the entry value covers both of the DW_OP_regx pieces. Previously -; the size operand of the entry value would be hardcoded to one. +; The q0 register does not have a DWARF register number, and is instead emitted +; as a composite location description with two sub-registers. Previously we +; emitted a single DW_OP_entry_value wrapping that whole composite location +; description, but that is not valid DWARF; DW_OP_entry_value operations can +; only hold DWARF expressions and register location descriptions. ; -; XXX: Is this really what should be emitted, or should we instead emit one -; entry value operation per DW_OP_regx? GDB can currently not understand -; entry values containing complex expressions like this. +; In the future we may want to emit a composite location description where each +; DW_OP_regx operation is wrapped in an entry value operation, but for now +; just verify that no invalid DWARF is emitted. target datalayout = "E-m:e-i64:64-n32:64-S128" target triple = "sparc64" @@ -20,8 +23,11 @@ ; return 123; ; } -; CHECK: .byte 243 ! DW_OP_GNU_entry_value -; CHECK-NEXT: .byte 8 ! 8 +; Verify that we got an entry value in the DIExpression... +; CHECK: DEBUG_VALUE: foo:p <- [DW_OP_LLVM_entry_value 1] $q0 + +; ... but that no entry value location was emitted: +; CHECK: .half 8 ! Loc expr size ; CHECK-NEXT: .byte 144 ! sub-register DW_OP_regx ; CHECK-NEXT: .byte 72 ! 72 ; CHECK-NEXT: .byte 147 ! DW_OP_piece @@ -30,7 +36,8 @@ ; CHECK-NEXT: .byte 73 ! 73 ; CHECK-NEXT: .byte 147 ! DW_OP_piece ; CHECK-NEXT: .byte 8 ! 8 -; CHECK-NEXT: .byte 159 ! DW_OP_stack_value +; CHECK-NEXT: .xword 0 +; CHECK-NEXT: .xword 0 @global = common global fp128 0xL00000000000000000000000000000000, align 16, !dbg !0