[llvm] r374881 - [DebugInfo] Add a DW_OP_LLVM_entry_value operation

David Stenberg via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 15 04:31:21 PDT 2019


Author: dstenb
Date: Tue Oct 15 04:31:21 2019
New Revision: 374881

URL: http://llvm.org/viewvc/llvm-project?rev=374881&view=rev
Log:
[DebugInfo] Add a DW_OP_LLVM_entry_value operation

Summary:
Internally in LLVM's metadata we use DW_OP_entry_value operations with
the same semantics as DWARF; that is, its operand specifies the number
of bytes that the entry value covers.

At the time of emitting entry values we don't know the emitted size of
the DWARF expression that the entry value will cover. Currently the size
is hardcoded to 1 in DIExpression, and other values causes the verifier
to fail. As the size is 1, that effectively means that we can only have
valid entry values for registers that can be encoded in one byte, which
are the registers with DWARF numbers 0 to 31 (as they can be encoded as
single-byte DW_OP_reg0..DW_OP_reg31 rather than a multi-byte
DW_OP_regx). It is a bit confusing, but it seems like llvm-dwarfdump
will print an operation "correctly", even if the byte size is less than
that, which may make it seem that we emit correct DWARF for registers
with DWARF numbers > 31. If you instead use readelf for such cases, it
will interpret the number of specified bytes as a DWARF expression. This
seems like a limitation in llvm-dwarfdump.

As suggested in D66746, a way forward would be to add an internal
variant of DW_OP_entry_value, DW_OP_LLVM_entry_value, whose operand
instead specifies the number of operations that the entry value covers,
and we then translate that into the byte size at the time of emission.

In this patch that internal operation is added. This patch keeps the
limitation that a entry value can only be applied to simple register
locations, but it will fix the issue with the size operand being
incorrect for DWARF numbers > 31.

Reviewers: aprantl, vsk, djtodoro, NikolaPrica

Reviewed By: aprantl

Subscribers: jyknight, fedor.sergeev, hiraditya, llvm-commits

Tags: #debug-info, #llvm

Differential Revision: https://reviews.llvm.org/D67492

Added:
    llvm/trunk/test/DebugInfo/ARM/entry-value-multi-byte-expr.ll
    llvm/trunk/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll
    llvm/trunk/test/Verifier/diexpression-dwarf-entry-value.ll
    llvm/trunk/test/Verifier/diexpression-entry-value-llvm-ir.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm/BinaryFormat/Dwarf.h
    llvm/trunk/include/llvm/CodeGen/MachineInstr.h
    llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
    llvm/trunk/lib/BinaryFormat/Dwarf.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
    llvm/trunk/lib/IR/DebugInfoMetadata.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/test/DebugInfo/MIR/Hexagon/live-debug-values-bundled-entry-values.mir
    llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir
    llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir
    llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir
    llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir
    llvm/trunk/test/Verifier/diexpression-entry-value.ll
    llvm/trunk/test/Verifier/diexpression-valid-entry-value.ll

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Tue Oct 15 04:31:21 2019
@@ -4793,17 +4793,24 @@ The current supported opcode vocabulary
   of the stack is treated as an address. The second stack entry is treated as an
   address space identifier.
 - ``DW_OP_stack_value`` marks a constant value.
