summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Blaikie <dblaikie@gmail.com>2014-05-27 18:37:48 +0000
committerDavid Blaikie <dblaikie@gmail.com>2014-05-27 18:37:48 +0000
commit254d093f991287bea06e47c27ef2e14db36b1c59 (patch)
tree957787852e37aee1067aa0c24d4fa517da8f940d
parentdef5a057976fe7ab21c8a6e6ccf1311d20971f4f (diff)
DebugInfo: Lazily construct subprogram definition DIEs.
A further step to correctly emitting concrete out of line definitions preceeding inlined instances of the same program. To do this, emission of subprograms must be delayed until required since we don't know which (abstract only (if there's no out of line definition), concrete only (if there are no inlined instances), or both) DIEs are required at the start of the module. To reduce the test churn in the following commit that actually fixes the bug, this commit introduces the lazy DIE construction and cleans up test cases that are impacted by the changes in the resulting DIE ordering. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209675 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp32
-rw-r--r--test/DebugInfo/X86/concrete_out_of_line.ll31
-rw-r--r--test/DebugInfo/X86/debug-info-blocks.ll8
-rw-r--r--test/DebugInfo/X86/inline-member-function.ll17
-rw-r--r--test/DebugInfo/X86/inline-seldag-test.ll7
-rw-r--r--test/DebugInfo/X86/sret.ll4
-rw-r--r--test/DebugInfo/debug-info-qualifiers.ll2
-rw-r--r--test/DebugInfo/namespace.ll36
-rw-r--r--test/DebugInfo/varargs.ll14
-rw-r--r--test/Linker/type-unique-odr-a.ll12
10 files changed, 88 insertions, 75 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 6234f12dd2b..421cdbd95fa 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -314,7 +314,7 @@ bool DwarfDebug::isSubprogramContext(const MDNode *Context) {
// scope then create and insert DIEs for these variables.
DIE &DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU,
DISubprogram SP) {
- DIE *SPDie = SPCU.getDIE(SP);
+ DIE *SPDie = SPCU.getOrCreateSubprogramDIE(SP);
assert(SPDie && "Unable to find subprogram DIE!");
@@ -525,15 +525,18 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU,
DISubprogram SP(Scope->getScopeNode());
- if (!ProcessedSPNodes.insert(SP))
+ DIE *&AbsDef = AbstractSPDies[SP];
+ if (AbsDef)
return;
// Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
// was inlined from another compile unit.
DwarfCompileUnit &SPCU = *SPMap[SP];
- DIE *AbsDef = SPCU.getDIE(SP);
- assert(AbsDef);
- AbstractSPDies.insert(std::make_pair(SP, AbsDef));
+ AbsDef = SPCU.getOrCreateSubprogramDIE(SP);
+
+ if (!ProcessedSPNodes.insert(SP))
+ return;
+
SPCU.addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
createAndAddScopeChildren(SPCU, Scope, *AbsDef);
}
@@ -781,7 +784,7 @@ void DwarfDebug::beginModule() {
CU.createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i)));
DIArray SPs = CUNode.getSubprograms();
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i)
- constructSubprogramDIE(CU, SPs.getElement(i));
+ SPMap.insert(std::make_pair(SPs.getElement(i), &CU));
DIArray EnumTypes = CUNode.getEnumTypes();
for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i)
CU.getOrCreateTypeDIE(EnumTypes.getElement(i));
@@ -818,8 +821,17 @@ void DwarfDebug::finishSubprogramDefinitions() {
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);
+ // Perhaps the subprogram is in another CU (such as due to comdat
+ // folding, etc), in which case ignore it here.
+ if (SPMap[SP] != SPCU)
+ continue;
+ DIE *D = SPCU->getDIE(SP);
+ if (!D)
+ // Lazily construct the subprogram if we didn't see either concrete or
+ // inlined versions during codegen.
+ D = SPCU->getOrCreateSubprogramDIE(SP);
+ SPCU->applySubprogramAttributes(SP, *D);
+ SPCU->addGlobalName(SP.getName(), *D, resolve(SP.getContext()));
}
}
}
@@ -863,11 +875,11 @@ void DwarfDebug::collectDeadVariables() {
}
void DwarfDebug::finalizeModuleInfo() {
+ finishSubprogramDefinitions();
+
// 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/test/DebugInfo/X86/concrete_out_of_line.ll b/test/DebugInfo/X86/concrete_out_of_line.ll
index 5d4d5802bd1..5d9f6a5779b 100644
--- a/test/DebugInfo/X86/concrete_out_of_line.ll
+++ b/test/DebugInfo/X86/concrete_out_of_line.ll
@@ -14,6 +14,19 @@
; CHECK: [[RELEASE_DECL:0x........]]: DW_TAG_subprogram
; CHECK: [[DTOR_DECL:0x........]]: DW_TAG_subprogram
+; CHECK: [[D2_ABS:.*]]: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT_inline
+; CHECK-NEXT: DW_AT_{{.*}}linkage_name {{.*}}D2
+; CHECK-NEXT: DW_AT_specification {{.*}} {[[DTOR_DECL]]}
+; CHECK-NOT: DW_AT
+; CHECK: DW_TAG
+; CHECK: [[D1_ABS:.*]]: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT_inline
+; CHECK-NEXT: DW_AT_{{.*}}linkage_name {{.*}}D1
+; CHECK-NEXT: DW_AT_specification {{.*}} {[[DTOR_DECL]]}
+; CHECK-NOT: DW_AT
+; CHECK: [[D1_THIS_ABS:.*]]: DW_TAG_formal_parameter
+
; CHECK: [[RELEASE:0x........]]: DW_TAG_subprogram
; CHECK: DW_AT_specification {{.*}} {[[RELEASE_DECL]]}
; CHECK: DW_TAG_formal_parameter
@@ -27,29 +40,15 @@
; CHECK-NOT: NULL
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_inlined_subroutine
-; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D1_ABS:0x........]]}
+; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D1_ABS]]}
; CHECK-NOT: NULL
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_inlined_subroutine
-; 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-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-NOT: DW_AT
-; CHECK: DW_TAG
+; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D2_ABS]]}
; and then that a TAG_subprogram refers to it with AT_abstract_origin.
; CHECK: DW_TAG_subprogram
-; CHECK: DW_TAG_subprogram
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D1_ABS]]}
; CHECK: DW_TAG_formal_parameter
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D1_THIS_ABS]]}
diff --git a/test/DebugInfo/X86/debug-info-blocks.ll b/test/DebugInfo/X86/debug-info-blocks.ll
index 5feab247723..430c1575816 100644
--- a/test/DebugInfo/X86/debug-info-blocks.ll
+++ b/test/DebugInfo/X86/debug-info-blocks.ll
@@ -5,6 +5,11 @@
; rdar://problem/9279956
; test that the DW_AT_location of self is at ( fbreg +{{[0-9]+}}, deref, +{{[0-9]+}} )
+; CHECK: [[A:.*]]: DW_TAG_structure_type
+; CHECK-NEXT: DW_AT_APPLE_objc_complete_type
+; CHECK-NEXT: DW_AT_name{{.*}}"A"
+
+; CHECK: DW_TAG_subprogram
; CHECK: DW_TAG_subprogram
; CHECK: DW_TAG_subprogram
; CHECK-NOT: DW_TAG
@@ -32,9 +37,6 @@
; 0x91 = DW_OP_fbreg
; CHECK: DW_AT_location{{.*}}91 {{[0-9]+}} 06 23 {{[0-9]+}} )
-; 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
; CHECK-NEXT: {[[A]]}
diff --git a/test/DebugInfo/X86/inline-member-function.ll b/test/DebugInfo/X86/inline-member-function.ll
index 4a4a19c1913..3dc6043bf36 100644
--- a/test/DebugInfo/X86/inline-member-function.ll
+++ b/test/DebugInfo/X86/inline-member-function.ll
@@ -13,21 +13,24 @@
; return foo().func(i);
; }
+; CHECK: DW_TAG_structure_type
+; CHECK: DW_TAG_subprogram
+
+; But make sure we emit DW_AT_object_pointer on the abstract definition.
+; CHECK: [[ABSTRACT_ORIGIN:.*]]: DW_TAG_subprogram
+; CHECK-NOT: NULL
+; CHECK-NOT: TAG
+; CHECK: DW_AT_object_pointer
+
; Ensure we omit DW_AT_object_pointer on inlined subroutines.
; CHECK: DW_TAG_inlined_subroutine
-; CHECK-NEXT: DW_AT_abstract_origin {{.*}}{[[ABSTRACT_ORIGIN:0x[0-9a-e]*]]}
+; CHECK-NEXT: DW_AT_abstract_origin {{.*}}{[[ABSTRACT_ORIGIN]]}
; CHECK-NOT: NULL
; CHECK-NOT: DW_AT_object_pointer
; CHECK: DW_TAG_formal_parameter
; CHECK-NOT: DW_AT_artificial
; CHECK: DW_TAG
-; But make sure we emit DW_AT_object_pointer on the abstract definition.
-; CHECK: [[ABSTRACT_ORIGIN]]: DW_TAG_subprogram
-; CHECK-NOT: NULL
-; CHECK-NOT: TAG
-; CHECK: DW_AT_object_pointer
-
%struct.foo = type { i8 }
@i = global i32 0, align 4
diff --git a/test/DebugInfo/X86/inline-seldag-test.ll b/test/DebugInfo/X86/inline-seldag-test.ll
index f139140ee75..615f03a2ad2 100644
--- a/test/DebugInfo/X86/inline-seldag-test.ll
+++ b/test/DebugInfo/X86/inline-seldag-test.ll
@@ -11,12 +11,13 @@
; x = f(x);
; }
-; CHECK: DW_TAG_inlined_subroutine
-; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[F:0x.*]]}
-; CHECK: [[F]]: DW_TAG_subprogram
+; CHECK: [[F:.*]]: DW_TAG_subprogram
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}} "f"
+; CHECK: DW_TAG_inlined_subroutine
+; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[F]]}
+
; Make sure the condition test is attributed to the inline function, not the
; location of the test's operands within the caller.
diff --git a/test/DebugInfo/X86/sret.ll b/test/DebugInfo/X86/sret.ll
index 004632814c2..fed4334c27f 100644
--- a/test/DebugInfo/X86/sret.ll
+++ b/test/DebugInfo/X86/sret.ll
@@ -3,8 +3,8 @@
; Based on the debuginfo-tests/sret.cpp code.
-; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0xc68148e4333befda)
-; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0xc68148e4333befda)
+; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x72aabf538392d298)
+; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x72aabf538392d298)
%class.A = type { i32 (...)**, i32 }
%class.B = type { i8 }
diff --git a/test/DebugInfo/debug-info-qualifiers.ll b/test/DebugInfo/debug-info-qualifiers.ll
index 2aea7360707..b624d3874cb 100644
--- a/test/DebugInfo/debug-info-qualifiers.ll
+++ b/test/DebugInfo/debug-info-qualifiers.ll
@@ -21,8 +21,6 @@
; CHECK-NEXT: DW_AT_rvalue_reference DW_FORM_flag_present
;
; CHECK: DW_TAG_subprogram
-;
-; CHECK: DW_TAG_subprogram
; CHECK-NOT: DW_TAG_subprogram
; CHECK: DW_AT_name {{.*}}"l"
; CHECK-NOT: DW_TAG_subprogram
diff --git a/test/DebugInfo/namespace.ll b/test/DebugInfo/namespace.ll
index ca5cf808d18..a9de62c3906 100644
--- a/test/DebugInfo/namespace.ll
+++ b/test/DebugInfo/namespace.ll
@@ -16,27 +16,24 @@
; CHECK: [[I:0x[0-9a-f]*]]:{{ *}}DW_TAG_variable
; CHECK-NEXT: DW_AT_name{{.*}}= "i"
; CHECK-NOT: NULL
-; CHECK: DW_TAG_subprogram
+; CHECK: [[FOO:0x[0-9a-f]*]]:{{ *}}DW_TAG_structure_type
+; CHECK-NEXT: DW_AT_name{{.*}}= "foo"
+; CHECK-NEXT: DW_AT_declaration
+; CHECK-NOT: NULL
+; CHECK: [[BAR:0x[0-9a-f]*]]:{{ *}}DW_TAG_structure_type
+; CHECK-NEXT: DW_AT_name{{.*}}= "bar"
+; CHECK: NULL
+; CHECK: [[FUNC1:.*]]: DW_TAG_subprogram
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_MIPS_linkage_name
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name{{.*}}= "f1"
-; CHECK: [[FUNC1:0x[0-9a-f]*]]:{{ *}}DW_TAG_subprogram
+; CHECK: DW_TAG_subprogram
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_MIPS_linkage_name
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name{{.*}}= "f1"
; CHECK: NULL
-; CHECK-NOT: NULL
-; CHECK: [[FOO:0x[0-9a-f]*]]:{{ *}}DW_TAG_structure_type
-; CHECK-NEXT: DW_AT_name{{.*}}= "foo"
-; CHECK-NEXT: DW_AT_declaration
-; CHECK-NOT: NULL
-; CHECK: [[BAR:0x[0-9a-f]*]]:{{ *}}DW_TAG_structure_type
-; CHECK-NEXT: DW_AT_name{{.*}}= "bar"
-; CHECK: NULL
-; CHECK: NULL
-; CHECK: NULL
; CHECK-NOT: NULL
; CHECK: DW_TAG_imported_module
@@ -48,6 +45,13 @@
; CHECK: NULL
; CHECK-NOT: NULL
+; CHECK: DW_TAG_imported_module
+; Same bug as above, this should be F2, not F1
+; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F1]])
+; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x0b)
+; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS1]]})
+; CHECK-NOT: NULL
+
; CHECK: DW_TAG_subprogram
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_MIPS_linkage_name
@@ -99,13 +103,7 @@
; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS2]]})
; CHECK: NULL
; CHECK: NULL
-; CHECK-NOT: NULL
-
-; CHECK: DW_TAG_imported_module
-; Same bug as above, this should be F2, not F1
-; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F1]])
-; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x0b)
-; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS1]]})
+; CHECK: NULL
; CHECK: file_names[ [[F1]]]{{.*}}debug-info-namespace.cpp
; CHECK: file_names[ [[F2]]]{{.*}}foo.cpp
diff --git a/test/DebugInfo/varargs.ll b/test/DebugInfo/varargs.ll
index a3274142619..ddfcd858f53 100644
--- a/test/DebugInfo/varargs.ll
+++ b/test/DebugInfo/varargs.ll
@@ -13,25 +13,25 @@
;
; CHECK: DW_TAG_subprogram
; CHECK-NOT: DW_TAG
-; CHECK: DW_AT_name {{.*}} "b"
+; CHECK: DW_AT_name {{.*}} "a"
+; CHECK-NOT: DW_TAG
+; CHECK: DW_TAG_formal_parameter
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_formal_parameter
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_unspecified_parameters
;
-; Variadic C++ member function.
-; struct A { void a(int c, ...); }
-;
; CHECK: DW_TAG_subprogram
; CHECK-NOT: DW_TAG
-; CHECK: DW_AT_name {{.*}} "a"
-; CHECK-NOT: DW_TAG
-; CHECK: DW_TAG_formal_parameter
+; CHECK: DW_AT_name {{.*}} "b"
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_formal_parameter
; CHECK-NOT: DW_TAG
; CHECK: DW_TAG_unspecified_parameters
;
+; Variadic C++ member function.
+; struct A { void a(int c, ...); }
+;
; Variadic function pointer.
; void (*fptr)(int, ...);
;
diff --git a/test/Linker/type-unique-odr-a.ll b/test/Linker/type-unique-odr-a.ll
index 54befb75ba4..91c80339ec0 100644
--- a/test/Linker/type-unique-odr-a.ll
+++ b/test/Linker/type-unique-odr-a.ll
@@ -22,12 +22,6 @@
; return A().getFoo();
; }
;
-; CHECK: DW_TAG_subprogram
-; CHECK-NOT: DW_TAG
-; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_Z3bazv"
-; CHECK: DW_TAG_subprogram
-; CHECK-NOT: DW_TAG
-; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_ZL3barv"
; CHECK: DW_TAG_class_type
; CHECK-NEXT: DW_AT_name {{.*}} "A"
; CHECK-NOT: DW_TAG
@@ -39,6 +33,12 @@
; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_ZN1A6getFooEv"
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_name {{.*}} "getFoo"
+; CHECK: DW_TAG_subprogram
+; CHECK-NOT: DW_TAG
+; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_Z3bazv"
+; CHECK: DW_TAG_subprogram
+; CHECK-NOT: DW_TAG
+; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_ZL3barv"
; getFoo and A may only appear once.
; CHECK-NOT: {{(getFoo)|("A")}}