[DebugInfo] Dwarfv5: Avoid unnecessary base_address specifiers in rnglists

Since DWARFv5 rnglists are self descriptive and have distinct encodings
for base-relative (offset_pair) and absolute (start_length) entries,
there's no need to use a base address specifier when describing a lone
address range in a section.

Use that, and improve the test coverage a bit here to include cases like
this and others.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337411 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Blaikie 2018-07-18 18:04:42 +00:00
parent 461ab257e2
commit 7e2280c100
4 changed files with 103 additions and 102 deletions

View File

@ -2002,22 +2002,23 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
// or optnone where there may be holes in a single CU's section
// contributions.
auto *Base = CUBase;
if (!Base && P.second.size() > 1 && UseDwarfRangesBaseAddressSpecifier) {
if (!Base && P.second.size() > 1 &&
(UseDwarfRangesBaseAddressSpecifier || DwarfVersion >= 5)) {
BaseIsSet = true;
// FIXME/use care: This may not be a useful base address if it's not
// the lowest address/range in this object.
Base = P.second.front()->getStart();
if (DwarfVersion >= 5)
if (DwarfVersion >= 5) {
Asm->OutStreamer->AddComment("DW_RLE_base_address");
Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1);
else
} else
Asm->OutStreamer->EmitIntValue(-1, Size);
Asm->OutStreamer->AddComment(" base address");
Asm->OutStreamer->EmitSymbolValue(Base, Size);
} else if (BaseIsSet) {
} else if (BaseIsSet && DwarfVersion < 5) {
BaseIsSet = false;
if (DwarfVersion >= 5)
Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1);
else
Asm->OutStreamer->EmitIntValue(-1, Size);
assert(!Base);
Asm->OutStreamer->EmitIntValue(-1, Size);
Asm->OutStreamer->EmitIntValue(0, Size);
}
@ -2029,16 +2030,22 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
if (Base) {
if (DwarfVersion >= 5) {
// Emit DW_RLE_offset_pair when we have a base.
Asm->OutStreamer->AddComment("DW_RLE_offset_pair");
Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_offset_pair, 1);
Asm->OutStreamer->AddComment(" starting offset");
Asm->EmitLabelDifferenceAsULEB128(Begin, Base);
Asm->OutStreamer->AddComment(" ending offset");
Asm->EmitLabelDifferenceAsULEB128(End, Base);
} else {
Asm->EmitLabelDifference(Begin, Base, Size);
Asm->EmitLabelDifference(End, Base, Size);
}
} else if (DwarfVersion >= 5) {
Asm->OutStreamer->AddComment("DW_RLE_start_length");
Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_start_length, 1);
Asm->OutStreamer->AddComment(" start");
Asm->OutStreamer->EmitSymbolValue(Begin, Size);
Asm->OutStreamer->AddComment(" length");
Asm->EmitLabelDifferenceAsULEB128(End, Begin);
} else {
Asm->OutStreamer->EmitSymbolValue(Begin, Size);
@ -2046,9 +2053,10 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
}
}
}
if (DwarfVersion >= 5)
if (DwarfVersion >= 5) {
Asm->OutStreamer->AddComment("DW_RLE_end_of_list");
Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_end_of_list, 1);
else {
} else {
// Terminate the list with two 0 values.
Asm->OutStreamer->EmitIntValue(0, Size);
Asm->OutStreamer->EmitIntValue(0, Size);

View File

@ -1,11 +1,12 @@
; RUN: llc -filetype=asm -mtriple=x86_64-pc-linux-gnu %s -o - -use-dwarf-ranges-base-address-specifier | FileCheck --check-prefix=COMMON --check-prefix=BASE %s
; RUN: llc -filetype=asm -mtriple=x86_64-pc-linux-gnu %s -o - | FileCheck --check-prefix=COMMON --check-prefix=NOBASE %s
; RUN: %llc_dwarf -filetype=asm -mtriple=x86_64-pc-linux-gnu %s -o - -use-dwarf-ranges-base-address-specifier | FileCheck --check-prefix=COMMON --check-prefix=BASE %s
; RUN: %llc_dwarf -filetype=asm -mtriple=x86_64-pc-linux-gnu %s -o - | FileCheck --check-prefix=COMMON --check-prefix=NOBASE %s
; RUN: %llc_dwarf -filetype=asm -mtriple=x86_64-pc-linux-gnu %s -o - -dwarf-version 5 | FileCheck --check-prefix=DWARF5 %s
; Group ranges in a range list that apply to the same section and use a base
; address selection entry to reduce the number of relocations to one reloc per
; section per range list. DWARF5 debug_rnglist will be more efficient than this
; in terms of relocations, but it's still better than one reloc per entry in a
; range list.
; section per range list. DWARF5 debug_rnglist (with *x variants) are more
; efficient than this in terms of relocations, but it's still better than one
; reloc per entry in a range list.
; This is an object/executable size tradeoff - shrinking objects, but growing
; the linked executable. In one large binary tested, total object size (not just
@ -36,6 +37,26 @@
; COMMON-NEXT: .quad 0
; COMMON-NEXT: .quad 0
; DWARF5: {{^.Ldebug_ranges0}}
; DWARF5-NEXT: # DW_RLE_start_length
; DWARF5-NEXT: .quad .Lfunc_begin0 # start
; DWARF5-NEXT: .uleb128 .Lfunc_end0-.Lfunc_begin0 # length
; DWARF5-NEXT: # DW_RLE_base_address
; DWARF5-NEXT: .quad .Lfunc_begin1 # base address
; DWARF5-NEXT: # DW_RLE_offset_pair
; DWARF5-NEXT: .uleb128 .Lfunc_begin1-.Lfunc_begin1 # starting offset
; DWARF5-NEXT: .uleb128 .Lfunc_end1-.Lfunc_begin1 # ending offset
; DWARF5-NEXT: # DW_RLE_offset_pair
; DWARF5-NEXT: .uleb128 .Lfunc_begin3-.Lfunc_begin1 # starting offset
; DWARF5-NEXT: .uleb128 .Lfunc_end3-.Lfunc_begin1 # ending offset
; DWARF5-NEXT: # DW_RLE_start_length
; DWARF5-NEXT: .quad .Lfunc_begin4 # start
; DWARF5-NEXT: .uleb128 .Lfunc_end4-.Lfunc_begin4 # length
; DWARF5-NEXT: # DW_RLE_start_length
; DWARF5-NEXT: .quad .Lfunc_begin5 # start
; DWARF5-NEXT: .uleb128 .Lfunc_end5-.Lfunc_begin5 # length
; DWARF5-NEXT: # DW_RLE_end_of_list
; Function Attrs: noinline nounwind optnone uwtable
define void @_Z2f1v() #0 section "a" !dbg !7 {
entry:

View File

@ -0,0 +1,59 @@
; RUN: %llc_dwarf -filetype=asm -mtriple=x86_64-pc-linux-gnu %s -o - -use-dwarf-ranges-base-address-specifier | FileCheck %s
; RUN: %llc_dwarf -filetype=asm -mtriple=x86_64-pc-linux-gnu %s -o - | FileCheck %s
; RUN: %llc_dwarf -filetype=asm -mtriple=x86_64-pc-linux-gnu %s -o - -dwarf-version 5 | FileCheck --check-prefix=DWARF5 %s
; CHECK: {{^.Ldebug_ranges0}}
; CHECK-NEXT: .quad .Ltmp0-.Lfunc_begin0
; CHECK-NEXT: .quad .Ltmp1-.Lfunc_begin0
; CHECK-NEXT: .quad .Ltmp2-.Lfunc_begin0
; CHECK-NEXT: .quad .Ltmp3-.Lfunc_begin0
; CHECK-NEXT: .quad 0
; CHECK-NEXT: .quad 0
; DWARF5: {{^.Ldebug_ranges0}}
; DWARF5-NEXT: # DW_RLE_offset_pair
; DWARF5-NEXT: .uleb128 .Ltmp0-.Lfunc_begin0 # starting offset
; DWARF5-NEXT: .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset
; DWARF5-NEXT: # DW_RLE_offset_pair
; DWARF5-NEXT: .uleb128 .Ltmp2-.Lfunc_begin0 # starting offset
; DWARF5-NEXT: .uleb128 .Ltmp3-.Lfunc_begin0 # ending offset
; DWARF5-NEXT: # DW_RLE_end_of_list
; Function Attrs: noinline optnone uwtable
define dso_local void @_Z2f2v() !dbg !7 {
entry:
%b = alloca i8, align 1
call void @llvm.dbg.declare(metadata i8* %b, metadata !11, metadata !DIExpression()), !dbg !14
call void @_Z2f1v(), !dbg !15
call void @_Z2f1v(), !dbg !10
call void @_Z2f1v(), !dbg !16
ret void, !dbg !17
}
declare dso_local void @_Z2f1v()
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 7.0.0 (trunk 337388) (llvm/trunk 337392)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "range_reloc_base.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{!"clang version 7.0.0 (trunk 337388) (llvm/trunk 337392)"}
!7 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!8 = !DISubroutineType(types: !9)
!9 = !{null}
!10 = !DILocation(line: 3, column: 3, scope: !7)
!11 = !DILocalVariable(name: "b", scope: !12, file: !1, line: 5, type: !13)
!12 = distinct !DILexicalBlock(scope: !7, file: !1, line: 4, column: 3)
!13 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
!14 = !DILocation(line: 5, column: 10, scope: !12)
!15 = !DILocation(line: 6, column: 5, scope: !12)
!16 = !DILocation(line: 7, column: 5, scope: !12)
!17 = !DILocation(line: 9, column: 1, scope: !7)

View File

@ -1,87 +0,0 @@
; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t < %s
; RUN: llvm-dwarfdump -v %t | FileCheck %s
; We make sure that we generate DW_RLE_start_length range list entries when
; we do not have a base, which is the case when functions go into different
; sections. We should have 3 individual range list entries because there are
; 3 functions.
;
; From the following source:
;
; class A
; {
; public:
; A();
; };
;
; static A glob;
; void foo() {
; }
;
; Compile with clang -O1 -gdwarf-5 -S -emit-llvm
;
; CHECK: .debug_rnglists contents:
; CHECK-NEXT: 0x00000000: Range List Header: length = 0x00000027, version = 0x0005,
; CHECK-SAME: addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
; CHECK-NEXT: Ranges:
; CHECK-NEXT: 0x0000000c: [DW_RLE_start_length]:
; CHECK-NEXT: 0x00000016: [DW_RLE_start_length]:
; CHECK-NEXT: 0x00000020: [DW_RLE_start_length]:
; CHECK-NEXT: 0x0000002a: [DW_RLE_end_of_list ]
%class.A = type { i8 }
@_ZL4glob = internal global %class.A zeroinitializer, align 1, !dbg !0
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_xx.cpp, i8* null }]
; Function Attrs: uwtable
define internal fastcc void @__cxx_global_var_init() unnamed_addr section ".text.startup" !dbg !16 {
entry:
tail call void @_ZN1AC1Ev(%class.A* nonnull @_ZL4glob), !dbg !19
ret void, !dbg !19
}
declare dso_local void @_ZN1AC1Ev(%class.A*) unnamed_addr
; Function Attrs: norecurse nounwind readnone uwtable
define dso_local void @_Z3foov() local_unnamed_addr !dbg !20 {
entry:
ret void, !dbg !21
}
; Function Attrs: uwtable
define internal void @_GLOBAL__sub_I_xx.cpp() section ".text.startup" !dbg !22 {
entry:
tail call fastcc void @__cxx_global_var_init(), !dbg !24
ret void
}
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!12, !13, !14}
!llvm.ident = !{!15}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "glob", linkageName: "_ZL4glob", scope: !2, file: !3, line: 7, type: !6, isLocal: true, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (trunk 335191)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
!3 = !DIFile(filename: "test.cpp", directory: "/home/test", checksumkind: CSK_MD5, checksum: "535784cf49522e3a6d1166f6c4e482ba")
!4 = !{}
!5 = !{!0}
!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A", file: !3, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTS1A")
!7 = !{!8}
!8 = !DISubprogram(name: "A", scope: !6, file: !3, line: 4, type: !9, isLocal: false, isDefinition: false, scopeLine: 4, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true)
!9 = !DISubroutineType(types: !10)
!10 = !{null, !11}
!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
!12 = !{i32 2, !"Dwarf Version", i32 5}
!13 = !{i32 2, !"Debug Info Version", i32 3}
!14 = !{i32 1, !"wchar_size", i32 4}
!15 = !{!"clang version 7.0.0 (trunk 335191)"}
!16 = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !3, file: !3, line: 7, type: !17, isLocal: true, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4)
!17 = !DISubroutineType(types: !18)
!18 = !{null}
!19 = !DILocation(line: 7, column: 10, scope: !16)
!20 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 9, type: !17, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4)
!21 = !DILocation(line: 10, column: 1, scope: !20)
!22 = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_xx.cpp", scope: !3, file: !3, type: !23, isLocal: true, isDefinition: true, flags: DIFlagArtificial, isOptimized: true, unit: !2, retainedNodes: !4)
!23 = !DISubroutineType(types: !4)
!24 = !DILocation(line: 0, scope: !22)