-- If an expression is marked with ``DW_OP_entry_value`` all register and
-  memory read operations refer to the respective value at the function entry.
-  The first operand of ``DW_OP_entry_value`` is the size of following
-  DWARF expression.
-  ``DW_OP_entry_value`` may appear after the ``LiveDebugValues`` pass.
-  LLVM only supports entry values for function parameters
-  that are unmodified throughout a function and that are described as
-  simple register location descriptions.
-  ``DW_OP_entry_value`` may also appear after the ``AsmPrinter`` pass when
-  a call site parameter value (``DW_AT_call_site_parameter_value``)
-  is represented as entry value of the parameter.
+- ``DW_OP_LLVM_entry_value, N`` can only appear at the beginning of a
+  ``DIExpression``, and it specifies that all register and memory read
+  operations for the debug value instruction's value/address operand and for
+  the ``(N - 1)`` operations immediately following the
+  ``DW_OP_LLVM_entry_value`` refer to their respective values at function
+  entry. For example, ``!DIExpression(DW_OP_LLVM_entry_value, 1,
+  DW_OP_plus_uconst, 123, DW_OP_stack_value)`` specifies an expression where
+  the entry value of the debug value instruction's value/address operand is
+  pushed to the stack, and is added with 123. Due to framework limitations
+  ``N`` can currently only be 1.
+
+  ``DW_OP_LLVM_entry_value`` is only legal in MIR. The operation is introduced
+  by the ``LiveDebugValues`` pass; currently only for function parameters that
+  are unmodified throughout a function and that are described as simple
+  register location descriptions. The operation is also introduced by the
+  ``AsmPrinter`` pass when a call site parameter value
+  (``DW_AT_call_site_parameter_value``) is represented as entry value of the
+  parameter.
 - ``DW_OP_breg`` (or ``DW_OP_bregx``) represents a content on the provided
   signed offset of the specified register. The opcode is only generated by the
   ``AsmPrinter`` pass to describe call site parameter value which requires an
@@ -4852,7 +4859,7 @@ These flags encode various properties of
 
 The `ArgumentNotModified` flag marks a function argument whose value
 is not modified throughout of a function. This flag is used to decide
-whether a DW_OP_entry_value can be used in a location description
+whether a DW_OP_LLVM_entry_value can be used in a location description
 after the function prologue. The language frontend is expected to compute
 this property for each DILocalVariable. The flag should be used
 only in optimized code.

Modified: llvm/trunk/include/llvm/BinaryFormat/Dwarf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Dwarf.h?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Dwarf.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Dwarf.h Tue Oct 15 04:31:21 2019
@@ -117,9 +117,10 @@ enum LocationAtom {
 #include "llvm/BinaryFormat/Dwarf.def"
   DW_OP_lo_user = 0xe0,
   DW_OP_hi_user = 0xff,
-  DW_OP_LLVM_fragment = 0x1000,   ///< Only used in LLVM metadata.
-  DW_OP_LLVM_convert = 0x1001,    ///< Only used in LLVM metadata.
-  DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata.
+  DW_OP_LLVM_fragment = 0x1000,    ///< Only used in LLVM metadata.
+  DW_OP_LLVM_convert = 0x1001,     ///< Only used in LLVM metadata.
+  DW_OP_LLVM_tag_offset = 0x1002,  ///< Only used in LLVM metadata.
+  DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata.
 };
 
 enum TypeKind : uint8_t {

Modified: llvm/trunk/include/llvm/CodeGen/MachineInstr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineInstr.h?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineInstr.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineInstr.h Tue Oct 15 04:31:21 2019
@@ -1042,7 +1042,7 @@ public:
   }
 
   /// A DBG_VALUE is an entry value iff its debug expression contains the
-  /// DW_OP_entry_value DWARF operation.
+  /// DW_OP_LLVM_entry_value operation.
   bool isDebugEntryValue() const {
     return isDebugValue() && getDebugExpression()->isEntryValue();
   }

Modified: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoMetadata.h?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h (original)
+++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h Tue Oct 15 04:31:21 2019
@@ -2569,7 +2569,7 @@ public:
   /// (This is the only configuration of entry values that is supported.)
   bool isEntryValue() const {
     return getNumElements() > 0 &&
-           getElement(0) == dwarf::DW_OP_entry_value;
+           getElement(0) == dwarf::DW_OP_LLVM_entry_value;
   }
 };
 

Modified: llvm/trunk/lib/BinaryFormat/Dwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/Dwarf.cpp?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/Dwarf.cpp (original)
+++ llvm/trunk/lib/BinaryFormat/Dwarf.cpp Tue Oct 15 04:31:21 2019
@@ -149,6 +149,8 @@ StringRef llvm::dwarf::OperationEncoding
     return "DW_OP_LLVM_fragment";
   case DW_OP_LLVM_tag_offset:
     return "DW_OP_LLVM_tag_offset";
