[llvm] r289266 - Fix LLVM's use of DW_OP_bit_piece in DWARF expressions.

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 9 12:43:40 PST 2016


Author: adrian
Date: Fri Dec  9 14:43:40 2016
New Revision: 289266

URL: http://llvm.org/viewvc/llvm-project?rev=289266&view=rev
Log:
Fix LLVM's use of DW_OP_bit_piece in DWARF expressions.

LLVM's use of DW_OP_bit_piece is incorrect and a based on a
misunderstanding of the wording in the DWARF specification. The offset
argument of DW_OP_bit_piece refers to the offset into the location
that is on the top of the DWARF expression stack, and not an offset
into the source variable. This has since also been clarified in the
DWARF specification.

This patch fixes all uses of DW_OP_bit_piece to emit the correct
offset and simplifies the DwarfExpression class to semi-automaticaly
emit empty DW_OP_pieces to adjust the offset of the source variable,
thus simplifying the code using DwarfExpression.

While this is an incompatible bugfix, in practice I don't expect this
to be much of a problem since LLVM's old interpretation and the
correct interpretation of DW_OP_bit_piece differ only when there are
gaps in the fragmented locations of the described variables or if
individual fragments are smaller than a byte. LLDB at least won't
interpret locations with gaps in them because is has no way to present
undefined bits in a variable, and there is a high probability that an
old-form expression will be malformed when interpreted correctly,
because the DW_OP_bit_piece offset will be outside of the location at
the top of the stack.

As a nice side-effect, this patch enables us to use a more efficient
encoding for subregisters: In order to express a sub-register at a
non-zero offset we now use a DW_OP_bit_piece instead of shifting the
value into place manually.

This patch also adds missing test coverage for code paths that weren't
exercised before.

<rdar://problem/29335809>
Differential Revision: https://reviews.llvm.org/D27550

Added:
    llvm/trunk/test/DebugInfo/MIR/ARM/
    llvm/trunk/test/DebugInfo/MIR/ARM/lit.local.cfg
    llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg-piece.mir
    llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg.mir
    llvm/trunk/test/DebugInfo/MIR/X86/bit-piece-dh.mir
    llvm/trunk/test/DebugInfo/X86/dw_op_minus_direct.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/AsmPrinter.h
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.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/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
    llvm/trunk/test/DebugInfo/AArch64/frameindices.ll
    llvm/trunk/test/DebugInfo/X86/PR26148.ll

Modified: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/AsmPrinter.h?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h (original)
+++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h Fri Dec  9 14:43:40 2016
@@ -468,10 +468,6 @@ public:
   /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified.
   virtual unsigned getISAEncoding() { return 0; }
 
-  /// EmitDwarfRegOp - Emit a dwarf register operation.
-  virtual void EmitDwarfRegOp(ByteStreamer &BS,
-                              const MachineLocation &MLoc) const;
-
   //===------------------------------------------------------------------===//
   // Dwarf Lowering Routines
   //===------------------------------------------------------------------===//

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp Fri Dec  9 14:43:40 2016
@@ -174,36 +174,6 @@ void AsmPrinter::emitDwarfStringOffset(D
   EmitInt32(S.getOffset());
 }
 
-/// EmitDwarfRegOp - Emit dwarf register operation.
-void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer,
-                                const MachineLocation &MLoc) const {
-  DebugLocDwarfExpression Expr(getDwarfVersion(), Streamer);
-  const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo();
-  int Reg = MRI->getDwarfRegNum(MLoc.getReg(), false);
-  if (Reg < 0) {
-    // We assume that pointers are always in an addressable register.
-    if (MLoc.isIndirect())
-      // FIXME: We have no reasonable way of handling errors in here. The
-      // caller might be in the middle of a dwarf expression. We should
-      // probably assert that Reg >= 0 once debug info generation is more
-      // mature.
-      return Expr.EmitOp(dwarf::DW_OP_nop,
-                         "nop (could not find a dwarf register number)");
-
-    // Attempt to find a valid super- or sub-register.
-    if (!Expr.AddMachineRegFragment(*MF->getSubtarget().getRegisterInfo(),
-                                    MLoc.getReg()))
-      Expr.EmitOp(dwarf::DW_OP_nop,
-                  "nop (could not find a dwarf register number)");
-    return;
-  }
-
-  if (MLoc.isIndirect())
-    Expr.AddRegIndirect(Reg, MLoc.getOffset());
-  else
-    Expr.AddReg(Reg);
-}
-
 //===----------------------------------------------------------------------===//
 // Dwarf Lowering Routines
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Fri Dec  9 14:43:40 2016
@@ -180,7 +180,9 @@ DIE *DwarfCompileUnit::getOrCreateGlobal
 
       if (Expr) {
         DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+        DwarfExpr.addFragmentOffset(Expr);
         DwarfExpr.AddExpression(Expr);
+        DwarfExpr.finalize();
       }
     }
 
@@ -498,8 +500,10 @@ DIE *DwarfCompileUnit::constructVariable
         DIELoc *Loc = new (DIEValueAllocator) DIELoc;
         DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
         // If there is an expression, emit raw unsigned bytes.
+        DwarfExpr.addFragmentOffset(Expr);
         DwarfExpr.AddUnsignedConstant(DVInsn->getOperand(0).getImm());
         DwarfExpr.AddExpression(Expr);
+        DwarfExpr.finalize();
         addBlock(*VariableDie, dwarf::DW_AT_location, Loc);
       } else
         addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType());
@@ -524,11 +528,13 @@ DIE *DwarfCompileUnit::constructVariable
     const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
     int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
     assert(Expr != DV.getExpression().end() && "Wrong number of expressions");
+    DwarfExpr.addFragmentOffset(*Expr);
     DwarfExpr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
                                     FrameReg, Offset);
     DwarfExpr.AddExpression(*Expr);
     ++Expr;
   }
+  DwarfExpr.finalize();
   addBlock(*VariableDie, dwarf::DW_AT_location, Loc);
 
   return VariableDie;
