// 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!");
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);
}
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));
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()));
}
}
}
}
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()) {
; 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
; 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
; 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
; 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]]}
; 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
; 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.
; 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 }
; 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
; 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
; 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
; 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
;
; 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, ...);
;
; 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
; 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")}}