mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-19 04:32:19 +00:00
Teach dwarf writer to handle complex address expression for .debug_loc entries.
This fixes clang generated blocks' variables' debug info. Radar 9279956. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130373 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
450ed1a05b
commit
c26f5447e3
@ -379,6 +379,10 @@ namespace llvm {
|
|||||||
/// operands.
|
/// operands.
|
||||||
virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
|
virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
|
||||||
|
|
||||||
|
/// getDwarfRegOpSize - get size required to emit given machine location
|
||||||
|
/// using dwarf encoding.
|
||||||
|
virtual unsigned getDwarfRegOpSize(const MachineLocation &MLoc) const;
|
||||||
|
|
||||||
/// getISAEncoding - Get the value for DW_AT_APPLE_isa. Zero if no isa
|
/// getISAEncoding - Get the value for DW_AT_APPLE_isa. Zero if no isa
|
||||||
/// encoding specified.
|
/// encoding specified.
|
||||||
virtual unsigned getISAEncoding() { return 0; }
|
virtual unsigned getISAEncoding() { return 0; }
|
||||||
|
@ -749,33 +749,49 @@ getDebugValueLocation(const MachineInstr *MI) const {
|
|||||||
return MachineLocation();
|
return MachineLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitDwarfRegOp - Emit dwarf register operation.
|
/// getDwarfRegOpSize - get size required to emit given machine location using
|
||||||
void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
|
/// dwarf encoding.
|
||||||
|
unsigned AsmPrinter::getDwarfRegOpSize(const MachineLocation &MLoc) const {
|
||||||
const TargetRegisterInfo *RI = TM.getRegisterInfo();
|
const TargetRegisterInfo *RI = TM.getRegisterInfo();
|
||||||
unsigned Reg = RI->getDwarfRegNum(MLoc.getReg(), false);
|
unsigned DWReg = RI->getDwarfRegNum(MLoc.getReg(), false);
|
||||||
if (int Offset = MLoc.getOffset()) {
|
if (int Offset = MLoc.getOffset()) {
|
||||||
// If the value is at a certain offset from frame register then
|
// If the value is at a certain offset from frame register then
|
||||||
// use DW_OP_fbreg.
|
// use DW_OP_breg.
|
||||||
unsigned OffsetSize = Offset ? MCAsmInfo::getSLEB128Size(Offset) : 1;
|
if (DWReg < 32)
|
||||||
OutStreamer.AddComment("Loc expr size");
|
return 1 + MCAsmInfo::getSLEB128Size(Offset);
|
||||||
EmitInt16(1 + OffsetSize);
|
else
|
||||||
|
return 1 + MCAsmInfo::getULEB128Size(MLoc.getReg())
|
||||||
|
+ MCAsmInfo::getSLEB128Size(Offset);
|
||||||
|
}
|
||||||
|
if (DWReg < 32)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 1 + MCAsmInfo::getULEB128Size(DWReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// EmitDwarfRegOp - Emit dwarf register operation.
|
||||||
|
void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
|
||||||
|
const TargetRegisterInfo *TRI = TM.getRegisterInfo();
|
||||||
|
unsigned Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
|
||||||
|
if (int Offset = MLoc.getOffset()) {
|
||||||
|
if (Reg < 32) {
|
||||||
OutStreamer.AddComment(
|
OutStreamer.AddComment(
|
||||||
dwarf::OperationEncodingString(dwarf::DW_OP_fbreg));
|
dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
|
||||||
EmitInt8(dwarf::DW_OP_fbreg);
|
EmitInt8(dwarf::DW_OP_breg0 + Reg);
|
||||||
OutStreamer.AddComment("Offset");
|
} else {
|
||||||
|
OutStreamer.AddComment("DW_OP_bregx");
|
||||||
|
EmitInt8(dwarf::DW_OP_bregx);
|
||||||
|
OutStreamer.AddComment(Twine(Reg));
|
||||||
|
EmitULEB128(Reg);
|
||||||
|
}
|
||||||
EmitSLEB128(Offset);
|
EmitSLEB128(Offset);
|
||||||
} else {
|
} else {
|
||||||
if (Reg < 32) {
|
if (Reg < 32) {
|
||||||
OutStreamer.AddComment("Loc expr size");
|
|
||||||
EmitInt16(1);
|
|
||||||
OutStreamer.AddComment(
|
OutStreamer.AddComment(
|
||||||
dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
|
dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
|
||||||
EmitInt8(dwarf::DW_OP_reg0 + Reg);
|
EmitInt8(dwarf::DW_OP_reg0 + Reg);
|
||||||
} else {
|
} else {
|
||||||
OutStreamer.AddComment("Loc expr size");
|
OutStreamer.AddComment("DW_OP_regx");
|
||||||
EmitInt16(1 + MCAsmInfo::getULEB128Size(Reg));
|
|
||||||
OutStreamer.AddComment(
|
|
||||||
dwarf::OperationEncodingString(dwarf::DW_OP_regx));
|
|
||||||
EmitInt8(dwarf::DW_OP_regx);
|
EmitInt8(dwarf::DW_OP_regx);
|
||||||
OutStreamer.AddComment(Twine(Reg));
|
OutStreamer.AddComment(Twine(Reg));
|
||||||
EmitULEB128(Reg);
|
EmitULEB128(Reg);
|
||||||
|
@ -258,15 +258,22 @@ void CompileUnit::addComplexAddress(DbgVariable *&DV, DIE *Die,
|
|||||||
unsigned Attribute,
|
unsigned Attribute,
|
||||||
const MachineLocation &Location) {
|
const MachineLocation &Location) {
|
||||||
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
|
||||||
|
unsigned N = DV->getNumAddrElements();
|
||||||
if (Location.isReg())
|
unsigned i = 0;
|
||||||
|
if (Location.isReg()) {
|
||||||
|
if (N >= 2 && DV->getAddrElement(0) == DIBuilder::OpPlus) {
|
||||||
|
// If first address element is OpPlus then emit
|
||||||
|
// DW_OP_breg + Offset instead of DW_OP_reg + Offset.
|
||||||
|
addRegisterOffset(Block, Location.getReg(), DV->getAddrElement(1));
|
||||||
|
i = 2;
|
||||||
|
} else
|
||||||
addRegisterOp(Block, Location.getReg());
|
addRegisterOp(Block, Location.getReg());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
addRegisterOffset(Block, Location.getReg(), Location.getOffset());
|
addRegisterOffset(Block, Location.getReg(), Location.getOffset());
|
||||||
|
|
||||||
for (unsigned i = 0, N = DV->getNumAddrElements(); i < N; ++i) {
|
for (;i < N; ++i) {
|
||||||
uint64_t Element = DV->getAddrElement(i);
|
uint64_t Element = DV->getAddrElement(i);
|
||||||
|
|
||||||
if (Element == DIBuilder::OpPlus) {
|
if (Element == DIBuilder::OpPlus) {
|
||||||
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
|
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
|
||||||
addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i));
|
addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i));
|
||||||
|
@ -1466,7 +1466,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The value is valid until the next DBG_VALUE or clobber.
|
// The value is valid until the next DBG_VALUE or clobber.
|
||||||
DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc));
|
DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc, Var));
|
||||||
}
|
}
|
||||||
DotDebugLocEntries.push_back(DotDebugLocEntry());
|
DotDebugLocEntries.push_back(DotDebugLocEntry());
|
||||||
}
|
}
|
||||||
@ -2721,8 +2721,40 @@ void DwarfDebug::emitDebugLoc() {
|
|||||||
} else {
|
} else {
|
||||||
Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size, 0);
|
Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size, 0);
|
||||||
Asm->OutStreamer.EmitSymbolValue(Entry.End, Size, 0);
|
Asm->OutStreamer.EmitSymbolValue(Entry.End, Size, 0);
|
||||||
|
DIVariable DV(Entry.Variable);
|
||||||
|
if (DV.hasComplexAddress()) {
|
||||||
|
unsigned N = DV.getNumAddrElements();
|
||||||
|
unsigned i = 0;
|
||||||
|
Asm->OutStreamer.AddComment("Loc expr size");
|
||||||
|
if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) {
|
||||||
|
// If first address element is OpPlus then emit
|
||||||
|
// DW_OP_breg + Offset instead of DW_OP_reg + Offset.
|
||||||
|
MachineLocation Loc(Entry.Loc.getReg(), DV.getAddrElement(1));
|
||||||
|
Asm->EmitInt16(Asm->getDwarfRegOpSize(Loc) + N - 2);
|
||||||
|
Asm->EmitDwarfRegOp(Loc);
|
||||||
|
// Asm->EmitULEB128(DV.getAddrElement(1));
|
||||||
|
i = 2;
|
||||||
|
} else {
|
||||||
|
Asm->EmitInt16(Asm->getDwarfRegOpSize(Entry.Loc) + N);
|
||||||
Asm->EmitDwarfRegOp(Entry.Loc);
|
Asm->EmitDwarfRegOp(Entry.Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit remaining complex address elements.
|
||||||
|
for (; i < N; ++i) {
|
||||||
|
uint64_t Element = DV.getAddrElement(i);
|
||||||
|
if (Element == DIBuilder::OpPlus) {
|
||||||
|
Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
|
||||||
|
Asm->EmitULEB128(DV.getAddrElement(++i));
|
||||||
|
} else if (Element == DIBuilder::OpDeref)
|
||||||
|
Asm->EmitInt8(dwarf::DW_OP_deref);
|
||||||
|
else llvm_unreachable("unknown Opcode found in complex address");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Asm->OutStreamer.AddComment("Loc expr size");
|
||||||
|
Asm->EmitInt16(Asm->getDwarfRegOpSize(Entry.Loc));
|
||||||
|
Asm->EmitDwarfRegOp(Entry.Loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,10 +66,12 @@ typedef struct DotDebugLocEntry {
|
|||||||
const MCSymbol *Begin;
|
const MCSymbol *Begin;
|
||||||
const MCSymbol *End;
|
const MCSymbol *End;
|
||||||
MachineLocation Loc;
|
MachineLocation Loc;
|
||||||
|
const MDNode *Variable;
|
||||||
bool Merged;
|
bool Merged;
|
||||||
DotDebugLocEntry() : Begin(0), End(0), Merged(false) {}
|
DotDebugLocEntry() : Begin(0), End(0), Variable(0), Merged(false) {}
|
||||||
DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L)
|
DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L,
|
||||||
: Begin(B), End(E), Loc(L), Merged(false) {}
|
const MDNode *V)
|
||||||
|
: Begin(B), End(E), Loc(L), Variable(V), Merged(false) {}
|
||||||
/// Empty entries are also used as a trigger to emit temp label. Such
|
/// Empty entries are also used as a trigger to emit temp label. Such
|
||||||
/// labels are referenced is used to find debug_loc offset for a given DIE.
|
/// labels are referenced is used to find debug_loc offset for a given DIE.
|
||||||
bool isEmpty() { return Begin == 0 && End == 0; }
|
bool isEmpty() { return Begin == 0 && End == 0; }
|
||||||
|
@ -172,6 +172,47 @@ getDebugValueLocation(const MachineInstr *MI) const {
|
|||||||
return Location;
|
return Location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getDwarfRegOpSize - get size required to emit given machine location using
|
||||||
|
/// dwarf encoding.
|
||||||
|
unsigned ARMAsmPrinter::getDwarfRegOpSize(const MachineLocation &MLoc) const {
|
||||||
|
const TargetRegisterInfo *RI = TM.getRegisterInfo();
|
||||||
|
if (RI->getDwarfRegNum(MLoc.getReg(), false) != -1)
|
||||||
|
return AsmPrinter::getDwarfRegOpSize(MLoc);
|
||||||
|
else {
|
||||||
|
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;
|
||||||
|
unsigned Rx = 256 + (SReg >> 1);
|
||||||
|
OutStreamer.AddComment("Loc expr size");
|
||||||
|
// DW_OP_regx + ULEB + DW_OP_bit_piece + ULEB + ULEB
|
||||||
|
// 1 + ULEB(Rx) + 1 + 1 + 1
|
||||||
|
return 4 + MCAsmInfo::getULEB128Size(Rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
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("Loc expr size");
|
||||||
|
// DW_OP_regx + ULEB + DW_OP_piece + ULEB(8) +
|
||||||
|
// DW_OP_regx + ULEB + DW_OP_piece + ULEB(8);
|
||||||
|
// 6 + ULEB(D1) + ULEB(D2)
|
||||||
|
return 6 + MCAsmInfo::getULEB128Size(D1) + MCAsmInfo::getULEB128Size(D2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// EmitDwarfRegOp - Emit dwarf register operation.
|
/// EmitDwarfRegOp - Emit dwarf register operation.
|
||||||
void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
|
void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
|
||||||
const TargetRegisterInfo *RI = TM.getRegisterInfo();
|
const TargetRegisterInfo *RI = TM.getRegisterInfo();
|
||||||
|
@ -89,6 +89,10 @@ public:
|
|||||||
|
|
||||||
MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
|
MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
|
||||||
|
|
||||||
|
/// getDwarfRegOpSize - get size required to emit given machine location
|
||||||
|
/// using dwarf encoding.
|
||||||
|
virtual unsigned getDwarfRegOpSize(const MachineLocation &MLoc) const;
|
||||||
|
|
||||||
/// EmitDwarfRegOp - Emit dwarf register operation.
|
/// EmitDwarfRegOp - Emit dwarf register operation.
|
||||||
virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const;
|
virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
; RUN: llc -O0 -mtriple=arm-apple-darwin < %s | grep DW_OP_fbreg
|
; RUN: llc -O0 -mtriple=arm-apple-darwin < %s | grep DW_OP_breg
|
||||||
; Use DW_OP_fbreg in variable's location expression if the variable is in a stack slot.
|
; Use DW_OP_breg in variable's location expression if the variable is in a stack slot.
|
||||||
|
|
||||||
%struct.SVal = type { i8*, i32 }
|
%struct.SVal = type { i8*, i32 }
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
; RUN: llc -O0 -mtriple=x86_64-apple-darwin < %s | grep DW_OP_fbreg
|
; RUN: llc -O0 -mtriple=x86_64-apple-darwin < %s | grep DW_OP_breg7
|
||||||
; Use DW_OP_fbreg in variable's location expression if the variable is in a stack slot.
|
; Use DW_OP_breg7 in variable's location expression if the variable is in a stack slot.
|
||||||
|
|
||||||
%struct.SVal = type { i8*, i32 }
|
%struct.SVal = type { i8*, i32 }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user