+  case DW_OP_LLVM_entry_value:
+    return "DW_OP_LLVM_entry_value";
   }
 }
 
@@ -160,6 +162,7 @@ unsigned llvm::dwarf::getOperationEncodi
       .Case("DW_OP_LLVM_convert", DW_OP_LLVM_convert)
       .Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment)
       .Case("DW_OP_LLVM_tag_offset", DW_OP_LLVM_tag_offset)
+      .Case("DW_OP_LLVM_entry_value", DW_OP_LLVM_entry_value)
       .Default(0);
 }
 

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp Tue Oct 15 04:31:21 2019
@@ -41,7 +41,7 @@ using EntryIndex = DbgValueHistoryMap::E
 static Register isDescribedByReg(const MachineInstr &MI) {
   assert(MI.isDebugValue());
   assert(MI.getNumOperands() == 4);
-  // If the location of variable is an entry value (DW_OP_entry_value)
+  // If the location of variable is an entry value (DW_OP_LLVM_entry_value)
   // do not consider it as a register location.
   if (MI.getDebugExpression()->isEntryValue())
     return 0;

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Tue Oct 15 04:31:21 2019
@@ -1205,7 +1205,7 @@ void DwarfCompileUnit::addComplexAddress
 
   if (DIExpr->isEntryValue()) {
     DwarfExpr.setEntryValueFlag();
-    DwarfExpr.addEntryValueExpression(Cursor);
+    DwarfExpr.beginEntryValueExpression(Cursor);
   }
 
   const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Oct 15 04:31:21 2019
@@ -669,10 +669,9 @@ static void collectCallSiteParameters(co
 
   // Emit the call site parameter's value as an entry value.
   if (ShouldTryEmitEntryVals) {
-    // Create an entry value expression where the expression following
-    // the 'DW_OP_entry_value' will be the size of 1 (a register operation).
-    DIExpression *EntryExpr = DIExpression::get(MF->getFunction().getContext(),
-                                                {dwarf::DW_OP_entry_value, 1});
+    // Create an expression where the register's entry value is used.
+    DIExpression *EntryExpr = DIExpression::get(
+        MF->getFunction().getContext(), {dwarf::DW_OP_LLVM_entry_value, 1});
     for (auto RegEntry : ForwardedRegWorklist) {
       unsigned FwdReg = RegEntry;
       auto EntryValReg = RegsForEntryValues.find(RegEntry);
@@ -2200,7 +2199,7 @@ void DwarfDebug::emitDebugLocValue(const
 
     if (DIExpr->isEntryValue()) {
       DwarfExpr.setEntryValueFlag();
-      DwarfExpr.addEntryValueExpression(Cursor);
+      DwarfExpr.beginEntryValueExpression(Cursor);
     }
 
     const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp Tue Oct 15 04:31:21 2019
@@ -254,6 +254,9 @@ bool DwarfExpression::addMachineRegExpre
       addOpPiece(Reg.Size);
     }
 
+    if (isEntryValue())
+      finalizeEntryValue();
+
     if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4)
       emitOp(dwarf::DW_OP_stack_value);
 
@@ -313,14 +316,33 @@ bool DwarfExpression::addMachineRegExpre
   return true;
 }
 
-void DwarfExpression::addEntryValueExpression(DIExpressionCursor &ExprCursor) {
+void DwarfExpression::beginEntryValueExpression(
+    DIExpressionCursor &ExprCursor) {
   auto Op = ExprCursor.take();
-  assert(Op && Op->getOp() == dwarf::DW_OP_entry_value);
+  assert(Op && Op->getOp() == dwarf::DW_OP_LLVM_entry_value);
   assert(!isMemoryLocation() &&
          "We don't support entry values of memory locations yet");
+  assert(!IsEmittingEntryValue && "Already emitting entry value?");
+  assert(Op->getArg(0) == 1 &&
+         "Can currently only emit entry values covering a single operation");
 
   emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value));
-  emitUnsigned(Op->getArg(0));
+  IsEmittingEntryValue = true;
+  enableTemporaryBuffer();
+}
+
+void DwarfExpression::finalizeEntryValue() {
+  assert(IsEmittingEntryValue && "Entry value not open?");
+  disableTemporaryBuffer();
+
+  // Emit the entry value's size operand.
+  unsigned Size = getTemporaryBufferSize();
+  emitUnsigned(Size);
+
+  // Emit the entry value's DWARF block operand.
+  commitTemporaryBuffer();
+
+  IsEmittingEntryValue = false;
 }
 
 /// Assuming a well-formed expression, match "DW_OP_deref* DW_OP_LLVM_fragment?".

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h Tue Oct 15 04:31:21 2019
@@ -111,6 +111,9 @@ protected:
     const char *Comment;
   };
 
