diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 5c802f7a2ce..6234f12dd2b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -806,6 +806,25 @@ void DwarfDebug::beginModule() { SectionMap[Asm->getObjFileLowering().getTextSection()]; } +void DwarfDebug::finishSubprogramDefinitions() { + const Module *M = MMI->getModule(); + + NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); + for (MDNode *N : CU_Nodes->operands()) { + DICompileUnit TheCU(N); + // Construct subprogram DIE and add variables DIEs. + DwarfCompileUnit *SPCU = + static_cast(CUMap.lookup(TheCU)); + DIArray Subprograms = TheCU.getSubprograms(); + for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { + DISubprogram SP(Subprograms.getElement(i)); + if (DIE *D = SPCU->getDIE(SP)) + SPCU->applySubprogramAttributes(SP, *D); + } + } +} + + // Collect info for variables that were optimized out. void DwarfDebug::collectDeadVariables() { const Module *M = MMI->getModule(); @@ -847,6 +866,8 @@ void DwarfDebug::finalizeModuleInfo() { // Collect info for variables that were optimized out. collectDeadVariables(); + finishSubprogramDefinitions(); + // Handle anything that needs to be done on a per-unit basis after // all other generation. for (const auto &TheU : getUnits()) { diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 1b0b1ebafd8..4a4d01246c2 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -389,6 +389,8 @@ class DwarfDebug : public AsmPrinterHandler { /// \brief Collect info for variables that were optimized out. void collectDeadVariables(); + void finishSubprogramDefinitions(); + /// \brief Finish off debug information after all functions have been /// processed. void finalizeModuleInfo(); diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index c6e47ec0720..2707f8b73d8 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1389,6 +1389,11 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { // DW_TAG_inlined_subroutine may refer to this DIE. DIE &SPDie = createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, SP); + // Abort here and fill this in later, depending on whether or not this + // subprogram turns out to have inlined instances or not. + if (SP.isDefinition()) + return &SPDie; + applySubprogramAttributes(SP, SPDie); return &SPDie; } @@ -1397,7 +1402,8 @@ void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie) { DIE *DeclDie = nullptr; StringRef DeclLinkageName; if (DISubprogram SPDecl = SP.getFunctionDeclaration()) { - DeclDie = getOrCreateSubprogramDIE(SPDecl); + DeclDie = getDIE(SPDecl); + assert(DeclDie); DeclLinkageName = SPDecl.getLinkageName(); } diff --git a/test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll b/test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll index e81667f6793..5f7cb696d73 100644 --- a/test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll +++ b/test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll @@ -10,10 +10,10 @@ ; Check that the subprogram inside the class definition has low_pc, only ; attached to the definition. ; CHECK: [[FOO_INL:0x........]]: DW_TAG_subprogram -; CHECK-NEXT: DW_AT_MIPS_linkage_name {{.*}} "_ZZN1B2fnEvEN1A3fooEv" -; CHECK-NOT: NULL ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_low_pc +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_ZZN1B2fnEvEN1A3fooEv" ; And just double check that there's no out of line definition that references ; this subprogram. ; CHECK-NOT: DW_AT_specification {{.*}} {[[FOO_INL]]} diff --git a/test/DebugInfo/X86/concrete_out_of_line.ll b/test/DebugInfo/X86/concrete_out_of_line.ll index a8bf7ca5f9e..5d4d5802bd1 100644 --- a/test/DebugInfo/X86/concrete_out_of_line.ll +++ b/test/DebugInfo/X86/concrete_out_of_line.ll @@ -34,17 +34,16 @@ ; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D2_ABS:0x........]]} ; CHECK: [[D1_ABS]]: DW_TAG_subprogram +; CHECK-NEXT: DW_AT_inline ; CHECK-NEXT: DW_AT_{{.*}}linkage_name ; CHECK-NEXT: DW_AT_specification {{.*}} {[[DTOR_DECL]]} -; CHECK-NEXT: DW_AT_inline -; CHECK-NOT: DW_AT_inline -; CHECK-NOT: DW_TAG +; CHECK-NOT: DW_AT ; CHECK: [[D1_THIS_ABS:0x........]]: DW_TAG_formal_parameter ; CHECK: [[D2_ABS]]: DW_TAG_subprogram +; CHECK-NEXT: DW_AT_inline ; CHECK-NEXT: DW_AT_{{.*}}linkage_name ; CHECK-NEXT: DW_AT_specification {{.*}} {[[DTOR_DECL]]} -; CHECK-NEXT: DW_AT_inline -; CHECK-NOT: DW_AT_inline +; CHECK-NOT: DW_AT ; CHECK: DW_TAG ; and then that a TAG_subprogram refers to it with AT_abstract_origin. diff --git a/test/DebugInfo/X86/dbg-value-inlined-parameter.ll b/test/DebugInfo/X86/dbg-value-inlined-parameter.ll index b901711c2dc..74b2f8bc338 100644 --- a/test/DebugInfo/X86/dbg-value-inlined-parameter.ll +++ b/test/DebugInfo/X86/dbg-value-inlined-parameter.ll @@ -9,9 +9,9 @@ ; incorrect. They should be separate ; CHECK: [[ABS:.*]]: DW_TAG_subprogram ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_name {{.*}} "foo" -; CHECK-NOT: DW_TAG ; CHECK: DW_AT_high_pc +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_name {{.*}} "foo" ; CHECK: [[ABS_SP:.*]]: DW_TAG_formal_parameter ; CHECK-NEXT: DW_AT_name {{.*}} "sp" ; CHECK: [[ABS_NUMS:.*]]: DW_TAG_formal_parameter diff --git a/test/DebugInfo/X86/debug-info-blocks.ll b/test/DebugInfo/X86/debug-info-blocks.ll index b2531f64708..5feab247723 100644 --- a/test/DebugInfo/X86/debug-info-blocks.ll +++ b/test/DebugInfo/X86/debug-info-blocks.ll @@ -6,16 +6,20 @@ ; test that the DW_AT_location of self is at ( fbreg +{{[0-9]+}}, deref, +{{[0-9]+}} ) ; CHECK: DW_TAG_subprogram -; CHECK: DW_AT_name{{.*}}_block_invoke +; CHECK: DW_TAG_subprogram +; CHECK-NOT: DW_TAG ; CHECK: DW_AT_object_pointer +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_name{{.*}}_block_invoke -; CHECK-NOT: DW_TAG_subprogram +; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_formal_parameter -; CHECK-NEXT: DW_AT_name{{.*}}.block_descriptor +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_name{{.*}}.block_descriptor ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_location -; CHECK-NOT: DW_TAG_subprogram +; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_name{{.*}}"self" ; CHECK-NOT: DW_TAG @@ -31,7 +35,7 @@ ; CHECK: [[A:.*]]: DW_TAG_structure_type ; CHECK-NEXT: DW_AT_APPLE_objc_complete_type ; CHECK-NEXT: DW_AT_name{{.*}}"A" -; CHECK: [[APTR]]: DW_TAG_pointer_type [5] +; CHECK: [[APTR]]: DW_TAG_pointer_type ; CHECK-NEXT: {[[A]]} diff --git a/test/DebugInfo/X86/empty-and-one-elem-array.ll b/test/DebugInfo/X86/empty-and-one-elem-array.ll index f5c37df1e5e..974bd734795 100644 --- a/test/DebugInfo/X86/empty-and-one-elem-array.ll +++ b/test/DebugInfo/X86/empty-and-one-elem-array.ll @@ -28,11 +28,6 @@ declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone ; An empty array should not have an AT_upper_bound attribute. But an array of 1 ; should. -; CHECK: DW_TAG_base_type -; CHECK-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "int") -; CHECK-NEXT: DW_AT_encoding [DW_FORM_data1] (0x05) -; CHECK-NEXT: DW_AT_byte_size [DW_FORM_data1] (0x04) - ; int foo::b[1]: ; CHECK: DW_TAG_structure_type ; CHECK: DW_AT_name{{.*}}"foo" @@ -41,6 +36,11 @@ declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone ; CHECK-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "b") ; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] +; CHECK: DW_TAG_base_type +; CHECK-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "int") +; CHECK-NEXT: DW_AT_encoding [DW_FORM_data1] (0x05) +; CHECK-NEXT: DW_AT_byte_size [DW_FORM_data1] (0x04) + ; int[1]: ; CHECK: DW_TAG_array_type [{{.*}}] * ; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] diff --git a/test/DebugInfo/cross-cu-inlining.ll b/test/DebugInfo/cross-cu-inlining.ll index 44a1a585069..6e0378d57f0 100644 --- a/test/DebugInfo/cross-cu-inlining.ll +++ b/test/DebugInfo/cross-cu-inlining.ll @@ -23,13 +23,11 @@ ; CHECK: DW_TAG_compile_unit ; CHECK: DW_AT_name {{.*}} "a.cpp" ; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000[[INT:.*]]) ; CHECK: DW_TAG_inlined_subroutine ; CHECK-NEXT: DW_AT_abstract_origin {{.*}}[[ABS_FUNC:........]]) ; CHECK: DW_TAG_formal_parameter ; CHECK-NEXT: DW_AT_abstract_origin {{.*}}[[ABS_VAR:........]]) -; CHECK: 0x[[INT:.*]]: DW_TAG_base_type -; CHECK-NOT: DW_TAG -; CHECK: DW_AT_name {{.*}} "int" ; Check the abstract definition is in the 'b.cpp' CU and doesn't contain any ; concrete information (address range or variable location) @@ -40,9 +38,13 @@ ; CHECK: 0x[[ABS_VAR]]: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG ; CHECK-NOT: DW_AT_location -; CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000[[INT]]) +; CHECK: DW_AT_type [DW_FORM_ref4] {{.*}} {0x[[INT]]} ; CHECK-NOT: DW_AT_location +; CHECK: 0x[[INT]]: DW_TAG_base_type +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_name {{.*}} "int" + ; Check the concrete out of line definition references the abstract and ; provides the address range and variable location ; CHECK: DW_TAG_subprogram diff --git a/test/DebugInfo/namespace_function_definition.ll b/test/DebugInfo/namespace_function_definition.ll index 15f39fd6d9d..590f2b301ff 100644 --- a/test/DebugInfo/namespace_function_definition.ll +++ b/test/DebugInfo/namespace_function_definition.ll @@ -12,9 +12,9 @@ ; CHECK-NEXT: DW_AT_name {{.*}} "ns" ; CHECK: DW_TAG_subprogram ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_ZN2ns4funcEv" -; CHECK-NOT: DW_TAG ; CHECK: DW_AT_low_pc +; CHECK-NOT: DW_TAG +; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_ZN2ns4funcEv" ; CHECK: NULL ; CHECK: NULL