From d66140514def3436b50a292603e574917d2676d6 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 18 Jul 2018 18:04:42 +0000 Subject: [PATCH] [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. llvm-svn: 337411 --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 28 ++++++---- llvm/test/DebugInfo/X86/range_reloc.ll | 31 ++++++++-- llvm/test/DebugInfo/X86/range_reloc_base.ll | 59 +++++++++++++++++++ llvm/test/DebugInfo/X86/rnglists-nobase.ll | 87 ----------------------------- 4 files changed, 103 insertions(+), 102 deletions(-) create mode 100644 llvm/test/DebugInfo/X86/range_reloc_base.ll delete mode 100644 llvm/test/DebugInfo/X86/rnglists-nobase.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index e12c866..2fe6a2d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -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); diff --git a/llvm/test/DebugInfo/X86/range_reloc.ll b/llvm/test/DebugInfo/X86/range_reloc.ll index 472ffa3..c049740 100644 --- a/llvm/test/DebugInfo/X86/range_reloc.ll +++ b/llvm/test/DebugInfo/X86/range_reloc.ll @@ -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: diff --git a/llvm/test/DebugInfo/X86/range_reloc_base.ll b/llvm/test/DebugInfo/X86/range_reloc_base.ll new file mode 100644 index 0000000..0b224d1 --- /dev/null +++ b/llvm/test/DebugInfo/X86/range_reloc_base.ll @@ -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) diff --git a/llvm/test/DebugInfo/X86/rnglists-nobase.ll b/llvm/test/DebugInfo/X86/rnglists-nobase.ll deleted file mode 100644 index 56ac3ff..0000000 --- a/llvm/test/DebugInfo/X86/rnglists-nobase.ll +++ /dev/null @@ -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) -- 2.7.4