+  /// Whether we are currently emitting an entry value operation.
+  bool IsEmittingEntryValue = false;
+
   DwarfCompileUnit &CU;
 
   /// The register location, if any.
@@ -260,6 +263,10 @@ protected:
   /// expression.  See PR21176 for more details.
   void addStackValue();
 
+  /// Finalize an entry value by emitting its size operand, and committing the
+  /// DWARF block which has been emitted to the temporary buffer.
+  void finalizeEntryValue();
+
   ~DwarfExpression() = default;
 
 public:
@@ -310,8 +317,11 @@ public:
                                DIExpressionCursor &Expr, unsigned MachineReg,
                                unsigned FragmentOffsetInBits = 0);
 
-  /// Emit entry value dwarf operation.
-  void addEntryValueExpression(DIExpressionCursor &ExprCursor);
+  /// Begin emission of an entry value dwarf operation. The entry value's
+  /// first operand is the size of the DWARF block (its second operand),
+  /// which needs to be calculated at time of emission, so we don't emit
+  /// any operands here.
+  void beginEntryValueExpression(DIExpressionCursor &ExprCursor);
 
   /// Emit all remaining operations in the DIExpressionCursor.
   ///

Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)
+++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Tue Oct 15 04:31:21 2019
@@ -843,7 +843,7 @@ unsigned DIExpression::ExprOperand::getS
   case dwarf::DW_OP_deref_size:
   case dwarf::DW_OP_plus_uconst:
   case dwarf::DW_OP_LLVM_tag_offset:
-  case dwarf::DW_OP_entry_value:
+  case dwarf::DW_OP_LLVM_entry_value:
   case dwarf::DW_OP_regx:
     return 2;
   default:
@@ -890,10 +890,12 @@ bool DIExpression::isValid() const {
         return false;
       break;
     }
-    case dwarf::DW_OP_entry_value: {
-      // An entry value operator must appear at the begin and the size
-      // of following expression should be 1, because we support only
-      // entry values of a simple register location.
+    case dwarf::DW_OP_LLVM_entry_value: {
+      // An entry value operator must appear at the beginning and the number of
+      // operations it cover can currently only be 1, because we support only
+      // entry values of a simple register location. One reason for this is that
+      // we currently can't calculate the size of the resulting DWARF block for
+      // other expressions.
       return I->get() == expr_op_begin()->get() && I->getArg(0) == 1 &&
              getNumElements() == 2;
     }
@@ -1050,7 +1052,7 @@ DIExpression *DIExpression::prependOpcod
   assert(Expr && "Can't prepend ops to this expression");
 
   if (EntryValue) {
-    Ops.push_back(dwarf::DW_OP_entry_value);
+    Ops.push_back(dwarf::DW_OP_LLVM_entry_value);
     // Add size info needed for entry value expression.
     // Add plus one for target register operand.
     Ops.push_back(Expr->getNumElements() + 1);

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Tue Oct 15 04:31:21 2019
@@ -518,6 +518,7 @@ private:
                                 DIExpression::FragmentInfo Fragment,
                                 ValueOrMetadata *Desc);
   void verifyFnArgs(const DbgVariableIntrinsic &I);
+  void verifyNotEntryValue(const DbgVariableIntrinsic &I);
 
   /// Module-level debug info verification...
   void verifyCompileUnits();
@@ -4213,8 +4214,10 @@ void Verifier::visitInstruction(Instruct
     visitMDNode(*N);
   }
 
-  if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I))
+  if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) {
     verifyFragmentExpression(*DII);
+    verifyNotEntryValue(*DII);
+  }
 
   InstsInThisBlock.insert(&I);
 }