@@ -727,16 +733,22 @@ void DwarfCompileUnit::addVariableAddres
 void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
                                   const MachineLocation &Location) {
   DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+  DIEDwarfExpression Expr(*Asm, *this, *Loc);
 
   bool validReg;
   if (Location.isReg())
-    validReg = addRegisterFragment(*Loc, Location.getReg());
+    validReg = Expr.AddMachineReg(*Asm->MF->getSubtarget().getRegisterInfo(),
+                                  Location.getReg());
   else
-    validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
+    validReg =
+        Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
+                                   Location.getReg(), Location.getOffset());
 
   if (!validReg)
     return;
 
+  Expr.finalize();
+
   // Now attach the location information to the DIE.
   addBlock(Die, Attribute, Loc);
 }
@@ -750,9 +762,11 @@ void DwarfCompileUnit::addComplexAddress
                                          const MachineLocation &Location) {
   DIELoc *Loc = new (DIEValueAllocator) DIELoc;
   DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
-  DIExpressionCursor ExprCursor(DV.getSingleExpression());
+  const DIExpression *Expr = DV.getSingleExpression();
+  DIExpressionCursor ExprCursor(Expr);
   const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
   auto Reg = Location.getReg();
+  DwarfExpr.addFragmentOffset(Expr);
   bool ValidReg =
       Location.getOffset()
           ? DwarfExpr.AddMachineRegIndirect(TRI, Reg, Location.getOffset())

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Fri Dec  9 14:43:40 2016
@@ -1413,9 +1413,9 @@ void DwarfDebug::emitDebugLocEntry(ByteS
 static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
                               ByteStreamer &Streamer,
                               const DebugLocEntry::Value &Value,
-                              unsigned FragmentOffsetInBits) {
+                              DwarfExpression &DwarfExpr) {
   DIExpressionCursor ExprCursor(Value.getExpression());
-  DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer);
+  DwarfExpr.addFragmentOffset(Value.getExpression());
   // Regular entry.
   if (Value.isInt()) {
     if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
@@ -1425,23 +1425,16 @@ static void emitDebugLocValue(const AsmP
       DwarfExpr.AddUnsignedConstant(Value.getInt());
   } else if (Value.isLocation()) {
     MachineLocation Loc = Value.getLoc();
-    if (!ExprCursor)
-      // Regular entry.
-      AP.EmitDwarfRegOp(Streamer, Loc);
-    else {
-      // Complex address entry.
-      const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
-      if (Loc.getOffset())
-        DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset());
-      else
-        DwarfExpr.AddMachineRegExpression(TRI, ExprCursor, Loc.getReg(),
-                                          FragmentOffsetInBits);
-    }
+    const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
+    if (Loc.getOffset())
+      DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset());
+    else
+      DwarfExpr.AddMachineRegExpression(TRI, ExprCursor, Loc.getReg());
   } else if (Value.isConstantFP()) {
     APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
     DwarfExpr.AddUnsignedConstant(RawBytes);
   }
-  DwarfExpr.AddExpression(std::move(ExprCursor), FragmentOffsetInBits);
+  DwarfExpr.AddExpression(std::move(ExprCursor));
 }
 
 void DebugLocEntry::finalize(const AsmPrinter &AP,
@@ -1449,6 +1442,7 @@ void DebugLocEntry::finalize(const AsmPr
                              const DIBasicType *BT) {
   DebugLocStream::EntryBuilder Entry(List, Begin, End);
   BufferByteStreamer Streamer = Entry.getStreamer();
+  DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer);
   const DebugLocEntry::Value &Value = Values[0];
   if (Value.isFragment()) {
     // Emit all fragments that belong to the same variable and range.
@@ -1457,27 +1451,15 @@ void DebugLocEntry::finalize(const AsmPr
         }) && "all values are expected to be fragments");
     assert(std::is_sorted(Values.begin(), Values.end()) &&
            "fragments are expected to be sorted");
-   
-    unsigned Offset = 0;
-    for (auto Fragment : Values) {
-      const DIExpression *Expr = Fragment.getExpression();
-      unsigned FragmentOffset = Expr->getFragmentOffsetInBits();
-      unsigned FragmentSize = Expr->getFragmentSizeInBits();
-      assert(Offset <= FragmentOffset && "overlapping or duplicate fragments");
-      if (Offset < FragmentOffset) {
-        // DWARF represents gaps as pieces with no locations.
-        DebugLocDwarfExpression Expr(AP.getDwarfVersion(), Streamer);
-        Expr.AddOpPiece(FragmentOffset-Offset, 0);
-        Offset += FragmentOffset-Offset;
-      }
-      Offset += FragmentSize;
 
-      emitDebugLocValue(AP, BT, Streamer, Fragment, FragmentOffset);
-    }
+    for (auto Fragment : Values)
+      emitDebugLocValue(AP, BT, Streamer, Fragment, DwarfExpr);
+
   } else {
     assert(Values.size() == 1 && "only fragments may have >1 value");
-    emitDebugLocValue(AP, BT, Streamer, Value, 0);
+    emitDebugLocValue(AP, BT, Streamer, Value, DwarfExpr);
   }
+  DwarfExpr.finalize();
 }
 
 void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp Fri Dec  9 14:43:40 2016
