Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -239,8 +239,8 @@ /// Add a Dwarf expression attribute data and value. void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr); - void applySubprogramAttributesToDefinition(const DISubprogram *SP, - DIE &SPDie); + void applySubprogramAttributesToDefinition(const DISubprogram *SP, DIE &SPDie, + bool Abstract); /// getRangeLists - Get the vector of range lists. const SmallVectorImpl &getRangeLists() const { Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -641,7 +641,7 @@ // Passing null as the associated node because the abstract definition // shouldn't be found by lookup. AbsDef = &createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr); - applySubprogramAttributesToDefinition(SP, *AbsDef); + applySubprogramAttributesToDefinition(SP, *AbsDef, /*Abstract=*/true); if (!includeMinimalInlineScopes()) addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); @@ -692,7 +692,7 @@ D = getOrCreateSubprogramDIE(SP); if (D) // And attach the attributes - applySubprogramAttributesToDefinition(SP, *D); + applySubprogramAttributesToDefinition(SP, *D, /*Abstract=*/false); } } void DwarfCompileUnit::collectDeadVariables(const DISubprogram *SP) { @@ -823,10 +823,10 @@ } void DwarfCompileUnit::applySubprogramAttributesToDefinition( - const DISubprogram *SP, DIE &SPDie) { + const DISubprogram *SP, DIE &SPDie, bool Abstract) { auto *SPDecl = SP->getDeclaration(); auto *Context = resolve(SPDecl ? SPDecl->getScope() : SP->getScope()); - applySubprogramAttributes(SP, SPDie, includeMinimalInlineScopes()); + applySubprogramAttributes(SP, SPDie, includeMinimalInlineScopes(), Abstract); addGlobalName(SP->getName(), SPDie, Context); } Index: lib/CodeGen/AsmPrinter/DwarfUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.h +++ lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -107,7 +107,8 @@ DwarfUnit(dwarf::Tag, const DICompileUnit *CU, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU); - bool applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE &SPDie); + bool applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE &SPDie, + bool Abstract); public: virtual ~DwarfUnit(); @@ -244,7 +245,7 @@ void addConstantFPValue(DIE &Die, const ConstantFP *CFP); /// Add a linkage name, if it isn't empty. - void addLinkageName(DIE &Die, StringRef LinkageName); + void addLinkageName(DIE &Die, StringRef LinkageName, bool Force = false); /// Add template parameters in buffer. void addTemplateParams(DIE &Buffer, DINodeArray TParams); @@ -281,7 +282,7 @@ DIE *getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal = false); void applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, - bool Minimal = false); + bool Minimal = false, bool Abstract = false); /// Find existing DIE or create new DIE for the given type. DIE *getOrCreateTypeDIE(const MDNode *N); 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 Force) { + if (!LinkageName.empty() && (DD->useLinkageNames() || Force)) addString(Die, DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name : dwarf::DW_AT_MIPS_linkage_name, @@ -1142,7 +1142,7 @@ } bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP, - DIE &SPDie) { + DIE &SPDie, bool Abstract) { DIE *DeclDie = nullptr; StringRef DeclLinkageName; if (auto *SPDecl = SP->getDeclaration()) { @@ -1170,7 +1170,7 @@ LinkageName == DeclLinkageName) && "decl has a linkage name and it is different"); if (DeclLinkageName.empty()) - addLinkageName(SPDie, LinkageName); + addLinkageName(SPDie, LinkageName, Abstract); if (!DeclDie) return false; @@ -1182,9 +1182,9 @@ } void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, - bool Minimal) { + bool Minimal, bool Abstract) { if (!Minimal) - if (applySubprogramDefinitionAttributes(SP, SPDie)) + if (applySubprogramDefinitionAttributes(SP, SPDie, Abstract)) return; // Constructors and operators for anonymous aggregates do not have names. 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,75 @@ +; RUN: %llc_dwarf -O0 -filetype=obj -dwarf-linkage-names=Disable < %s | llvm-dwarfdump -debug-dump=info - > %t +; RUN: FileCheck %s -check-prefix=ONENAME < %t +; RUN: FileCheck %s -check-prefix=REF < %t +; REQUIRES: object-emission + +; Even with linkage-names disabled, the abstract-origin of inlined subprograms +; needs a linkage name (there's no other way to find that name). + +; IR generated from clang -O0 with: +; int i = 2; +; __attribute__((always_inline)) int foo() { +; return i; +; } +; int bar() { +; return 1 + foo(); +; } + +; 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]]} + +@i = global i32 2, align 4 + +; Function Attrs: alwaysinline nounwind uwtable +define i32 @_Z3foov() #0 !dbg !4 { +entry: + %0 = load i32, i32* @i, align 4, !dbg !14 + ret i32 %0, !dbg !15 +} + +; Function Attrs: nounwind uwtable +define i32 @_Z3barv() #1 !dbg !8 { +entry: + %0 = load i32, i32* @i, align 4, !dbg !16 + %add = add nsw i32 1, %0, !dbg !18 + ret i32 %add, !dbg !19 +} + +attributes #0 = { alwaysinline nounwind uwtable } +attributes #1 = { nounwind uwtable } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!11, !12} +!llvm.ident = !{!13} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 265000)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3, globals: !9) +!1 = !DIFile(filename: "t.cpp", directory: "/home/probinson/projects/scratch") +!2 = !{} +!3 = !{!4, !8} +!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, variables: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{!7} +!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!8 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 6, type: !5, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false, variables: !2) +!9 = !{!10} +!10 = !DIGlobalVariable(name: "i", scope: !0, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, variable: i32* @i) +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{!"clang version 3.9.0 (trunk 265000)"} +!14 = !DILocation(line: 4, column: 10, scope: !4) +!15 = !DILocation(line: 4, column: 3, scope: !4) +!16 = !DILocation(line: 4, column: 10, scope: !4, inlinedAt: !17) +!17 = distinct !DILocation(line: 7, column: 14, scope: !8) +!18 = !DILocation(line: 7, column: 12, scope: !8) +!19 = !DILocation(line: 7, column: 3, scope: !8)