@@ -5047,6 +5050,16 @@ void Verifier::verifyFnArgs(const DbgVar
            Prev, Var);
 }
 
+void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) {
+  DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression());
+
+  // We don't know whether this intrinsic verified correctly.
+  if (!E || !E->isValid())
+    return;
+
+  AssertDI(!E->isEntryValue(), "Entry values are only allowed in MIR", &I);
+}
+
 void Verifier::verifyCompileUnits() {
   // When more than one Module is imported into the same context, such as during
   // an LTO build before linking the modules, ODR type uniquing may cause types

Added: llvm/trunk/test/DebugInfo/ARM/entry-value-multi-byte-expr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/ARM/entry-value-multi-byte-expr.ll?rev=374881&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/ARM/entry-value-multi-byte-expr.ll (added)
+++ llvm/trunk/test/DebugInfo/ARM/entry-value-multi-byte-expr.ll Tue Oct 15 04:31:21 2019
@@ -0,0 +1,91 @@
+; RUN: llc -debug-entry-values -filetype=asm -o - %s | FileCheck %s
+
+; Verify that the size operands of the DW_OP_GNU_entry_value operations are
+; correct for the multi-byte DW_OP_regx expressions.
+
+; Based on the following C reproducer:
+;
+; extern void clobber();
+; double global;
+; int f(double a, double b) {
+;   global = a + b;
+;   clobber();
+;   return 1;
+; }
+
+; This test checks the assembly output rather than the output from
+; llvm-dwarfdump, as the latter printed the DW_OP_regx D0 correctly, even
+; though the entry value's size operand did not fully cover that:
+
+; DW_OP_GNU_entry_value(DW_OP_regx D0), DW_OP_stack_value
+;
+; whereas readelf interpreted it as an DW_OP_GNU_entry_value covering one byte,
+; resulting in garbage data:
+;
+; DW_OP_GNU_entry_value: (DW_OP_regx: 0 (r0)); DW_OP_breg16 (r16): 2; DW_OP_stack_value
+
+; CHECK:      .byte   243       @ DW_OP_GNU_entry_value
+; CHECK-NEXT: .byte   3         @ 3
+; CHECK-NEXT: .byte   144       @ DW_OP_regx
+; CHECK-NEXT: .byte   128       @ 256
+; CHECK-NEXT: .byte   2         @
+; CHECK-NEXT: .byte   159       @ DW_OP_stack_value
+
+; CHECK:      .byte   243       @ DW_OP_GNU_entry_value
+; CHECK-NEXT: .byte   3         @ 3
+; CHECK-NEXT: .byte   144       @ DW_OP_regx
+; CHECK-NEXT: .byte   129       @ 257
+; CHECK-NEXT: .byte   2         @
+; CHECK-NEXT: .byte   159       @ DW_OP_stack_value
+
+target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "armv7-unknown-unknown"
+
+ at global = common global double 0.000000e+00, align 8, !dbg !0
+
+; Function Attrs: nounwind
+define arm_aapcs_vfpcc i32 @f(double %a, double %b) #0 !dbg !12 {
+entry:
+  call void @llvm.dbg.value(metadata double %a, metadata !17, metadata !DIExpression()), !dbg !19
+  call void @llvm.dbg.value(metadata double %b, metadata !18, metadata !DIExpression()), !dbg !19
+  %add = fadd double %a, %b, !dbg !20
+  store double %add, double* @global, align 8, !dbg !20
+  tail call arm_aapcs_vfpcc void @clobber(), !dbg !21
+  ret i32 1, !dbg !22
+}
+
+declare arm_aapcs_vfpcc void @clobber()
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!7, !8, !9, !10}
+!llvm.ident = !{!11}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "global", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "entry-value-multi-byte-expr.c", directory: "/")
+!4 = !{}
+!5 = !{!0}
+!6 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"wchar_size", i32 4}
+!10 = !{i32 1, !"min_enum_size", i32 4}
+!11 = !{!"clang version 10.0.0"}
+!12 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 6, type: !13, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!15, !6, !6}
+!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!16 = !{!17, !18}
+!17 = !DILocalVariable(name: "a", arg: 1, scope: !12, file: !3, line: 6, type: !6, flags: DIFlagArgumentNotModified)
+!18 = !DILocalVariable(name: "b", arg: 2, scope: !12, file: !3, line: 6, type: !6, flags: DIFlagArgumentNotModified)
+!19 = !DILocation(line: 0, scope: !12)
+!20 = !DILocation(line: 7, scope: !12)
+!21 = !DILocation(line: 8, scope: !12)
+!22 = !DILocation(line: 9, scope: !12)