@@ -46,7 +46,9 @@ void DwarfExpression::AddRegIndirect(int
 }
 
 void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) {
-  assert(SizeInBits > 0 && "piece has size zero");
+  if (!SizeInBits)
+    return;
+
   const unsigned SizeOfByte = 8;
   if (OffsetInBits > 0 || SizeInBits % SizeOfByte) {
     EmitOp(dwarf::DW_OP_bit_piece);
@@ -57,6 +59,7 @@ void DwarfExpression::AddOpPiece(unsigne
     unsigned ByteSize = SizeInBits / SizeOfByte;
     EmitUnsigned(ByteSize);
   }
+  this->OffsetInBits += SizeInBits;
 }
 
 void DwarfExpression::AddShr(unsigned ShiftBy) {
@@ -82,10 +85,8 @@ bool DwarfExpression::AddMachineRegIndir
   return true;
 }
 
-bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI,
-                                            unsigned MachineReg,
-                                            unsigned FragmentSizeInBits,
-                                            unsigned FragmentOffsetInBits) {
+bool DwarfExpression::AddMachineReg(const TargetRegisterInfo &TRI,
+                                    unsigned MachineReg) {
   if (!TRI.isPhysicalRegister(MachineReg))
     return false;
 
@@ -94,8 +95,6 @@ bool DwarfExpression::AddMachineRegFragm
   // If this is a valid register number, emit it.
   if (Reg >= 0) {
     AddReg(Reg);
-    if (FragmentSizeInBits)
-      AddOpPiece(FragmentSizeInBits, FragmentOffsetInBits);
     return true;
   }
 
@@ -108,24 +107,15 @@ bool DwarfExpression::AddMachineRegFragm
       unsigned Size = TRI.getSubRegIdxSize(Idx);
       unsigned RegOffset = TRI.getSubRegIdxOffset(Idx);
       AddReg(Reg, "super-register");
-      if (FragmentOffsetInBits == RegOffset) {
-        AddOpPiece(Size, RegOffset);
-      } else {
-        // If this is part of a variable in a sub-register at a non-zero offset,
-        // we need to manually shift the value into place, since the
-        // DW_OP_LLVM_fragment describes the part of the variable, not the
-        // position of the subregister.
-        if (RegOffset)
-          AddShr(RegOffset);
-        AddOpPiece(Size, FragmentOffsetInBits);
-      }
+      // Use a DW_OP_bit_piece to describe the sub-register.
+      setSubRegisterPiece(Size, RegOffset);
       return true;
     }
   }
 
   // Otherwise, attempt to find a covering set of sub-register numbers.
   // For example, Q0 on ARM is a composition of D0+D1.
-  unsigned CurPos = FragmentOffsetInBits;
+  unsigned CurPos = 0;
   // The size of the register in bits, assuming 8 bits per byte.
   unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->getSize() * 8;
   // Keep track of the bits in the register we already emitted, so we
@@ -147,7 +137,10 @@ bool DwarfExpression::AddMachineRegFragm
     // its range, emit a DWARF piece for it.
     if (Reg >= 0 && Intersection.any()) {
       AddReg(Reg, "sub-register");
-      AddOpPiece(Size, Offset == CurPos ? 0 : Offset);
+      // Emit a piece for the any gap in the coverage.
+      if (Offset > CurPos)
+        AddOpPiece(Offset - CurPos);
+      AddOpPiece(Size);
       CurPos = Offset + Size;
 
       // Mark it as emitted.
@@ -155,7 +148,7 @@ bool DwarfExpression::AddMachineRegFragm
     }
   }
 
-  return CurPos > FragmentOffsetInBits;
+  return CurPos;
 }
 
 void DwarfExpression::AddStackValue() {
@@ -191,35 +184,21 @@ void DwarfExpression::AddUnsignedConstan
   }
 }
 
-static unsigned getOffsetOrZero(unsigned OffsetInBits,
-                                unsigned FragmentOffsetInBits) {
-  if (OffsetInBits == FragmentOffsetInBits)
-    return 0;
-  assert(OffsetInBits >= FragmentOffsetInBits && "overlapping fragments");
-  return OffsetInBits;
-}
-
 bool DwarfExpression::AddMachineRegExpression(const TargetRegisterInfo &TRI,
                                               DIExpressionCursor &ExprCursor,
                                               unsigned MachineReg,
                                               unsigned FragmentOffsetInBits) {
   if (!ExprCursor)
-    return AddMachineRegFragment(TRI, MachineReg);
+    return AddMachineReg(TRI, MachineReg);
 
   // Pattern-match combinations for which more efficient representations exist
   // first.
   bool ValidReg = false;
   auto Op = ExprCursor.peek();
   switch (Op->getOp()) {
-  case dwarf::DW_OP_LLVM_fragment: {
-    unsigned OffsetInBits = Op->getArg(0);
-    unsigned SizeInBits = Op->getArg(1);
-    // Piece always comes at the end of the expression.
-    AddMachineRegFragment(TRI, MachineReg, SizeInBits,
-                          getOffsetOrZero(OffsetInBits, FragmentOffsetInBits));
-    ExprCursor.take();
+  default:
+    ValidReg = AddMachineReg(TRI, MachineReg);
     break;
-  }
   case dwarf::DW_OP_plus:
   case dwarf::DW_OP_minus: {
     // [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset].
@@ -231,7 +210,7 @@ bool DwarfExpression::AddMachineRegExpre
           TRI, MachineReg, Op->getOp() == dwarf::DW_OP_plus ? Offset : -Offset);
       ExprCursor.consume(2);
     } else
-      ValidReg = AddMachineRegFragment(TRI, MachineReg);
+      ValidReg = AddMachineReg(TRI, MachineReg);
     break;
   }
   case dwarf::DW_OP_deref:
@@ -250,10 +229,25 @@ void DwarfExpression::AddExpression(DIEx
     auto Op = ExprCursor.take();
     switch (Op->getOp()) {
     case dwarf::DW_OP_LLVM_fragment: {
-      unsigned OffsetInBits = Op->getArg(0);
-      unsigned SizeInBits   = Op->getArg(1);
-      AddOpPiece(SizeInBits,
-                 getOffsetOrZero(OffsetInBits, FragmentOffsetInBits));
+      unsigned SizeInBits = Op->getArg(1);
+      unsigned FragmentOffset = Op->getArg(0);
+      // The fragment offset must have already been adjusted by emitting an
+      // empty DW_OP_piece / DW_OP_bit_piece before we emitted the base
+      // location.
+      assert(OffsetInBits >= FragmentOffset && "fragment offset not added?");
+
+      // If \a AddMachineReg already emitted DW_OP_piece operations to represent
+      // a super-register by splicing together sub-registers, subtract the size
+      // of the pieces that was already emitted.
+      SizeInBits -= OffsetInBits - FragmentOffset;
+
+      // If \a AddMachineReg requested a DW_OP_bit_piece to stencil out a
+      // sub-register that is smaller than the current fragment's size, use it.
+      if (SubRegisterSizeInBits)
+        SizeInBits = std::min<unsigned>(SizeInBits, SubRegisterSizeInBits);
+      
+      AddOpPiece(SizeInBits, SubRegisterOffsetInBits);
+      setSubRegisterPiece(0, 0);
       break;
     }
     case dwarf::DW_OP_plus:
@@ -281,3 +275,20 @@ void DwarfExpression::AddExpression(DIEx
     }
   }
 }
