Debug info: Remove ARMAsmPrinter::EmitDwarfRegOp(). AsmPrinter can now
authorAdrian Prantl <aprantl@apple.com>
Thu, 27 Feb 2014 17:56:08 +0000 (17:56 +0000)
committerAdrian Prantl <aprantl@apple.com>
Thu, 27 Feb 2014 17:56:08 +0000 (17:56 +0000)
scan the register file for sub- and super-registers.
No functionality change intended.

(Tests are updated because the comments in the assembler output are
different.)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202416 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/Target/ARM/ARMAsmPrinter.cpp
lib/Target/ARM/ARMAsmPrinter.h
test/CodeGen/ARM/debug-info-qreg.ll
test/CodeGen/ARM/debug-info-s16-reg.ll
test/CodeGen/ARM/debug-info-sreg2.ll
test/DebugInfo/X86/subreg.ll

index 548ef97962de88c35e58006cd95b93af331d6378..d59713c142eba2f84cc1dcee8bb9cfe4453bb033 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "DwarfDebug.h"
 #include "DwarfException.h"
+#include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/ConstantFolding.h"
@@ -908,13 +909,9 @@ static void emitDwarfRegOpIndirect(const AsmPrinter &AP,
 /// Emit a dwarf register operation for describing
 /// - a small value occupying only part of a register or
 /// - a small register representing only part of a value.
-static void emitDwarfRegOpPiece(const AsmPrinter &AP,
-                                int Reg, unsigned Size, unsigned Offset) {
-  assert(Reg >= 0);
+static void emitDwarfOpPiece(const AsmPrinter &AP,
+                                unsigned Size, unsigned Offset) {
   assert(Size > 0);
-
-  emitDwarfRegOp(AP, Reg);
-  // Emit Mask
   if (Offset > 0) {
     AP.OutStreamer.AddComment("DW_OP_bit_piece");
     AP.EmitInt8(dwarf::DW_OP_bit_piece);
@@ -931,41 +928,93 @@ static void emitDwarfRegOpPiece(const AsmPrinter &AP,
   }
 }
 
+/// Some targets do not provide a DWARF register number for every
+/// register.  This function attempts to emit a dwarf register by
+/// emitting a piece of a super-register or by piecing together
+/// multiple subregisters that alias the register.
+static void EmitDwarfRegOpPiece(const AsmPrinter &AP,
+                                const MachineLocation &MLoc) {
+  assert(!MLoc.isIndirect());
+  const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
+  int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
+
+  // Walk up the super-register chain until we find a valid number.
+  // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0.
+  for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
+    Reg = TRI->getDwarfRegNum(*SR, false);
+    if (Reg >= 0) {
+      unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg());
+      unsigned Size = TRI->getSubRegIdxSize(Idx);
+      unsigned Offset = TRI->getSubRegIdxOffset(Idx);
+      AP.OutStreamer.AddComment("super-register");
+      emitDwarfRegOp(AP, Reg);
+      emitDwarfOpPiece(AP, Size, Offset);
+      return;
+    }
+  }
+
+  // Otherwise, attempt to find a covering set of sub-register numbers.
+  // For example, Q0 on ARM is a composition of D0+D1.
+  //
+  // Keep track of the current position so we can emit the more
+  // efficient DW_OP_piece.
+  unsigned CurPos = 0;
+  // The size of the register in bits, assuming 8 bits per byte.
+  unsigned RegSize = TRI->getMinimalPhysRegClass(MLoc.getReg())->getSize()*8;
+  // Keep track of the bits in the register we already emitted, so we
+  // can avoid emitting redundant aliasing subregs.
+  SmallBitVector Coverage(RegSize, false);
+  for (MCSubRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
+    unsigned Idx = TRI->getSubRegIndex(MLoc.getReg(), *SR);
+    unsigned Size = TRI->getSubRegIdxSize(Idx);
+    unsigned Offset = TRI->getSubRegIdxOffset(Idx);
+    Reg = TRI->getDwarfRegNum(*SR, false);
+
+    // Intersection between the bits we already emitted and the bits
+    // covered by this subregister.
+    SmallBitVector Intersection(RegSize, false);
+    Intersection.set(Offset, Offset+Size);
+    Intersection ^= Coverage;
+
+    // If this sub-register has a DWARF number and we haven't covered
+    // its range, emit a DWARF piece for it.
+    if (Reg >= 0 && Intersection.any()) {
+      AP.OutStreamer.AddComment("sub-register");
+      emitDwarfRegOp(AP, Reg);
+      emitDwarfOpPiece(AP, Size, Offset == CurPos ? 0 : Offset);
+      CurPos = Offset+Size;
+
+      // Mark it as emitted.
+      Coverage.set(Offset, Offset+Size);
+    }
+  }
+
+  if (CurPos == 0) {
+    // FIXME: We have no reasonable way of handling errors in here.
+    AP.OutStreamer.AddComment("nop (could not find a dwarf register number)");
+    AP.EmitInt8(dwarf::DW_OP_nop);
+  }
+}
+
 /// EmitDwarfRegOp - Emit dwarf register operation.
 void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc,
                                 bool Indirect) const {
   const TargetRegisterInfo *TRI = TM.getRegisterInfo();
   int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
-
   if (Reg < 0) {
-    // Walk up the super-register chain until we find a valid number.
-    for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
-      Reg = TRI->getDwarfRegNum(*SR, false);
-      if (Reg >= 0) {
-        unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg());
-        unsigned Size = TRI->getSubRegIdxSize(Idx);
-        unsigned Offset = TRI->getSubRegIdxOffset(Idx);
-        emitDwarfRegOpPiece(*this, Reg, Size, Offset);
-
-        if (MLoc.isIndirect())
-          EmitInt8(dwarf::DW_OP_deref);
-
-        if (Indirect)
-          EmitInt8(dwarf::DW_OP_deref);
-
-        return;
-      }
-
-      // FIXME: Handle cases like a super register being encoded as
-      // DW_OP_reg 32 DW_OP_piece 4 DW_OP_reg 33
-
+    // We assume that pointers are always in an addressable register.
+    if (Indirect || 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.
+      OutStreamer.AddComment("nop (invalid dwarf register number for indirect loc)");
+      EmitInt8(dwarf::DW_OP_nop);
+      return;
     }
-    // FIXME: We have no reasonable way of handling errors in here. The
-    // caller might be in the middle of an dwarf expression. We should
-    // probably assert that Reg >= 0 once debug info generation is more mature.
-    OutStreamer.AddComment("nop (invalid dwarf register number)");
-    EmitInt8(dwarf::DW_OP_nop);
-    return;
+
+    // Attempt to find a valid super- or sub-register.
+    if (!Indirect && !MLoc.isIndirect())
+      return EmitDwarfRegOpPiece(*this, MLoc);
   }
 
   if (MLoc.isIndirect())
