mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
Debug info: Remove ARMAsmPrinter::EmitDwarfRegOp(). AsmPrinter can now
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.) llvm-svn: 202416
This commit is contained in:
parent
947c19eaa0
commit
d7f77dd966
@ -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())
|
||||
|
@ -55,70 +55,6 @@
|
||||
#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.
|
||||
|
@ -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())
|
||||
|
@ -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]
|
||||
|
@ -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"
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user