+
+void DwarfExpression::finalize() {
+  if (SubRegisterSizeInBits)
+    AddOpPiece(SubRegisterSizeInBits, SubRegisterOffsetInBits);
+}
+
+void DwarfExpression::addFragmentOffset(const DIExpression *Expr) {
+  if (!Expr || !Expr->isFragment())
+    return;
+
+  uint64_t FragmentOffset = Expr->getFragmentOffsetInBits();
+  assert(FragmentOffset >= OffsetInBits &&
+         "overlapping or duplicate fragments");
+  if (FragmentOffset > OffsetInBits)
+    AddOpPiece(FragmentOffset - OffsetInBits);
+  OffsetInBits = FragmentOffset;
+}

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h Fri Dec  9 14:43:40 2016
@@ -39,6 +39,9 @@ public:
     End = Expr->expr_op_end();
   }
 
+  DIExpressionCursor(ArrayRef<uint64_t> Expr)
+      : Start(Expr.begin()), End(Expr.end()) {}
+
   /// Consume one operation.
   Optional<DIExpression::ExprOperand> take() {
     if (Start == End)
@@ -77,10 +80,26 @@ public:
 class DwarfExpression {
 protected:
   unsigned DwarfVersion;
+  /// Current Fragment Offset in Bits.
+  uint64_t OffsetInBits = 0;
+
+  /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. 
+  unsigned SubRegisterSizeInBits = 0;
+  unsigned SubRegisterOffsetInBits = 0;
+
+  /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
+  /// to represent a subregister.
+  void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
+    SubRegisterSizeInBits = SizeInBits;
+    SubRegisterOffsetInBits = OffsetInBits;
+  }
 
 public:
   DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {}
-  virtual ~DwarfExpression() {}
+  virtual ~DwarfExpression() {};
+
+  /// This needs to be called last to commit any pending changes.
+  void finalize();
 
   /// Output a dwarf operand and an optional assembler comment.
   virtual void EmitOp(uint8_t Op, const char *Comment = nullptr) = 0;
@@ -97,9 +116,9 @@ public:
   /// Emit an (double-)indirect dwarf register operation.
   void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false);
 
-  /// Emit a DW_OP_piece operation for a variable fragment.
-  /// \param OffsetInBits    This is the offset where the fragment appears
-  ///                        inside the *source variable*.
+  /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment.
+  /// \param OffsetInBits    This is an optional offset into the location that
+  /// is at the top of the DWARF stack.
   void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
 
   /// Emit a shift-right dwarf expression.
@@ -125,10 +144,7 @@ public:
 
   /// Emit a partial DWARF register operation.
   ///
-  /// \param MachineReg           the register,
-  /// \param FragmentSizeInBits   size and
-  /// \param FragmentOffsetInBits offset of the fragment in bits, if this is
-  ///                             a fragment of an aggregate value.
+  /// \param MachineReg           The register number.
   ///
   /// If size and offset is zero an operation for the entire register is
   /// emitted: Some targets do not provide a DWARF register number for every
@@ -137,9 +153,7 @@ public:
   /// multiple subregisters that alias the register.
   ///
   /// \return false if no DWARF register exists for MachineReg.
-  bool AddMachineRegFragment(const TargetRegisterInfo &TRI, unsigned MachineReg,
-                          unsigned FragmentSizeInBits = 0,
-                          unsigned FragmentOffsetInBits = 0);
+  bool AddMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg);
 
   /// Emit a signed constant.
   void AddSignedConstant(int64_t Value);
@@ -167,6 +181,10 @@ public:
   ///                                 fragment inside the entire variable.
   void AddExpression(DIExpressionCursor &&Expr,
                      unsigned FragmentOffsetInBits = 0);
+
+  /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
+  /// the fragment described by \c Expr.
+  void addFragmentOffset(const DIExpression *Expr);
 };
 
 /// DwarfExpression implementation for .debug_loc entries.

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Fri Dec  9 14:43:40 2016
@@ -371,22 +371,6 @@ void DwarfUnit::addSourceLine(DIE &Die,
   addSourceLine(Die, NS->getLine(), NS->getFilename(), NS->getDirectory());
 }
 
