summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevang Patel <dpatel@apple.com>2011-04-28 02:22:40 +0000
committerDevang Patel <dpatel@apple.com>2011-04-28 02:22:40 +0000
commitc26f5447e39b43a6dd9c1a9d88227f4adf3b5600 (patch)
tree8aa0a0b61c3c69a8c101b2ed4b58adbe1abd180f
parent450ed1a05bd5e12c141629b0d0ba275958634980 (diff)
downloadllvm-c26f5447e39b43a6dd9c1a9d88227f4adf3b5600.tar.gz
llvm-c26f5447e39b43a6dd9c1a9d88227f4adf3b5600.tar.bz2
llvm-c26f5447e39b43a6dd9c1a9d88227f4adf3b5600.tar.xz
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
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h4
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp50
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp17
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp36
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h8
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.cpp41
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.h4
-rw-r--r--test/CodeGen/ARM/2010-08-04-StackVariable.ll4
-rw-r--r--test/CodeGen/X86/2010-08-04-StackVariable.ll4
9 files changed, 137 insertions, 31 deletions
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index 1dac67119a..600b218b77 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -379,6 +379,10 @@ namespace llvm {
/// operands.
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
/// encoding specified.
virtual unsigned getISAEncoding() { return 0; }
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d830e9766b..86e8bb6c34 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -749,33 +749,49 @@ getDebugValueLocation(const MachineInstr *MI) const {
return MachineLocation();
}
+/// getDwarfRegOpSize - get size required to emit given machine location using
+/// dwarf encoding.
+unsigned AsmPrinter::getDwarfRegOpSize(const MachineLocation &MLoc) const {
+ const TargetRegisterInfo *RI = TM.getRegisterInfo();
+ unsigned DWReg = RI->getDwarfRegNum(MLoc.getReg(), false);
+ if (int Offset = MLoc.getOffset()) {
+ // If the value is at a certain offset from frame register then
+ // use DW_OP_breg.
+ if (DWReg < 32)
+ return 1 + MCAsmInfo::getSLEB128Size(Offset);
+ 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 *RI = TM.getRegisterInfo();
- unsigned Reg = RI->getDwarfRegNum(MLoc.getReg(), false);
+ const TargetRegisterInfo *TRI = TM.getRegisterInfo();
+ unsigned Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
if (int Offset = MLoc.getOffset()) {
- // If the value is at a certain offset from frame register then
- // use DW_OP_fbreg.
- unsigned OffsetSize = Offset ? MCAsmInfo::getSLEB128Size(Offset) : 1;
- OutStreamer.AddComment("Loc expr size");
- EmitInt16(1 + OffsetSize);
- OutStreamer.AddComment(
- dwarf::OperationEncodingString(dwarf::DW_OP_fbreg));
- EmitInt8(dwarf::DW_OP_fbreg);
- OutStreamer.AddComment("Offset");
+ if (Reg < 32) {
+ OutStreamer.AddComment(
+ dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
+ EmitInt8(dwarf::DW_OP_breg0 + Reg);
+ } else {
+ OutStreamer.AddComment("DW_OP_bregx");
+ EmitInt8(dwarf::DW_OP_bregx);
+ OutStreamer.AddComment(Twine(Reg));
+ EmitULEB128(Reg);
+ }
EmitSLEB128(Offset);
} else {
if (Reg < 32) {
- OutStreamer.AddComment("Loc expr size");
- EmitInt16(1);
OutStreamer.AddComment(
dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
EmitInt8(dwarf::DW_OP_reg0 + Reg);
} else {
- OutStreamer.AddComment("Loc expr size");
- EmitInt16(1 + MCAsmInfo::getULEB128Size(Reg));
- OutStreamer.AddComment(
- dwarf::OperationEncodingString(dwarf::DW_OP_regx));
+ OutStreamer.AddComment("DW_OP_regx");
EmitInt8(dwarf::DW_OP_regx);
OutStreamer.AddComment(Twine(Reg));
EmitULEB128(Reg);
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index fa5cdd248a..7ce0cfe8e7 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -258,15 +258,22 @@ void CompileUnit::addComplexAddress(DbgVariable *&DV, DIE *Die,
unsigned Attribute,
const MachineLocation &Location) {
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
-
- if (Location.isReg())
- addRegisterOp(Block, Location.getReg());
+ unsigned N = DV->getNumAddrElements();
+ 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());
+ }
else
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);
-
if (Element == DIBuilder::OpPlus) {
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i));
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index d99faf96b4..26da8006b3 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1466,7 +1466,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
}
// 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());
}
@@ -2721,7 +2721,39 @@ void DwarfDebug::emitDebugLoc() {
} else {
Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size, 0);
Asm->OutStreamer.EmitSymbolValue(Entry.End, Size, 0);
- Asm->EmitDwarfRegOp(Entry.Loc);
+ 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);
+ }
+
+ // 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);
+ }
}
}
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 892224b232..25f2675d40 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -66,10 +66,12 @@ typedef struct DotDebugLocEntry {
const MCSymbol *Begin;
const MCSymbol *End;
MachineLocation Loc;
+ const MDNode *Variable;
bool Merged;
- DotDebugLocEntry() : Begin(0), End(0), Merged(false) {}
- DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L)
- : Begin(B), End(E), Loc(L), Merged(false) {}
+ DotDebugLocEntry() : Begin(0), End(0), Variable(0), Merged(false) {}
+ DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L,
+ 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
/// labels are referenced is used to find debug_loc offset for a given DIE.
bool isEmpty() { return Begin == 0 && End == 0; }
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp
index b8c117c2cb..c428e1852a 100644
--- a/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -172,6 +172,47 @@ getDebugValueLocation(const MachineInstr *MI) const {
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.
void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const {
const TargetRegisterInfo *RI = TM.getRegisterInfo();
diff --git a/lib/Target/ARM/ARMAsmPrinter.h b/lib/Target/ARM/ARMAsmPrinter.h
index 5f9169ef7f..1ee1b7024d 100644
--- a/lib/Target/ARM/ARMAsmPrinter.h
+++ b/lib/Target/ARM/ARMAsmPrinter.h
@@ -89,6 +89,10 @@ public:
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.
virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const;
diff --git a/test/CodeGen/ARM/2010-08-04-StackVariable.ll b/test/CodeGen/ARM/2010-08-04-StackVariable.ll
index f077d04803..25d38ed774 100644
--- a/test/CodeGen/ARM/2010-08-04-StackVariable.ll
+++ b/test/CodeGen/ARM/2010-08-04-StackVariable.ll
@@ -1,5 +1,5 @@
-; RUN: llc -O0 -mtriple=arm-apple-darwin < %s | grep DW_OP_fbreg
-; Use DW_OP_fbreg in variable's location expression if the variable is in a stack slot.
+; RUN: llc -O0 -mtriple=arm-apple-darwin < %s | grep DW_OP_breg
+; Use DW_OP_breg in variable's location expression if the variable is in a stack slot.
%struct.SVal = type { i8*, i32 }
diff --git a/test/CodeGen/X86/2010-08-04-StackVariable.ll b/test/CodeGen/X86/2010-08-04-StackVariable.ll
index edfd1b8687..ba36fe7c12 100644
--- a/test/CodeGen/X86/2010-08-04-StackVariable.ll
+++ b/test/CodeGen/X86/2010-08-04-StackVariable.ll
@@ -1,5 +1,5 @@
-; RUN: llc -O0 -mtriple=x86_64-apple-darwin < %s | grep DW_OP_fbreg
-; Use DW_OP_fbreg in variable's location expression if the variable is in a stack slot.
+; RUN: llc -O0 -mtriple=x86_64-apple-darwin < %s | grep DW_OP_breg7
+; Use DW_OP_breg7 in variable's location expression if the variable is in a stack slot.
%struct.SVal = type { i8*, i32 }