Modified: llvm/trunk/test/DebugInfo/MIR/Hexagon/live-debug-values-bundled-entry-values.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/Hexagon/live-debug-values-bundled-entry-values.mir?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/Hexagon/live-debug-values-bundled-entry-values.mir (original)
+++ llvm/trunk/test/DebugInfo/MIR/Hexagon/live-debug-values-bundled-entry-values.mir Tue Oct 15 04:31:21 2019
@@ -98,7 +98,7 @@ body:             |
 # CHECK-NEXT: $r29 = S2_allocframe $r29, 0
 # CHECK-NEXT: J2_call @clobber
 # CHECK-NEXT: }
-# CHECK-NEXT: DBG_VALUE $r0, $noreg, !16, !DIExpression(DW_OP_entry_value, 1)
+# CHECK-NEXT: DBG_VALUE $r0, $noreg, !16, !DIExpression(DW_OP_LLVM_entry_value, 1)
 
 ---
 name:            bar
@@ -136,4 +136,4 @@ body:             |
 # CHECK-NEXT: $r29 = S2_allocframe $r29, 0
 # CHECK-NEXT: J2_call @clobber
 # CHECK-NEXT: }
-# CHECK-NEXT: DBG_VALUE $r0, $noreg, !22, !DIExpression(DW_OP_entry_value, 1)
+# CHECK-NEXT: DBG_VALUE $r0, $noreg, !22, !DIExpression(DW_OP_LLVM_entry_value, 1)

Modified: llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir (original)
+++ llvm/trunk/test/DebugInfo/MIR/X86/avoid-single-entry-value-location.mir Tue Oct 15 04:31:21 2019
@@ -61,7 +61,7 @@ body:             |
     DBG_VALUE $edi, $noreg, !16, !DIExpression(), debug-location !18
     DBG_VALUE $edi, $noreg, !17, !DIExpression(), debug-location !18
     $edi = KILL renamable $edi, implicit killed $rdi, debug-location !18
-    DBG_VALUE $rdi, $noreg, !16, !DIExpression(DW_OP_entry_value, 1), debug-location !18
+    DBG_VALUE $rdi, $noreg, !16, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !18
     TAILJMPd64 @fn2, csr_64, implicit $rsp, implicit $ssp, implicit $rsp, implicit $ssp, implicit killed $edi, debug-location !18
 
 ...

Modified: llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir (original)
+++ llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir Tue Oct 15 04:31:21 2019
@@ -190,10 +190,10 @@ body:             |
     $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
     CFI_INSTRUCTION def_cfa_offset 24, debug-location !21
     $r14 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
-    DBG_VALUE $ecx, $noreg, !17, !DIExpression(DW_OP_entry_value, 1), debug-location !21
+    DBG_VALUE $ecx, $noreg, !17, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !21
     CFI_INSTRUCTION def_cfa_offset 16, debug-location !21
     $r15 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
-    DBG_VALUE $esi, $noreg, !15, !DIExpression(DW_OP_entry_value, 1), debug-location !21
+    DBG_VALUE $esi, $noreg, !15, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !21
     CFI_INSTRUCTION def_cfa_offset 8, debug-location !21
     RETQ $eax, debug-location !21
 

Modified: llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir (original)
+++ llvm/trunk/test/DebugInfo/MIR/X86/dbginfo-entryvals.mir Tue Oct 15 04:31:21 2019
@@ -14,8 +14,8 @@
 #  fn2 (a);
 #  u --;
 #}
