mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
[DebugInfo] Generate fixups as emitting DWARF .debug_line.
It is necessary to generate fixups in .debug_line as relaxation is enabled due to the address delta may be changed after relaxation. DWARF will record the mappings of lines and addresses in .debug_line section. It will encode the information using special opcodes, standard opcodes and extended opcodes in Line Number Program. I use DW_LNS_fixed_advance_pc to encode fixed length address delta and DW_LNE_set_address to encode absolute address to make it possible to generate fixups in .debug_line section. Differential Revision: https://reviews.llvm.org/D46850 llvm-svn: 338477
This commit is contained in:
parent
da5081315b
commit
429710b3ef
@ -362,6 +362,13 @@ public:
|
|||||||
static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
|
static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
|
||||||
int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
|
int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
|
||||||
|
|
||||||
|
/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas using
|
||||||
|
/// fixed length operands.
|
||||||
|
static bool FixedEncode(MCContext &Context,
|
||||||
|
MCDwarfLineTableParams Params,
|
||||||
|
int64_t LineDelta, uint64_t AddrDelta,
|
||||||
|
raw_ostream &OS, uint32_t *Offset, uint32_t *Size);
|
||||||
|
|
||||||
/// Utility function to emit the encoding to a streamer.
|
/// Utility function to emit the encoding to a streamer.
|
||||||
static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
|
static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
|
||||||
int64_t LineDelta, uint64_t AddrDelta);
|
int64_t LineDelta, uint64_t AddrDelta);
|
||||||
|
@ -149,6 +149,7 @@ public:
|
|||||||
case MCFragment::FT_Relaxable:
|
case MCFragment::FT_Relaxable:
|
||||||
case MCFragment::FT_CompactEncodedInst:
|
case MCFragment::FT_CompactEncodedInst:
|
||||||
case MCFragment::FT_Data:
|
case MCFragment::FT_Data:
|
||||||
|
case MCFragment::FT_Dwarf:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +233,7 @@ public:
|
|||||||
static bool classof(const MCFragment *F) {
|
static bool classof(const MCFragment *F) {
|
||||||
MCFragment::FragmentType Kind = F->getKind();
|
MCFragment::FragmentType Kind = F->getKind();
|
||||||
return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
|
return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
|
||||||
Kind == MCFragment::FT_CVDefRange;
|
Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf;;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -514,7 +515,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MCDwarfLineAddrFragment : public MCFragment {
|
class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
|
||||||
/// LineDelta - the value of the difference between the two line numbers
|
/// LineDelta - the value of the difference between the two line numbers
|
||||||
/// between two .loc dwarf directives.
|
/// between two .loc dwarf directives.
|
||||||
int64_t LineDelta;
|
int64_t LineDelta;
|
||||||
@ -523,15 +524,11 @@ class MCDwarfLineAddrFragment : public MCFragment {
|
|||||||
/// make up the address delta between two .loc dwarf directives.
|
/// make up the address delta between two .loc dwarf directives.
|
||||||
const MCExpr *AddrDelta;
|
const MCExpr *AddrDelta;
|
||||||
|
|
||||||
SmallString<8> Contents;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
|
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
|
||||||
MCSection *Sec = nullptr)
|
MCSection *Sec = nullptr)
|
||||||
: MCFragment(FT_Dwarf, false, Sec), LineDelta(LineDelta),
|
: MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
|
||||||
AddrDelta(&AddrDelta) {
|
LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
|
||||||
Contents.push_back(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \name Accessors
|
/// \name Accessors
|
||||||
/// @{
|
/// @{
|
||||||
@ -540,9 +537,6 @@ public:
|
|||||||
|
|
||||||
const MCExpr &getAddrDelta() const { return *AddrDelta; }
|
const MCExpr &getAddrDelta() const { return *AddrDelta; }
|
||||||
|
|
||||||
SmallString<8> &getContents() { return Contents; }
|
|
||||||
const SmallString<8> &getContents() const { return Contents; }
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
static bool classof(const MCFragment *F) {
|
static bool classof(const MCFragment *F) {
|
||||||
|
@ -822,6 +822,9 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
|
|||||||
} else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
|
} else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
|
||||||
Fixups = FragWithFixups->getFixups();
|
Fixups = FragWithFixups->getFixups();
|
||||||
Contents = FragWithFixups->getContents();
|
Contents = FragWithFixups->getContents();
|
||||||
|
} else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) {
|
||||||
|
Fixups = FragWithFixups->getFixups();
|
||||||
|
Contents = FragWithFixups->getContents();
|
||||||
} else
|
} else
|
||||||
llvm_unreachable("Unknown fragment with fixups!");
|
llvm_unreachable("Unknown fragment with fixups!");
|
||||||
for (const MCFixup &Fixup : Fixups) {
|
for (const MCFixup &Fixup : Fixups) {
|
||||||
@ -951,16 +954,37 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
|
|||||||
MCContext &Context = Layout.getAssembler().getContext();
|
MCContext &Context = Layout.getAssembler().getContext();
|
||||||
uint64_t OldSize = DF.getContents().size();
|
uint64_t OldSize = DF.getContents().size();
|
||||||
int64_t AddrDelta;
|
int64_t AddrDelta;
|
||||||
bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
|
bool Abs = DF.getAddrDelta().evaluateAsAbsolute(AddrDelta, Layout);
|
||||||
assert(Abs && "We created a line delta with an invalid expression");
|
|
||||||
(void) Abs;
|
|
||||||
int64_t LineDelta;
|
int64_t LineDelta;
|
||||||
LineDelta = DF.getLineDelta();
|
LineDelta = DF.getLineDelta();
|
||||||
SmallString<8> &Data = DF.getContents();
|
SmallVectorImpl<char> &Data = DF.getContents();
|
||||||
Data.clear();
|
Data.clear();
|
||||||
raw_svector_ostream OSE(Data);
|
raw_svector_ostream OSE(Data);
|
||||||
|
DF.getFixups().clear();
|
||||||
|
|
||||||
|
if (Abs) {
|
||||||
MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
|
MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
|
||||||
AddrDelta, OSE);
|
AddrDelta, OSE);
|
||||||
|
} else {
|
||||||
|
uint32_t Offset;
|
||||||
|
uint32_t Size;
|
||||||
|
bool SetDelta = MCDwarfLineAddr::FixedEncode(Context,
|
||||||
|
getDWARFLinetableParams(),
|
||||||
|
LineDelta, AddrDelta,
|
||||||
|
OSE, &Offset, &Size);
|
||||||
|
// Add Fixups for address delta or new address.
|
||||||
|
const MCExpr *FixupExpr;
|
||||||
|
if (SetDelta) {
|
||||||
|
FixupExpr = &DF.getAddrDelta();
|
||||||
|
} else {
|
||||||
|
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(&DF.getAddrDelta());
|
||||||
|
FixupExpr = ABE->getLHS();
|
||||||
|
}
|
||||||
|
DF.getFixups().push_back(
|
||||||
|
MCFixup::create(Offset, FixupExpr,
|
||||||
|
MCFixup::getKindForSize(Size, false /*isPCRel*/)));
|
||||||
|
}
|
||||||
|
|
||||||
return OldSize != Data.size();
|
return OldSize != Data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,6 +731,57 @@ void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MCDwarfLineAddr::FixedEncode(MCContext &Context,
|
||||||
|
MCDwarfLineTableParams Params,
|
||||||
|
int64_t LineDelta, uint64_t AddrDelta,
|
||||||
|
raw_ostream &OS,
|
||||||
|
uint32_t *Offset, uint32_t *Size) {
|
||||||
|
if (LineDelta != INT64_MAX) {
|
||||||
|
OS << char(dwarf::DW_LNS_advance_line);
|
||||||
|
encodeSLEB128(LineDelta, OS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use address delta to adjust address or use absolute address to adjust
|
||||||
|
// address.
|
||||||
|
bool SetDelta;
|
||||||
|
// According to DWARF spec., the DW_LNS_fixed_advance_pc opcode takes a
|
||||||
|
// single uhalf (unencoded) operand. So, the maximum value of AddrDelta
|
||||||
|
// is 65535. We set a conservative upper bound for it for relaxation.
|
||||||
|
if (AddrDelta > 60000) {
|
||||||
|
const MCAsmInfo *asmInfo = Context.getAsmInfo();
|
||||||
|
unsigned AddrSize = asmInfo->getCodePointerSize();
|
||||||
|
|
||||||
|
OS << char(dwarf::DW_LNS_extended_op);
|
||||||
|
encodeULEB128(1 + AddrSize, OS);
|
||||||
|
OS << char(dwarf::DW_LNE_set_address);
|
||||||
|
// Generate fixup for the address.
|
||||||
|
*Offset = OS.tell();
|
||||||
|
*Size = AddrSize;
|
||||||
|
SetDelta = false;
|
||||||
|
std::vector<uint8_t> FillData;
|
||||||
|
FillData.insert(FillData.begin(), AddrSize, 0);
|
||||||
|
OS.write(reinterpret_cast<char *>(FillData.data()), AddrSize);
|
||||||
|
} else {
|
||||||
|
OS << char(dwarf::DW_LNS_fixed_advance_pc);
|
||||||
|
// Generate fixup for 2-bytes address delta.
|
||||||
|
*Offset = OS.tell();
|
||||||
|
*Size = 2;
|
||||||
|
SetDelta = true;
|
||||||
|
OS << char(0);
|
||||||
|
OS << char(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LineDelta == INT64_MAX) {
|
||||||
|
OS << char(dwarf::DW_LNS_extended_op);
|
||||||
|
OS << char(1);
|
||||||
|
OS << char(dwarf::DW_LNE_end_sequence);
|
||||||
|
} else {
|
||||||
|
OS << char(dwarf::DW_LNS_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetDelta;
|
||||||
|
}
|
||||||
|
|
||||||
// Utility function to write a tuple for .debug_abbrev.
|
// Utility function to write a tuple for .debug_abbrev.
|
||||||
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
|
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
|
||||||
MCOS->EmitULEB128IntValue(Name);
|
MCOS->EmitULEB128IntValue(Name);
|
||||||
|
2
test/DebugInfo/RISCV/lit.local.cfg
Normal file
2
test/DebugInfo/RISCV/lit.local.cfg
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
if not 'RISCV' in config.root.targets:
|
||||||
|
config.unsupported = True
|
75
test/DebugInfo/RISCV/relax-debug-line.ll
Normal file
75
test/DebugInfo/RISCV/relax-debug-line.ll
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=+relax %s -o - \
|
||||||
|
; RUN: | llvm-readobj -r | FileCheck -check-prefix=RELAX %s
|
||||||
|
;
|
||||||
|
; RELAX: .rela.debug_line {
|
||||||
|
; RELAX: R_RISCV_ADD16
|
||||||
|
; RELAX: R_RISCV_SUB16
|
||||||
|
source_filename = "line.c"
|
||||||
|
|
||||||
|
; Function Attrs: noinline nounwind optnone
|
||||||
|
define i32 @init() !dbg !7 {
|
||||||
|
entry:
|
||||||
|
ret i32 0, !dbg !11
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: noinline nounwind optnone
|
||||||
|
define i32 @foo(i32 signext %value) !dbg !12 {
|
||||||
|
entry:
|
||||||
|
%value.addr = alloca i32, align 4
|
||||||
|
store i32 %value, i32* %value.addr, align 4
|
||||||
|
call void @llvm.dbg.declare(metadata i32* %value.addr, metadata !15, metadata !DIExpression()), !dbg !16
|
||||||
|
%0 = load i32, i32* %value.addr, align 4, !dbg !17
|
||||||
|
ret i32 %0, !dbg !18
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind readnone speculatable
|
||||||
|
declare void @llvm.dbg.declare(metadata, metadata, metadata)
|
||||||
|
|
||||||
|
; Function Attrs: noinline nounwind optnone
|
||||||
|
define i32 @bar() !dbg !19 {
|
||||||
|
entry:
|
||||||
|
%result = alloca i32, align 4
|
||||||
|
%v = alloca i32, align 4
|
||||||
|
call void @llvm.dbg.declare(metadata i32* %result, metadata !20, metadata !DIExpression()), !dbg !21
|
||||||
|
call void @llvm.dbg.declare(metadata i32* %v, metadata !22, metadata !DIExpression()), !dbg !23
|
||||||
|
%call = call i32 @init(), !dbg !24
|
||||||
|
store i32 %call, i32* %v, align 4, !dbg !23
|
||||||
|
%0 = load i32, i32* %v, align 4, !dbg !25
|
||||||
|
%call1 = call i32 @foo(i32 signext %0), !dbg !26
|
||||||
|
store i32 %call1, i32* %result, align 4, !dbg !27
|
||||||
|
%1 = load i32, i32* %result, align 4, !dbg !28
|
||||||
|
ret i32 %1, !dbg !29
|
||||||
|
}
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!3, !4, !5}
|
||||||
|
|
||||||
|
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
|
||||||
|
!1 = !DIFile(filename: "line.c", directory: "./")
|
||||||
|
!2 = !{}
|
||||||
|
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
||||||
|
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||||
|
!7 = distinct !DISubprogram(name: "init", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, retainedNodes: !2)
|
||||||
|
!8 = !DISubroutineType(types: !9)
|
||||||
|
!9 = !{!10}
|
||||||
|
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||||
|
!11 = !DILocation(line: 3, column: 3, scope: !7)
|
||||||
|
!12 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 6, type: !13, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
|
||||||
|
!13 = !DISubroutineType(types: !14)
|
||||||
|
!14 = !{!10, !10}
|
||||||
|
!15 = !DILocalVariable(name: "value", arg: 1, scope: !12, file: !1, line: 6, type: !10)
|
||||||
|
!16 = !DILocation(line: 6, column: 13, scope: !12)
|
||||||
|
!17 = !DILocation(line: 8, column: 10, scope: !12)
|
||||||
|
!18 = !DILocation(line: 8, column: 3, scope: !12)
|
||||||
|
!19 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 11, type: !8, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: false, unit: !0, retainedNodes: !2)
|
||||||
|
!20 = !DILocalVariable(name: "result", scope: !19, file: !1, line: 13, type: !10)
|
||||||
|
!21 = !DILocation(line: 13, column: 7, scope: !19)
|
||||||
|
!22 = !DILocalVariable(name: "v", scope: !19, file: !1, line: 14, type: !10)
|
||||||
|
!23 = !DILocation(line: 14, column: 7, scope: !19)
|
||||||
|
!24 = !DILocation(line: 14, column: 11, scope: !19)
|
||||||
|
!25 = !DILocation(line: 16, column: 16, scope: !19)
|
||||||
|
!26 = !DILocation(line: 16, column: 12, scope: !19)
|
||||||
|
!27 = !DILocation(line: 16, column: 10, scope: !19)
|
||||||
|
!28 = !DILocation(line: 18, column: 10, scope: !19)
|
||||||
|
!29 = !DILocation(line: 18, column: 3, scope: !19)
|
Loading…
Reference in New Issue
Block a user