-bool DwarfUnit::addRegisterFragment(DIELoc &TheDie, unsigned Reg,
-                                    unsigned SizeInBits,
-                                    unsigned OffsetInBits) {
-  DIEDwarfExpression Expr(*Asm, *this, TheDie);
-  Expr.AddMachineRegFragment(*Asm->MF->getSubtarget().getRegisterInfo(), Reg,
-                             SizeInBits, OffsetInBits);
-  return true;
-}
-
-bool DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg,
-                                  int64_t Offset) {
-  DIEDwarfExpression Expr(*Asm, *this, TheDie);
-  return Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
-                                    Reg, Offset);
-}
-
 /* Byref variables, in Blocks, are declared by the programmer as "SomeType
    VarName;", but the compiler creates a __Block_byref_x_VarName struct, and
    gives the variable VarName either the struct, or a pointer to the struct, as
@@ -479,12 +463,17 @@ void DwarfUnit::addBlockByrefAddress(con
   // Decode the original location, and use that as the start of the byref
   // variable's location.
   DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+  SmallVector<uint64_t, 6> DIExpr;
+  DIEDwarfExpression Expr(*Asm, *this, *Loc);
 
   bool validReg;
   if (Location.isReg())
-    validReg = addRegisterFragment(*Loc, Location.getReg());
+    validReg = Expr.AddMachineReg(*Asm->MF->getSubtarget().getRegisterInfo(),
+                                  Location.getReg());
   else
-    validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
+    validReg =
+        Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
+                                   Location.getReg(), Location.getOffset());
 
   if (!validReg)
     return;
@@ -492,27 +481,29 @@ void DwarfUnit::addBlockByrefAddress(con
   // If we started with a pointer to the __Block_byref... struct, then
   // the first thing we need to do is dereference the pointer (DW_OP_deref).
   if (isPointer)
-    addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+    DIExpr.push_back(dwarf::DW_OP_deref);
 
   // Next add the offset for the '__forwarding' field:
   // DW_OP_plus_uconst ForwardingFieldOffset.  Note there's no point in
   // adding the offset if it's 0.
   if (forwardingFieldOffset > 0) {
-    addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
-    addUInt(*Loc, dwarf::DW_FORM_udata, forwardingFieldOffset);
+    DIExpr.push_back(dwarf::DW_OP_plus);
+    DIExpr.push_back(forwardingFieldOffset);
   }
 
   // Now dereference the __forwarding field to get to the real __Block_byref
   // struct:  DW_OP_deref.
-  addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+  DIExpr.push_back(dwarf::DW_OP_deref);
 
   // Now that we've got the real __Block_byref... struct, add the offset
   // for the variable's field to get to the location of the actual variable:
   // DW_OP_plus_uconst varFieldOffset.  Again, don't add if it's 0.
   if (varFieldOffset > 0) {
-    addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
-    addUInt(*Loc, dwarf::DW_FORM_udata, varFieldOffset);
+    DIExpr.push_back(dwarf::DW_OP_plus);
+    DIExpr.push_back(varFieldOffset);
   }
+  Expr.AddExpression(makeArrayRef(DIExpr));
+  Expr.finalize();
 
   // Now attach the location information to the DIE.
   addBlock(Die, Attribute, Loc);

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h Fri Dec  9 14:43:40 2016
@@ -235,19 +235,6 @@ public:
   /// Add template parameters in buffer.
   void addTemplateParams(DIE &Buffer, DINodeArray TParams);
 
-  /// Add register operand for a source variable fragment of the specified size
-  /// and offset.
-  ///
-  /// \returns false if the register does not exist, e.g., because it was never
-  ///          materialized.
-  bool addRegisterFragment(DIELoc &TheDie, unsigned Reg,
-                           unsigned SizeInBits = 0, unsigned OffsetInBits = 0);
-
-  /// Add register offset.
-  /// \returns false if the register does not exist, e.g., because it was never
-  /// materialized.
-  bool addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset);
-
   // FIXME: Should be reformulated in terms of addComplexAddress.
   /// Start with the address based on the location provided, and generate the
   /// DWARF information necessary to find the actual Block variable (navigating

Modified: llvm/trunk/test/DebugInfo/AArch64/frameindices.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/AArch64/frameindices.ll?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/AArch64/frameindices.ll (original)
+++ llvm/trunk/test/DebugInfo/AArch64/frameindices.ll Fri Dec  9 14:43:40 2016
@@ -5,8 +5,8 @@
 ; CHECK: DW_TAG_inlined_subroutine
 ; CHECK:    "_Z3f111A"
 ; CHECK: DW_TAG_formal_parameter
-; CHECK: DW_AT_location [DW_FORM_block1]    (<0x0b> 91 51 9d 78 08 91 4a 9d 38 88 01 )
-;  -- fbreg -47, bit-piece 120 8 , fbreg -54, bit-piece 56 136 ------^
+; CHECK: DW_AT_location [DW_FORM_block1]    (<0x0c> 93 01 91 51 93 0f 93 01 91 4a 93 07 )
+;  -- piece 0x00000001, fbreg -47, piece 0x0000000f, piece 0x00000001, fbreg -54, piece 0x00000007 ------^
 ; CHECK: DW_AT_abstract_origin {{.*}} "p1"
 ;
 ; long a;

Added: llvm/trunk/test/DebugInfo/MIR/ARM/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/ARM/lit.local.cfg?rev=289266&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/ARM/lit.local.cfg (added)
+++ llvm/trunk/test/DebugInfo/MIR/ARM/lit.local.cfg Fri Dec  9 14:43:40 2016
@@ -0,0 +1,3 @@
+if not 'ARM' in config.root.targets:
+    config.unsupported = True
+

Added: llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg-piece.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg-piece.mir?rev=289266&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg-piece.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg-piece.mir Fri Dec  9 14:43:40 2016
@@ -0,0 +1,125 @@
+# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
+# CHECK: .debug_info contents:
+# CHECK: DW_TAG_variable
+# CHECK-NEXT: DW_AT_location [DW_FORM_data4]	([[OFS:.*]])
+# CHECK-NEXT: DW_AT_name {{.*}}"vec"
+# CHECK: .debug_loc contents:
+# CHECK: [[OFS]]: Beginning address offset: 0x0000000000000016
+# CHECK:             Ending address offset: 0x000000000000001e
+# CHECK:              Location description: 93 10 90 80 02 93 08 90 81 02 93 08 
+#                  piece 0x00000010, d0, piece 0x00000008, d1, piece 0x00000008
+--- |
+  ; Generate from (and then manually modified to incorporate a DW_OP_LLVM_fragment):
+  ; typedef float vec2 __attribute__((vector_size(16)));
+  ; vec2 v();
+  ; float f() {
+  ;   vec2 vec = v();
+  ;   return vec[0] + vec[1];
+  ; }
+
+  target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+  target triple = "thumbv7s-apple-ios5.0.0"
+  
+  define float @f() local_unnamed_addr #0 !dbg !9 {
+  entry:
+    %call = tail call <4 x float> bitcast (<4 x float> (...)* @v to <4 x float> ()*)() #0, !dbg !19
+    tail call void @llvm.dbg.value(metadata <4 x float> %call, i64 0, metadata !14, metadata !20), !dbg !21
+    %vecext = extractelement <4 x float> %call, i32 0, !dbg !22
+    %vecext1 = extractelement <4 x float> %call, i32 1, !dbg !23
+    %add = fadd float %vecext, %vecext1, !dbg !24
+    ret float %add, !dbg !25
+  }
+  
+  declare arm_aapcs_vfpcc <4 x float> @v(...) local_unnamed_addr #0
+  
+  declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0
+  
+  attributes #0 = { nounwind readnone }
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!3, !4, !5, !6, !7}
+  !llvm.ident = !{!8}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+  !1 = !DIFile(filename: "v.c", directory: "/")
+  !2 = !{}
+  !3 = !{i32 2, !"Dwarf Version", i32 2}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = !{i32 1, !"wchar_size", i32 4}
+  !6 = !{i32 1, !"min_enum_size", i32 4}
+  !7 = !{i32 1, !"PIC Level", i32 2}
+  !8 = !{!"clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)"}
+  !9 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !10, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, variables: !13)
+  !10 = !DISubroutineType(types: !11)
+  !11 = !{!12}
+  !12 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+  !13 = !{!14}
+  !14 = !DILocalVariable(name: "vec", scope: !9, file: !1, line: 4, type: !15)
+  !15 = !DIDerivedType(tag: DW_TAG_typedef, name: "vec2", file: !1, line: 1, baseType: !16)
+  !16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 256, flags: DIFlagVector, elements: !17)
+  !17 = !{!18}
+  !18 = !DISubrange(count: 8)
+  !19 = !DILocation(line: 4, column: 13, scope: !9)
+  !20 = !DIExpression(DW_OP_LLVM_fragment, 128, 128)
+  !21 = !DILocation(line: 4, column: 7, scope: !9)
+  !22 = !DILocation(line: 5, column: 9, scope: !9)
+  !23 = !DILocation(line: 5, column: 18, scope: !9)
+  !24 = !DILocation(line: 5, column: 16, scope: !9)
+  !25 = !DILocation(line: 5, column: 2, scope: !9)
+
+...
+---
+name:            f
+alignment:       1
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+calleeSavedRegisters: [ '%lr', '%d8', '%d9', '%d10', '%d11', '%d12', '%d13', 
+                        '%d14', '%d15', '%q4', '%q5', '%q6', '%q7', '%r4', 
+                        '%r5', '%r6', '%r7', '%r8', '%r10', '%r11', '%s16', 
+                        '%s17', '%s18', '%s19', '%s20', '%s21', '%s22', 
+                        '%s23', '%s24', '%s25', '%s26', '%s27', '%s28', 
+                        '%s29', '%s30', '%s31', '%d8_d10', '%d9_d11', '%d10_d12', 
+                        '%d11_d13', '%d12_d14', '%d13_d15', '%q4_q5', '%q5_q6', 
+                        '%q6_q7', '%q4_q5_q6_q7', '%r4_r5', '%r6_r7', '%r10_r11', 
+                        '%d8_d9_d10', '%d9_d10_d11', '%d10_d11_d12', '%d11_d12_d13', 
+                        '%d12_d13_d14', '%d13_d14_d15', '%d8_d10_d12', 
+                        '%d9_d11_d13', '%d10_d12_d14', '%d11_d13_d15', 
+                        '%d8_d10_d12_d14', '%d9_d11_d13_d15', '%d9_d10', 
+                        '%d11_d12', '%d13_d14', '%d9_d10_d11_d12', '%d11_d12_d13_d14' ]
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       4
+  offsetAdjustment: 0
+  maxAlignment:    4
+  adjustsStack:    true
+  hasCalls:        true
+  maxCallFrameSize: 0
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+stack:           
+  - { id: 0, type: spill-slot, offset: -4, size: 4, alignment: 4, callee-saved-register: '%lr' }
+body:             |
+  bb.0.entry:
+    liveins: %lr
+  
+    early-clobber %sp = frame-setup t2STR_PRE killed undef %lr, %sp, -4, 14, _
+    frame-setup CFI_INSTRUCTION def_cfa_offset 4
+    frame-setup CFI_INSTRUCTION offset %lr, -4
+    tBL 14, _, @v, csr_ios, implicit-def dead %lr, implicit %sp, implicit-def %sp, implicit-def %r0, implicit-def %r1, implicit-def %r2, implicit-def %r3, debug-location !19
+    %d1 = VMOVDRR killed %r2, killed %r3, 14, _, implicit-def %q0, debug-location !19
+    %d0 = VMOVDRR killed %r0, killed %r1, 14, _, implicit killed %q0, implicit-def %q0, debug-location !19
+    DBG_VALUE debug-use %q0, debug-use _, !14, !20, debug-location !21
+    %s4 = VMOVS %s1, 14, _, implicit-def %d2, debug-location !24
+    %d0 = VADDfd %d0, killed %d2, 14, _, implicit killed %q0, debug-location !24
+    %r0 = VMOVRS %s0, 14, _, implicit killed %d0, debug-location !25
+    %lr, %sp = t2LDR_POST %sp, 4, 14, _, debug-location !25
+    tBX_RET 14, _, implicit %r0, debug-location !25
+
+...

Added: llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg.mir?rev=289266&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg.mir Fri Dec  9 14:43:40 2016
@@ -0,0 +1,125 @@
+# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
+# CHECK: .debug_info contents:
+# CHECK: DW_TAG_variable
+# CHECK-NEXT: DW_AT_location [DW_FORM_data4]	([[OFS:.*]])
+# CHECK-NEXT: DW_AT_name {{.*}}"vec"
+# CHECK: .debug_loc contents:
+# CHECK: [[OFS]]: Beginning address offset: 0x0000000000000016
+# CHECK:             Ending address offset: 0x000000000000001e
+# CHECK:              Location description: 90 80 02 93 08 90 81 02 93 08 
+#                                           d0, piece 0x00000008, d1, piece 0x00000008
+--- |
+  ; Generated from:
+  ; typedef float vec2 __attribute__((vector_size(16)));
+  ; vec2 v();
+  ; float f() {
+  ;   vec2 vec = v();
+  ;   return vec[0] + vec[1];
+  ; }
+
+  target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+  target triple = "thumbv7s-apple-ios5.0.0"
+  
+  define float @f() local_unnamed_addr #0 !dbg !9 {
+  entry:
+    %call = tail call <4 x float> bitcast (<4 x float> (...)* @v to <4 x float> ()*)() #0, !dbg !19
+    tail call void @llvm.dbg.value(metadata <4 x float> %call, i64 0, metadata !14, metadata !20), !dbg !21
+    %vecext = extractelement <4 x float> %call, i32 0, !dbg !22
+    %vecext1 = extractelement <4 x float> %call, i32 1, !dbg !23
+    %add = fadd float %vecext, %vecext1, !dbg !24
+    ret float %add, !dbg !25
+  }
+  
+  declare arm_aapcs_vfpcc <4 x float> @v(...) local_unnamed_addr #0
+  
+  declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0
+  
+  attributes #0 = { nounwind readnone }
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!3, !4, !5, !6, !7}
+  !llvm.ident = !{!8}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+  !1 = !DIFile(filename: "v.c", directory: "/")
+  !2 = !{}
+  !3 = !{i32 2, !"Dwarf Version", i32 2}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = !{i32 1, !"wchar_size", i32 4}
+  !6 = !{i32 1, !"min_enum_size", i32 4}
+  !7 = !{i32 1, !"PIC Level", i32 2}
+  !8 = !{!"clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)"}
+  !9 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !10, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, variables: !13)
+  !10 = !DISubroutineType(types: !11)
+  !11 = !{!12}
+  !12 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+  !13 = !{!14}
+  !14 = !DILocalVariable(name: "vec", scope: !9, file: !1, line: 4, type: !15)
+  !15 = !DIDerivedType(tag: DW_TAG_typedef, name: "vec2", file: !1, line: 1, baseType: !16)
+  !16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 128, flags: DIFlagVector, elements: !17)
+  !17 = !{!18}
+  !18 = !DISubrange(count: 4)
+  !19 = !DILocation(line: 4, column: 13, scope: !9)
+  !20 = !DIExpression()
+  !21 = !DILocation(line: 4, column: 7, scope: !9)
+  !22 = !DILocation(line: 5, column: 9, scope: !9)
+  !23 = !DILocation(line: 5, column: 18, scope: !9)
+  !24 = !DILocation(line: 5, column: 16, scope: !9)
+  !25 = !DILocation(line: 5, column: 2, scope: !9)
+
+...
+---
+name:            f
+alignment:       1
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+calleeSavedRegisters: [ '%lr', '%d8', '%d9', '%d10', '%d11', '%d12', '%d13', 
+                        '%d14', '%d15', '%q4', '%q5', '%q6', '%q7', '%r4', 
+                        '%r5', '%r6', '%r7', '%r8', '%r10', '%r11', '%s16', 
+                        '%s17', '%s18', '%s19', '%s20', '%s21', '%s22', 
+                        '%s23', '%s24', '%s25', '%s26', '%s27', '%s28', 
+                        '%s29', '%s30', '%s31', '%d8_d10', '%d9_d11', '%d10_d12', 
+                        '%d11_d13', '%d12_d14', '%d13_d15', '%q4_q5', '%q5_q6', 
+                        '%q6_q7', '%q4_q5_q6_q7', '%r4_r5', '%r6_r7', '%r10_r11', 
+                        '%d8_d9_d10', '%d9_d10_d11', '%d10_d11_d12', '%d11_d12_d13', 
+                        '%d12_d13_d14', '%d13_d14_d15', '%d8_d10_d12', 
+                        '%d9_d11_d13', '%d10_d12_d14', '%d11_d13_d15', 
+                        '%d8_d10_d12_d14', '%d9_d11_d13_d15', '%d9_d10', 
+                        '%d11_d12', '%d13_d14', '%d9_d10_d11_d12', '%d11_d12_d13_d14' ]
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       4
+  offsetAdjustment: 0
+  maxAlignment:    4
+  adjustsStack:    true
+  hasCalls:        true
+  maxCallFrameSize: 0
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+stack:           
+  - { id: 0, type: spill-slot, offset: -4, size: 4, alignment: 4, callee-saved-register: '%lr' }
+body:             |
+  bb.0.entry:
+    liveins: %lr
+  
+    early-clobber %sp = frame-setup t2STR_PRE killed undef %lr, %sp, -4, 14, _
+    frame-setup CFI_INSTRUCTION def_cfa_offset 4
+    frame-setup CFI_INSTRUCTION offset %lr, -4
+    tBL 14, _, @v, csr_ios, implicit-def dead %lr, implicit %sp, implicit-def %sp, implicit-def %r0, implicit-def %r1, implicit-def %r2, implicit-def %r3, debug-location !19
+    %d1 = VMOVDRR killed %r2, killed %r3, 14, _, implicit-def %q0, debug-location !19
+    %d0 = VMOVDRR killed %r0, killed %r1, 14, _, implicit killed %q0, implicit-def %q0, debug-location !19
+    DBG_VALUE debug-use %q0, debug-use _, !14, !20, debug-location !21
+    %s4 = VMOVS %s1, 14, _, implicit-def %d2, debug-location !24
+    %d0 = VADDfd %d0, killed %d2, 14, _, implicit killed %q0, debug-location !24
+    %r0 = VMOVRS %s0, 14, _, implicit killed %d0, debug-location !25
+    %lr, %sp = t2LDR_POST %sp, 4, 14, _, debug-location !25
+    tBX_RET 14, _, implicit %r0, debug-location !25
+
+...

Added: llvm/trunk/test/DebugInfo/MIR/X86/bit-piece-dh.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/bit-piece-dh.mir?rev=289266&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/bit-piece-dh.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/X86/bit-piece-dh.mir Fri Dec  9 14:43:40 2016
@@ -0,0 +1,102 @@
+# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
+# CHECK: .debug_info contents:
+# CHECK: DW_TAG_variable
+# CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset]	([[OFS:.*]])
+# CHECK-NEXT: DW_AT_name {{.*}}"dh"
+# CHECK: .debug_loc contents:
+# CHECK: [[OFS]]: Beginning address offset: 0x0000000000000002
+# CHECK:             Ending address offset: 0x000000000000000c
+# CHECK:              Location description: 51 9d 08 08
+#                                           rdx, bit-piece 8 8
+--- |
+  ; Manually created after:
+  ; char f(int i) {
+  ;   char dh = i>>8;
+  ;   return dh;
+  ; }
+
+  target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-apple-macosx10.12.0"
+  
+  define signext i8 @f(i32 %i) local_unnamed_addr #0 !dbg !7 {
+  entry:
+    tail call void @llvm.dbg.value(metadata i32 %i, i64 0, metadata !13, metadata !15), !dbg !16
+    %shr1 = lshr i32 %i, 8, !dbg !17
+    %conv = trunc i32 %shr1 to i8, !dbg !18
+    tail call void @llvm.dbg.value(metadata i8 %conv, i64 0, metadata !14, metadata !15), !dbg !19
+    ret i8 %conv, !dbg !20
+  }
+  
+  declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0
+  
+  attributes #0 = { nounwind readnone }
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!3, !4, !5}
+  !llvm.ident = !{!6}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 288677) (llvm/trunk 288679)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+  !1 = !DIFile(filename: "t.c", directory: "/")
+  !2 = !{}
+  !3 = !{i32 2, !"Dwarf Version", i32 4}
+  !4 = !{i32 2, !"Debug Info Version", i32 3}
+  !5 = !{i32 1, !"PIC Level", i32 2}
+  !6 = !{!"clang version 4.0.0 (trunk 288677) (llvm/trunk 288679)"}
+  !7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
+  !8 = !DISubroutineType(types: !9)
+  !9 = !{!10, !11}
+  !10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+  !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !12 = !{!13, !14}
+  !13 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !11)
+  !14 = !DILocalVariable(name: "dh", scope: !7, file: !1, line: 2, type: !10)
+  !15 = !DIExpression()
+  !16 = !DILocation(line: 1, column: 12, scope: !7)
+  !17 = !DILocation(line: 2, column: 14, scope: !7)
+  !18 = !DILocation(line: 2, column: 13, scope: !7)
+  !19 = !DILocation(line: 2, column: 8, scope: !7)
+  !20 = !DILocation(line: 3, column: 3, scope: !7)
+
+...
+---
+name:            f
+alignment:       4
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+liveins:         
+  - { reg: '%edi' }
+frameInfo:       
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       8
+  offsetAdjustment: 0
+  maxAlignment:    0
+  adjustsStack:    false
+  hasCalls:        false
+  maxCallFrameSize: 0
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+fixedStack:      
+  - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 }
+body:             |
+  bb.0.entry:
+    liveins: %edi, %rbp
+  
+    frame-setup PUSH64r killed %rbp, implicit-def %rsp, implicit %rsp
+    CFI_INSTRUCTION def_cfa_offset 16
+    CFI_INSTRUCTION offset %rbp, -16
+    %rbp = frame-setup MOV64rr %rsp
+    CFI_INSTRUCTION def_cfa_register %rbp
+    DBG_VALUE debug-use %dh, debug-use _, !14, !15, debug-location !16
+    %edi = SHR32ri killed %edi, 8, implicit-def dead %eflags, debug-location !17
+    %eax = MOVSX32rr8 %dil, implicit killed %edi, debug-location !20
+    %rbp = POP64r implicit-def %rsp, implicit %rsp, debug-location !20
+    RETQ %eax, debug-location !20
+
+...

Modified: llvm/trunk/test/DebugInfo/X86/PR26148.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/PR26148.ll?rev=289266&r1=289265&r2=289266&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/PR26148.ll (original)
+++ llvm/trunk/test/DebugInfo/X86/PR26148.ll Fri Dec  9 14:43:40 2016
@@ -21,8 +21,8 @@
 ;
 ; CHECK: 0x00000025: Beginning address offset: 0x0000000000000004
 ; CHECK:                Ending address offset: 0x0000000000000004
-; CHECK:                 Location description: 10 03 93 04 55 93 04
-; constu 0x00000003, piece 0x00000004, rdi, piece 0x00000004
+; CHECK:                 Location description: 10 03 93 04 55 93 02
+; constu 0x00000003, piece 0x00000004, rdi, piece 0x00000002
 ; CHECK:             Beginning address offset: 0x0000000000000004
 ; CHECK:                Ending address offset: 0x0000000000000014
 ; CHECK:                 Location description: 10 03 93 04 10 00

Added: llvm/trunk/test/DebugInfo/X86/dw_op_minus_direct.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/dw_op_minus_direct.ll?rev=289266&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/dw_op_minus_direct.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/dw_op_minus_direct.ll Fri Dec  9 14:43:40 2016
@@ -0,0 +1,48 @@
+; Test dwarf codegen of DW_OP_minus.
+; RUN: llc -filetype=obj < %s | llvm-dwarfdump - | FileCheck %s
+
+; This was derived manually from:
+; int inc(int i) {
+;  return i+1;
+; }
+
+; CHECK: Beginning address offset: 0x0000000000000000
+; CHECK:    Ending address offset: 0x0000000000000004
+; CHECK:     Location description: 50 10 01 1c 93 04
+;                                  rax, constu 0x00000001, minus, piece 0x00000004
+source_filename = "minus.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+define i32 @inc(i32 %i) local_unnamed_addr #1 !dbg !7 {
+entry:
+  %add = add nsw i32 %i, 1, !dbg !15
+  tail call void @llvm.dbg.value(metadata i32 %add, i64 0, metadata !12, metadata !13), !dbg !14
+  ret i32 %add, !dbg !16
+}
+
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
+
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "minus.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"PIC Level", i32 2}
+!6 = !{!"clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)"}
+!7 = distinct !DISubprogram(name: "inc", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !11)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !{!12}
+!12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10)
+!13 = !DIExpression(DW_OP_minus, 1)
+!14 = !DILocation(line: 1, column: 13, scope: !7)
+!15 = !DILocation(line: 2, column: 11, scope: !7)
+!16 = !DILocation(line: 2, column: 3, scope: !7)




More information about the llvm-commits mailing list