-# CHECK: DBG_VALUE $edi, $noreg, !14, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
-# CHECK: DBG_VALUE $esi, $noreg, !15, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
+# CHECK: DBG_VALUE $edi, $noreg, !14, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location {{.*}}
+# CHECK: DBG_VALUE $esi, $noreg, !15, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location {{.*}}
 
 --- |
   ; ModuleID = 'test.c'

Modified: llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir (original)
+++ llvm/trunk/test/DebugInfo/MIR/X86/multiple-param-dbg-value-entry.mir Tue Oct 15 04:31:21 2019
@@ -7,11 +7,11 @@
 #  return 123;
 #}
 #
-# Verify that DW_OP_entry_values are generated for parameters with multiple
+# Verify that DW_OP_LLVM_entry_values are generated for parameters with multiple
 # DBG_VALUEs at entry block.
-# CHECK: DBG_VALUE $edi, $noreg, !{{.*}}, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
-# CHECK: DBG_VALUE $edx, $noreg, !{{.*}}, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
-# CHECK: DBG_VALUE $esi, $noreg, !{{.*}}, !DIExpression(DW_OP_entry_value, 1), debug-location {{.*}}
+# CHECK: DBG_VALUE $edi, $noreg, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location {{.*}}
+# CHECK: DBG_VALUE $edx, $noreg, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location {{.*}}
+# CHECK: DBG_VALUE $esi, $noreg, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location {{.*}}
 
 --- |
   ; ModuleID = 'multiple-param-dbg-value-entry.ll'

Added: llvm/trunk/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll?rev=374881&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll (added)
+++ llvm/trunk/test/DebugInfo/Sparc/entry-value-complex-reg-expr.ll Tue Oct 15 04:31:21 2019
@@ -0,0 +1,79 @@
+; 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.
+;
+; 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.
+
+target datalayout = "E-m:e-i64:64-n32:64-S128"
+target triple = "sparc64"
+
+; Based on the following C reproducer:
+;
+; volatile long double global;
+; extern void clobber();
+; int foo(long double p) {
+;   global = p;
+;   clobber();
+;   return 123;
+; }
+
+; CHECK:      .byte   243       ! DW_OP_GNU_entry_value
+; CHECK-NEXT: .byte   8         ! 8
+; CHECK-NEXT: .byte   144       ! sub-register DW_OP_regx
+; CHECK-NEXT: .byte   72        ! 72
+; CHECK-NEXT: .byte   147       ! DW_OP_piece
+; CHECK-NEXT: .byte   8         ! 8
+; CHECK-NEXT: .byte   144       ! sub-register DW_OP_regx
+; 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
+
+ at global = common global fp128 0xL00000000000000000000000000000000, align 16, !dbg !0
+
+; Function Attrs: nounwind
+define signext i32 @foo(fp128 %p) #0 !dbg !12 {
+entry:
+  call void @llvm.dbg.value(metadata fp128 %p, metadata !17, metadata !DIExpression()), !dbg !18
+  store volatile fp128 %p, fp128* @global, align 16, !dbg !19
+  tail call void @clobber(), !dbg !20
+  ret i32 123, !dbg !21
+}
+
+declare void @clobber()
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!8, !9, !10}
+!llvm.ident = !{!11}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "global", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "entry-value-complex-reg-expr.c", directory: "/")
+!4 = !{}
+!5 = !{!0}
+!6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
+!7 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float)
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{i32 1, !"wchar_size", i32 4}
+!11 = !{!"clang version 10.0.0"}
+!12 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 3, type: !13, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!15, !7}
+!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!16 = !{!17}
+!17 = !DILocalVariable(name: "p", arg: 1, scope: !12, file: !3, line: 3, type: !7, flags: DIFlagArgumentNotModified)
+!18 = !DILocation(line: 0, scope: !12)
+!19 = !DILocation(line: 4, scope: !12)
+!20 = !DILocation(line: 5, scope: !12)
+!21 = !DILocation(line: 6, scope: !12)

