1
0
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:
Hsiangkai Wang 2018-08-01 02:18:06 +00:00
parent da5081315b
commit 429710b3ef
6 changed files with 170 additions and 17 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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);
MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
AddrDelta, OSE);
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();
}

View File

@ -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);

View File

@ -0,0 +1,2 @@
if not 'RISCV' in config.root.targets:
config.unsupported = True

View 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)