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,
|
||||
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.
|
||||
static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
|
||||
int64_t LineDelta, uint64_t AddrDelta);
|
||||
|
@ -149,6 +149,7 @@ public:
|
||||
case MCFragment::FT_Relaxable:
|
||||
case MCFragment::FT_CompactEncodedInst:
|
||||
case MCFragment::FT_Data:
|
||||
case MCFragment::FT_Dwarf:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -232,7 +233,7 @@ public:
|
||||
static bool classof(const MCFragment *F) {
|
||||
MCFragment::FragmentType Kind = F->getKind();
|
||||
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
|
||||
/// between two .loc dwarf directives.
|
||||
int64_t LineDelta;
|
||||
@ -523,15 +524,11 @@ class MCDwarfLineAddrFragment : public MCFragment {
|
||||
/// make up the address delta between two .loc dwarf directives.
|
||||
const MCExpr *AddrDelta;
|
||||
|
||||
SmallString<8> Contents;
|
||||
|
||||
public:
|
||||
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
|
||||
MCSection *Sec = nullptr)
|
||||
: MCFragment(FT_Dwarf, false, Sec), LineDelta(LineDelta),
|
||||
AddrDelta(&AddrDelta) {
|
||||
Contents.push_back(0);
|
||||
}
|
||||
: MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
|
||||
LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
|
||||
|
||||
/// \name Accessors
|
||||
/// @{
|
||||
@ -540,9 +537,6 @@ public:
|
||||
|
||||
const MCExpr &getAddrDelta() const { return *AddrDelta; }
|
||||
|
||||
SmallString<8> &getContents() { return Contents; }
|
||||
const SmallString<8> &getContents() const { return Contents; }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
|
@ -822,6 +822,9 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
|
||||
} else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
|
||||
Fixups = FragWithFixups->getFixups();
|
||||
Contents = FragWithFixups->getContents();
|
||||
} else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) {
|
||||
Fixups = FragWithFixups->getFixups();
|
||||
Contents = FragWithFixups->getContents();
|
||||
} else
|
||||
llvm_unreachable("Unknown fragment with fixups!");
|
||||
for (const MCFixup &Fixup : Fixups) {
|
||||
@ -951,16 +954,37 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
|
||||
MCContext &Context = Layout.getAssembler().getContext();
|
||||
uint64_t OldSize = DF.getContents().size();
|
||||
int64_t AddrDelta;
|
||||
bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
|
||||
assert(Abs && "We created a line delta with an invalid expression");
|
||||
(void) Abs;
|
||||
bool Abs = DF.getAddrDelta().evaluateAsAbsolute(AddrDelta, Layout);
|
||||
int64_t LineDelta;
|
||||
LineDelta = DF.getLineDelta();
|
||||
SmallString<8> &Data = DF.getContents();
|
||||
SmallVectorImpl<char> &Data = DF.getContents();
|
||||
Data.clear();
|
||||
raw_svector_ostream OSE(Data);
|
||||
DF.getFixups().clear();
|
||||
|
||||
if (Abs) {
|
||||
MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
|
||||
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