Added: llvm/trunk/test/Verifier/diexpression-dwarf-entry-value.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/diexpression-dwarf-entry-value.ll?rev=374881&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/diexpression-dwarf-entry-value.ll (added)
+++ llvm/trunk/test/Verifier/diexpression-dwarf-entry-value.ll Tue Oct 15 04:31:21 2019
@@ -0,0 +1,8 @@
+; RUN: not opt -S < %s 2>&1 | FileCheck %s
+
+; We can only use the internal variant of the entry value operation,
+; DW_OP_LLVM_entry_value, in DIExpressions.
+
+!named = !{!0}
+; CHECK: invalid expression
+!0 = !DIExpression(DW_OP_entry_value, 1)

Added: llvm/trunk/test/Verifier/diexpression-entry-value-llvm-ir.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/diexpression-entry-value-llvm-ir.ll?rev=374881&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/diexpression-entry-value-llvm-ir.ll (added)
+++ llvm/trunk/test/Verifier/diexpression-entry-value-llvm-ir.ll Tue Oct 15 04:31:21 2019
@@ -0,0 +1,31 @@
+; RUN: llvm-as -disable-output <%s 2>&1| FileCheck %s
+
+; The DW_OP_LLVM_entry_value operation can only be used in MIR.
+
+; CHECK: Entry values are only allowed in MIR
+; CHECK: call void @llvm.dbg.value(metadata i32 %param, metadata !{{.*}}, metadata !DIExpression(DW_OP_LLVM_entry_value, 1))
+; CHECK: warning: ignoring invalid debug info
+
+define void @foo(i32 %param) !dbg !4 {
+entry:
+  call void @llvm.dbg.value(metadata i32 %param, metadata !8, metadata !DIExpression(DW_OP_LLVM_entry_value, 1)), !dbg !9
+  ret void
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "a.c", directory: "/")
+!2 = !{i32 2, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, type: !5, unit: !0)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null, !7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !DILocalVariable(name: "param", arg: 1, scope: !4, file: !1, type: !7)
+!9 = !DILocation(line: 0, scope: !4)

Modified: llvm/trunk/test/Verifier/diexpression-entry-value.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/diexpression-entry-value.ll?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/diexpression-entry-value.ll (original)
+++ llvm/trunk/test/Verifier/diexpression-entry-value.ll Tue Oct 15 04:31:21 2019
@@ -2,6 +2,11 @@
 
 !named = !{!0, !1, !2}
 ; CHECK: invalid expression
-!0 = !DIExpression(DW_OP_entry_value, 4, DW_OP_constu, 0, DW_OP_stack_value)
-!1 = !DIExpression(DW_OP_constu, 0, DW_OP_entry_value, 1, DW_OP_constu, 0)
-!2 = !DIExpression(DW_OP_entry_value, 100, DW_OP_constu, 0)
+; CHECK-NEXT: !DIExpression
+; CHECK: invalid expression
+; CHECK-NEXT: !DIExpression
+; CHECK: invalid expression
+; CHECK-NEXT: !DIExpression
+!0 = !DIExpression(DW_OP_LLVM_entry_value, 4, DW_OP_constu, 0, DW_OP_stack_value)
+!1 = !DIExpression(DW_OP_constu, 0, DW_OP_LLVM_entry_value, 1, DW_OP_constu, 0)
+!2 = !DIExpression(DW_OP_LLVM_entry_value, 100, DW_OP_constu, 0)

Modified: llvm/trunk/test/Verifier/diexpression-valid-entry-value.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/diexpression-valid-entry-value.ll?rev=374881&r1=374880&r2=374881&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/diexpression-valid-entry-value.ll (original)
+++ llvm/trunk/test/Verifier/diexpression-valid-entry-value.ll Tue Oct 15 04:31:21 2019
@@ -2,4 +2,4 @@
 
 !named = !{!0}
 ; CHECK-NOT: invalid expression
-!0 = !DIExpression(DW_OP_entry_value, 1)
+!0 = !DIExpression(DW_OP_LLVM_entry_value, 1)




More information about the llvm-commits mailing list