index 5a81a73ff6893fe16aac7bf5750ca4a1a7d5f06c..b1b1aad2f8c4a4b712b31ebb16e3447524b831d6 100644 (file)
 #include <cctype>
 using namespace llvm;
 
-/// EmitDwarfRegOp - Emit dwarf register operation.
-void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc,
-                                   bool Indirect) const {
-  const TargetRegisterInfo *RI = TM.getRegisterInfo();
-  if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1) {
-    AsmPrinter::EmitDwarfRegOp(MLoc, Indirect);
-    return;
-  }
-  assert(MLoc.isReg() && !Indirect &&
-         "This doesn't support offset/indirection - implement it if needed");
-  unsigned Reg = MLoc.getReg();
-  if (Reg >= ARM::S0 && Reg <= ARM::S31) {
-    assert(ARM::S0 + 31 == ARM::S31 && "Unexpected ARM S register numbering");
-    // S registers are described as bit-pieces of a register
-    // S[2x] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 0)
-    // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32)
-
-    unsigned SReg = Reg - ARM::S0;
-    bool odd = SReg & 0x1;
-    unsigned Rx = 256 + (SReg >> 1);
-
-    OutStreamer.AddComment("DW_OP_regx for S register");
-    EmitInt8(dwarf::DW_OP_regx);
-
-    OutStreamer.AddComment(Twine(SReg));
-    EmitULEB128(Rx);
-
-    if (odd) {
-      OutStreamer.AddComment("DW_OP_bit_piece 32 32");
-      EmitInt8(dwarf::DW_OP_bit_piece);
-      EmitULEB128(32);
-      EmitULEB128(32);
-    } else {
-      OutStreamer.AddComment("DW_OP_bit_piece 32 0");
-      EmitInt8(dwarf::DW_OP_bit_piece);
-      EmitULEB128(32);
-      EmitULEB128(0);
-    }
-  } else if (Reg >= ARM::Q0 && Reg <= ARM::Q15) {
-    assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering");
-    // Q registers Q0-Q15 are described by composing two D registers together.
-    // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1)
-    // DW_OP_piece(8)
-
-    unsigned QReg = Reg - ARM::Q0;
-    unsigned D1 = 256 + 2 * QReg;
-    unsigned D2 = D1 + 1;
-
-    OutStreamer.AddComment("DW_OP_regx for Q register: D1");
-    EmitInt8(dwarf::DW_OP_regx);
-    EmitULEB128(D1);
-    OutStreamer.AddComment("DW_OP_piece 8");
-    EmitInt8(dwarf::DW_OP_piece);
-    EmitULEB128(8);
-
-    OutStreamer.AddComment("DW_OP_regx for Q register: D2");
-    EmitInt8(dwarf::DW_OP_regx);
-    EmitULEB128(D2);
-    OutStreamer.AddComment("DW_OP_piece 8");
-    EmitInt8(dwarf::DW_OP_piece);
-    EmitULEB128(8);
-  }
-}
-
 void ARMAsmPrinter::EmitFunctionBodyEnd() {
   // Make sure to terminate any constant pools that were at the end
   // of the function.
index fe17d996b73b3e4a2ca2d3b069ccb0e1b2509636..8c4a6b6e599b258be14c9296d07a07751f355a69 100644 (file)
@@ -98,10 +98,6 @@ private:
                                    const MachineInstr *MI);
 
 public:
-  /// EmitDwarfRegOp - Emit dwarf register operation.
-  virtual void EmitDwarfRegOp(const MachineLocation &MLoc, bool Indirect) const
-      LLVM_OVERRIDE;
-
   virtual unsigned getISAEncoding() LLVM_OVERRIDE {
     // ARM/Darwin adds ISA to the DWARF info for each function.
     if (!Subtarget->isTargetMachO())
index ee515fd55c81461392663a8c2517e67b1fb167e8..03ce312a9013e2506391e93377f8d85f0eac3afc 100644 (file)
@@ -2,13 +2,15 @@
 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
 target triple = "thumbv7-apple-macosx10.6.7"
 
-;CHECK: DW_OP_regx for Q register: D1
+;CHECK: sub-register
+;CHECK-NEXT: DW_OP_regx
 ;CHECK-NEXT: ascii
-;CHECK-NEXT: DW_OP_piece 8
+;CHECK-NEXT: DW_OP_piece
 ;CHECK-NEXT: byte   8
-;CHECK-NEXT: DW_OP_regx for Q register: D2
+;CHECK-NEXT: sub-register
+;CHECK-NEXT: DW_OP_regx
 ;CHECK-NEXT: ascii
-;CHECK-NEXT: DW_OP_piece 8
+;CHECK-NEXT: DW_OP_piece
 ;CHECK-NEXT: byte   8
 
 @.str = external constant [13 x i8]
index e92d9776db8c770ec7afa16eb89c8662d35da398..ee9faf833ccf384bf8018c6758f7b6d32cc8539d 100644 (file)
@@ -1,9 +1,11 @@
 ; RUN: llc < %s - | FileCheck %s
 ; Radar 9309221
 ; Test dwarf reg no for s16
-;CHECK: DW_OP_regx for S register
+;CHECK: super-register
+;CHECK-NEXT: DW_OP_regx
 ;CHECK-NEXT: ascii
-;CHECK-NEXT: DW_OP_bit_piece 32 0
+;CHECK-NEXT: DW_OP_piece
+;CHECK-NEXT: 4
 
 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
 target triple = "thumbv7-apple-macosx10.6.7"
index a27b0565a68f5cdbe58c51ebf5c82884db858506..71a696a6a4a9e4ef96348b7eead53bdafc811ae6 100644 (file)
@@ -12,7 +12,10 @@ target triple = "thumbv7-apple-macosx10.6.7"
 ;CHECK-NEXT: Lset[[N:[0-9]+]] = Ltmp{{[0-9]+}}-Ltmp[[M:[0-9]+]]        @ Loc expr size
 ;CHECK-NEXT:        .short  Lset[[N]]
 ;CHECK-NEXT: Ltmp[[M]]:
-;CHECK-NEXT:        .byte   144                     @ DW_OP_regx for S register
+;CHECK-NEXT:        .byte   144                     @ super-register
+;CHECK-NEXT:                                        @ DW_OP_regx
+;CHECK-NEXT:        .ascii
+;CHECK-NEXT:        .byte   {{[0-9]+}}              @ DW_OP_{{.*}}piece
 
 define void @_Z3foov() optsize ssp {
 entry:
index 94526ffae85b3c48536b3b51661917fe9a629dac..22fd1a80e87b3e887b6da541302f0d770318524f 100644 (file)
@@ -3,9 +3,10 @@
 ; We are testing that a value in a 16 bit register gets reported as
 ; being in its superregister.
 
-; CHECK: .byte   80                      # DW_OP_reg0
-; CHECK: .byte   147                     # DW_OP_piece
-; CHECK: .byte   2                       # 2
+; CHECK: .byte   80                      # super-register
+; CHECK-NEXT:                            # DW_OP_reg0
+; CHECK-NEXT: .byte   147                # DW_OP_piece
+; CHECK-NEXT: .byte   2                  # 2
 
 define i16 @f(i16 signext %zzz) nounwind {
 entry: