Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -253,8 +253,17 @@ /// Whether to use the GNU TLS opcode (instead of the standard opcode). bool UseGNUTLSOpcode; - /// Whether to emit DW_AT_[MIPS_]linkage_name. - bool UseLinkageNames; + /// When to emit DW_AT_[MIPS_]linkage_name. +public: + enum LinkageNameOption { + DefaultLinkageNames, // Default policy for platform/tuning. + AllLinkageNames, // Always. + AbstractLinkageNames, // Abstract subprograms only. + NoLinkageNames // Never. + }; + +private: + LinkageNameOption WhichLinkageNames; /// Version of dwarf we're emitting. unsigned DwarfVersion; @@ -485,8 +494,11 @@ SymSize[Sym] = Size; } - /// Returns whether to emit DW_AT_[MIPS_]linkage_name. - bool useLinkageNames() const { return UseLinkageNames; } + /// Returns whether to emit this DW_AT_[MIPS_]linkage_name. + bool useLinkageName(bool Abstract) const { + return WhichLinkageNames == AllLinkageNames || + (Abstract && WhichLinkageNames == AbstractLinkageNames); + } /// Returns whether to use DW_OP_GNU_push_tls_address, instead of the /// standard DW_OP_form_tls_address opcode Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -105,13 +105,17 @@ clEnumVal(Disable, "Disabled"), clEnumValEnd), cl::init(Default)); -static cl::opt -DwarfLinkageNames("dwarf-linkage-names", cl::Hidden, - cl::desc("Emit DWARF linkage-name attributes."), - cl::values(clEnumVal(Default, "Default for platform"), - clEnumVal(Enable, "Enabled"), - clEnumVal(Disable, "Disabled"), clEnumValEnd), - cl::init(Default)); +static cl::opt DwarfLinkageNames( + "dwarf-linkage-names", cl::Hidden, + cl::desc("Which DWARF linkage-name attributes to emit."), + cl::values(clEnumValN(DwarfDebug::DefaultLinkageNames, "Default", + "Default for platform"), + clEnumValN(DwarfDebug::AllLinkageNames, "All", "All"), + clEnumValN(DwarfDebug::AbstractLinkageNames, "Abstract", + "Abstract subprograms"), + clEnumValN(DwarfDebug::NoLinkageNames, "None", "None"), + clEnumValEnd), + cl::init(DwarfDebug::DefaultLinkageNames)); static const char *const DWARFGroupName = "DWARF Emission"; static const char *const DbgTimerName = "DWARF Debug Writer"; @@ -245,11 +249,14 @@ else HasDwarfPubSections = DwarfPubSections == Enable; - // SCE does not use linkage names. - if (DwarfLinkageNames == Default) - UseLinkageNames = !tuneForSCE(); - else - UseLinkageNames = DwarfLinkageNames == Enable; + // SCE defaults to linkage names only for abstract subprograms. + if (DwarfLinkageNames == DefaultLinkageNames) { + if (tuneForSCE()) + WhichLinkageNames = AbstractLinkageNames; + else + WhichLinkageNames = AllLinkageNames; + } else + WhichLinkageNames = DwarfLinkageNames; unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion; DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber Index: lib/CodeGen/AsmPrinter/DwarfUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.h +++ lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -243,8 +243,8 @@ void addConstantFPValue(DIE &Die, const MachineOperand &MO); void addConstantFPValue(DIE &Die, const ConstantFP *CFP); - /// Add a linkage name, if it isn't empty. - void addLinkageName(DIE &Die, StringRef LinkageName); + /// Add a linkage name, if it isn't empty and we're doing linkage names. + void addLinkageName(DIE &Die, StringRef LinkageName, bool Abstract = false); /// Add template parameters in buffer. void addTemplateParams(DIE &Buffer, DINodeArray TParams); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -664,8 +664,8 @@ addBlock(Die, dwarf::DW_AT_const_value, Block); } -void DwarfUnit::addLinkageName(DIE &Die, StringRef LinkageName) { - if (!LinkageName.empty() && DD->useLinkageNames()) +void DwarfUnit::addLinkageName(DIE &Die, StringRef LinkageName, bool Abstract) { + if (!LinkageName.empty() && (DD->useLinkageName(Abstract))) addString(Die, DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name : dwarf::DW_AT_MIPS_linkage_name, @@ -1169,8 +1169,11 @@ assert(((LinkageName.empty() || DeclLinkageName.empty()) || LinkageName == DeclLinkageName) && "decl has a linkage name and it is different"); - if (DeclLinkageName.empty()) - addLinkageName(SPDie, LinkageName); + if (DeclLinkageName.empty()) { + // Whether to emit this can depend on whether it's abstract. + bool Abstract = DU->getAbstractSPDies().lookup(SP); + addLinkageName(SPDie, LinkageName, Abstract); + } if (!DeclDie) return false; Index: test/DebugInfo/Generic/PR20038.ll =================================================================== --- test/DebugInfo/Generic/PR20038.ll +++ test/DebugInfo/Generic/PR20038.ll @@ -3,7 +3,7 @@ ; For some reason, the output when targetting sparc is not quite as expected. ; XFAIL: sparc -; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=Enable < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s +; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=All < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s ; IR generated from clang -O0 with: ; struct C { Index: test/DebugInfo/Generic/cross-cu-inlining.ll =================================================================== --- test/DebugInfo/Generic/cross-cu-inlining.ll +++ test/DebugInfo/Generic/cross-cu-inlining.ll @@ -1,7 +1,7 @@ ; REQUIRES: object-emission -; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=Enable < %s | llvm-dwarfdump -debug-dump=info - | FileCheck -implicit-check-not=DW_TAG %s -; RUN: %llc_dwarf -dwarf-accel-tables=Enable -dwarf-linkage-names=Enable -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck --check-prefix=CHECK-ACCEL --check-prefix=CHECK %s +; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=All < %s | llvm-dwarfdump -debug-dump=info - | FileCheck -implicit-check-not=DW_TAG %s +; RUN: %llc_dwarf -dwarf-accel-tables=Enable -dwarf-linkage-names=All -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck --check-prefix=CHECK-ACCEL --check-prefix=CHECK %s ; Build from source: ; $ clang++ a.cpp b.cpp -g -c -emit-llvm Index: test/DebugInfo/Generic/enum-types.ll =================================================================== --- test/DebugInfo/Generic/enum-types.ll +++ test/DebugInfo/Generic/enum-types.ll @@ -1,6 +1,6 @@ ; REQUIRES: object-emission ; -; RUN: %llc_dwarf -filetype=obj -O0 -dwarf-linkage-names=Enable < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s +; RUN: %llc_dwarf -filetype=obj -O0 -dwarf-linkage-names=All < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s ; Make sure we can handle enums with the same identifier but in enum types of ; different compile units. Index: test/DebugInfo/Generic/linkage-name-abstract.ll =================================================================== --- test/DebugInfo/Generic/linkage-name-abstract.ll +++ test/DebugInfo/Generic/linkage-name-abstract.ll @@ -0,0 +1,70 @@ +; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=Abstract < %s | llvm-dwarfdump -debug-dump=info - > %t +; RUN: FileCheck %s -check-prefix=ONENAME < %t +; RUN: FileCheck %s -check-prefix=REF < %t +; REQUIRES: object-emission + +; Verify that the only linkage-name present is the abstract origin of the +; inlined subprogram. + +; IR generated from clang -O0 with: +; void f1(); +; __attribute__((always_inline)) void f2() { +; f1(); +; } +; void f3() { +; f2(); +; } + +; Show that there's only one linkage_name. +; ONENAME: {{DW_AT(_MIPS)?_linkage_name}} +; ONENAME-NOT: {{DW_AT(_MIPS)?_linkage_name}} + +; Locate the subprogram DIE with the linkage name. +; Show that the inlined_subroutine refers to it. +; REF: DW_TAG_subprogram +; REF: [[FOO:0x.*]]: DW_TAG_subprogram +; REF-NOT: {{DW_TAG|NULL}} +; REF: {{DW_AT(_MIPS)?_linkage_name}} +; REF: DW_TAG_inlined_subroutine +; REF-NOT: {{DW_TAG|NULL}} +; REF: DW_AT_abstract_origin {{.*}} {[[FOO]]} + +; Function Attrs: alwaysinline uwtable +define void @_Z2f2v() #0 !dbg !4 { +entry: + call void @_Z2f1v(), !dbg !11 + ret void, !dbg !12 +} + +declare void @_Z2f1v() + +; Function Attrs: uwtable +define void @_Z2f3v() #2 !dbg !7 { +entry: + call void @_Z2f1v(), !dbg !13 + ret void, !dbg !15 +} + +attributes #0 = { alwaysinline uwtable } +attributes #2 = { uwtable } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!8, !9} +!llvm.ident = !{!10} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 265282)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, subprograms: !3) +!1 = !DIFile(filename: "linkage-name-abstract.cpp", directory: "/home/probinson/projects/scratch") +!2 = !{} +!3 = !{!4, !7} +!4 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, variables: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{null} +!7 = distinct !DISubprogram(name: "f3", linkageName: "_Z2f3v", scope: !1, file: !1, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, variables: !2) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{!"clang version 3.9.0 (trunk 265282)"} +!11 = !DILocation(line: 3, column: 3, scope: !4) +!12 = !DILocation(line: 4, column: 1, scope: !4) +!13 = !DILocation(line: 3, column: 3, scope: !4, inlinedAt: !14) +!14 = distinct !DILocation(line: 6, column: 3, scope: !7) +!15 = !DILocation(line: 7, column: 1, scope: !7) Index: test/DebugInfo/Generic/namespace.ll =================================================================== --- test/DebugInfo/Generic/namespace.ll +++ test/DebugInfo/Generic/namespace.ll @@ -1,6 +1,6 @@ ; REQUIRES: object-emission -; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=Enable < %s | llvm-dwarfdump - | FileCheck %s +; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=All < %s | llvm-dwarfdump - | FileCheck %s ; CHECK: debug_info contents ; CHECK: [[NS1:0x[0-9a-f]*]]:{{ *}}DW_TAG_namespace ; CHECK-NEXT: DW_AT_name{{.*}} = "A" Index: test/DebugInfo/Generic/namespace_function_definition.ll =================================================================== --- test/DebugInfo/Generic/namespace_function_definition.ll +++ test/DebugInfo/Generic/namespace_function_definition.ll @@ -1,6 +1,6 @@ ; REQUIRES: object-emission -; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=Enable < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s +; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=All < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s ; Generated from clang with the following source: ; namespace ns { Index: test/DebugInfo/Generic/namespace_inline_function_definition.ll =================================================================== --- test/DebugInfo/Generic/namespace_inline_function_definition.ll +++ test/DebugInfo/Generic/namespace_inline_function_definition.ll @@ -1,6 +1,6 @@ ; REQUIRES: object-emission -; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=Enable < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s +; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=All < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s ; Generate from clang with the following source. Note that the definition of ; the inline function follows its use to workaround another bug that should be Index: test/Linker/type-unique-odr-a.ll =================================================================== --- test/Linker/type-unique-odr-a.ll +++ test/Linker/type-unique-odr-a.ll @@ -1,6 +1,6 @@ ; REQUIRES: default_triple, object-emission ; -; RUN: llvm-link %s %p/type-unique-odr-b.ll -S -o - | %llc_dwarf -dwarf-linkage-names=Enable -filetype=obj -O0 | llvm-dwarfdump -debug-dump=info - | FileCheck %s +; RUN: llvm-link %s %p/type-unique-odr-b.ll -S -o - | %llc_dwarf -dwarf-linkage-names=All -filetype=obj -O0 | llvm-dwarfdump -debug-dump=info - | FileCheck %s ; ; Test ODR-based type uniquing for C++ class members. ; rdar://problem/15851313.