mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
DebugInfo: Create abstract function definitions even when concrete definitions preceed inline definitions.
After much puppetry, here's the major piece of the work to ensure that even when a concrete definition preceeds all inline definitions, an abstract definition is still created and referenced from both concrete and inline definitions. Variables are still broken in this case (see comment in dbg-value-inlined-parameter.ll test case) and will be addressed in follow up work. llvm-svn: 209677
This commit is contained in:
parent
b7b9f0c76e
commit
54d2925f43
@ -316,20 +316,6 @@ DIE &DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU,
|
|||||||
DISubprogram SP) {
|
DISubprogram SP) {
|
||||||
DIE *SPDie = SPCU.getOrCreateSubprogramDIE(SP);
|
DIE *SPDie = SPCU.getOrCreateSubprogramDIE(SP);
|
||||||
|
|
||||||
assert(SPDie && "Unable to find subprogram DIE!");
|
|
||||||
|
|
||||||
// If we're updating an abstract DIE, then we will be adding the children and
|
|
||||||
// object pointer later on. But what we don't want to do is process the
|
|
||||||
// concrete DIE twice.
|
|
||||||
if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) {
|
|
||||||
assert(SPDie == AbsSPDIE);
|
|
||||||
// Pick up abstract subprogram DIE.
|
|
||||||
SPDie = &SPCU.createAndAddDIE(
|
|
||||||
dwarf::DW_TAG_subprogram,
|
|
||||||
*SPCU.getOrCreateContextDIE(resolve(SP.getContext())));
|
|
||||||
SPCU.addDIEEntry(*SPDie, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym);
|
attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym);
|
||||||
|
|
||||||
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
|
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
|
||||||
@ -525,6 +511,8 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU,
|
|||||||
|
|
||||||
DISubprogram SP(Scope->getScopeNode());
|
DISubprogram SP(Scope->getScopeNode());
|
||||||
|
|
||||||
|
ProcessedSPNodes.insert(SP);
|
||||||
|
|
||||||
DIE *&AbsDef = AbstractSPDies[SP];
|
DIE *&AbsDef = AbstractSPDies[SP];
|
||||||
if (AbsDef)
|
if (AbsDef)
|
||||||
return;
|
return;
|
||||||
@ -532,10 +520,24 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU,
|
|||||||
// Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
|
// Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
|
||||||
// was inlined from another compile unit.
|
// was inlined from another compile unit.
|
||||||
DwarfCompileUnit &SPCU = *SPMap[SP];
|
DwarfCompileUnit &SPCU = *SPMap[SP];
|
||||||
AbsDef = SPCU.getOrCreateSubprogramDIE(SP);
|
DIE *ContextDIE;
|
||||||
|
|
||||||
if (!ProcessedSPNodes.insert(SP))
|
// Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with
|
||||||
return;
|
// the important distinction that the DIDescriptor is not associated with the
|
||||||
|
// DIE (since the DIDescriptor will be associated with the concrete DIE, if
|
||||||
|
// any). It could be refactored to some common utility function.
|
||||||
|
if (DISubprogram SPDecl = SP.getFunctionDeclaration()) {
|
||||||
|
ContextDIE = &SPCU.getUnitDie();
|
||||||
|
SPCU.getOrCreateSubprogramDIE(SPDecl);
|
||||||
|
} else
|
||||||
|
ContextDIE = SPCU.getOrCreateContextDIE(resolve(SP.getContext()));
|
||||||
|
|
||||||
|
// Passing null as the associated DIDescriptor because the abstract definition
|
||||||
|
// shouldn't be found by lookup.
|
||||||
|
AbsDef = &SPCU.createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE,
|
||||||
|
DIDescriptor());
|
||||||
|
SPCU.applySubprogramAttributes(SP, *AbsDef);
|
||||||
|
SPCU.addGlobalName(SP.getName(), *AbsDef, resolve(SP.getContext()));
|
||||||
|
|
||||||
SPCU.addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
|
SPCU.addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
|
||||||
createAndAddScopeChildren(SPCU, Scope, *AbsDef);
|
createAndAddScopeChildren(SPCU, Scope, *AbsDef);
|
||||||
@ -686,28 +688,6 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) {
|
|||||||
return NewCU;
|
return NewCU;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct subprogram DIE.
|
|
||||||
void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit &TheCU,
|
|
||||||
const MDNode *N) {
|
|
||||||
// FIXME: We should only call this routine once, however, during LTO if a
|
|
||||||
// program is defined in multiple CUs we could end up calling it out of
|
|
||||||
// beginModule as we walk the CUs.
|
|
||||||
|
|
||||||
DwarfCompileUnit *&CURef = SPMap[N];
|
|
||||||
if (CURef)
|
|
||||||
return;
|
|
||||||
CURef = &TheCU;
|
|
||||||
|
|
||||||
DISubprogram SP(N);
|
|
||||||
assert(SP.isSubprogram());
|
|
||||||
assert(SP.isDefinition());
|
|
||||||
|
|
||||||
DIE &SubprogramDie = *TheCU.getOrCreateSubprogramDIE(SP);
|
|
||||||
|
|
||||||
// Expose as a global name.
|
|
||||||
TheCU.addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
|
void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
|
||||||
const MDNode *N) {
|
const MDNode *N) {
|
||||||
DIImportedEntity Module(N);
|
DIImportedEntity Module(N);
|
||||||
@ -826,12 +806,19 @@ void DwarfDebug::finishSubprogramDefinitions() {
|
|||||||
if (SPMap[SP] != SPCU)
|
if (SPMap[SP] != SPCU)
|
||||||
continue;
|
continue;
|
||||||
DIE *D = SPCU->getDIE(SP);
|
DIE *D = SPCU->getDIE(SP);
|
||||||
if (!D)
|
if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) {
|
||||||
// Lazily construct the subprogram if we didn't see either concrete or
|
if (D)
|
||||||
// inlined versions during codegen.
|
// If this subprogram has an abstract definition, reference that
|
||||||
D = SPCU->getOrCreateSubprogramDIE(SP);
|
SPCU->addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
|
||||||
SPCU->applySubprogramAttributes(SP, *D);
|
} else {
|
||||||
SPCU->addGlobalName(SP.getName(), *D, resolve(SP.getContext()));
|
if (!D)
|
||||||
|
// Lazily construct the subprogram if we didn't see either concrete or
|
||||||
|
// inlined versions during codegen.
|
||||||
|
D = SPCU->getOrCreateSubprogramDIE(SP);
|
||||||
|
// And attach the attributes
|
||||||
|
SPCU->applySubprogramAttributes(SP, *D);
|
||||||
|
SPCU->addGlobalName(SP.getName(), *D, resolve(SP.getContext()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -861,7 +848,9 @@ void DwarfDebug::collectDeadVariables() {
|
|||||||
if (Variables.getNumElements() == 0)
|
if (Variables.getNumElements() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
DIE *SPDIE = SPCU->getDIE(SP);
|
DIE *SPDIE = AbstractSPDies.lookup(SP);
|
||||||
|
if (!SPDIE)
|
||||||
|
SPDIE = SPCU->getDIE(SP);
|
||||||
assert(SPDIE);
|
assert(SPDIE);
|
||||||
for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
|
for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
|
||||||
DIVariable DV(Variables.getElement(vi));
|
DIVariable DV(Variables.getElement(vi));
|
||||||
|
@ -491,9 +491,6 @@ class DwarfDebug : public AsmPrinterHandler {
|
|||||||
/// DW_TAG_compile_unit.
|
/// DW_TAG_compile_unit.
|
||||||
DwarfCompileUnit &constructDwarfCompileUnit(DICompileUnit DIUnit);
|
DwarfCompileUnit &constructDwarfCompileUnit(DICompileUnit DIUnit);
|
||||||
|
|
||||||
/// \brief Construct subprogram DIE.
|
|
||||||
void constructSubprogramDIE(DwarfCompileUnit &TheCU, const MDNode *N);
|
|
||||||
|
|
||||||
/// \brief Construct imported_module or imported_declaration DIE.
|
/// \brief Construct imported_module or imported_declaration DIE.
|
||||||
void constructImportedEntityDIE(DwarfCompileUnit &TheCU, const MDNode *N);
|
void constructImportedEntityDIE(DwarfCompileUnit &TheCU, const MDNode *N);
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
; CHECK: [[DTOR_DECL:0x........]]: DW_TAG_subprogram
|
; CHECK: [[DTOR_DECL:0x........]]: DW_TAG_subprogram
|
||||||
|
|
||||||
; CHECK: [[D2_ABS:.*]]: 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_{{.*}}linkage_name {{.*}}D2
|
||||||
; CHECK-NEXT: DW_AT_specification {{.*}} {[[DTOR_DECL]]}
|
; CHECK-NEXT: DW_AT_specification {{.*}} {[[DTOR_DECL]]}
|
||||||
|
; CHECK-NEXT: DW_AT_inline
|
||||||
; CHECK-NOT: DW_AT
|
; CHECK-NOT: DW_AT
|
||||||
; CHECK: DW_TAG
|
; CHECK: DW_TAG
|
||||||
; CHECK: [[D1_ABS:.*]]: DW_TAG_subprogram
|
; CHECK: [[D1_ABS:.*]]: DW_TAG_subprogram
|
||||||
; CHECK-NEXT: DW_AT_inline
|
|
||||||
; CHECK-NEXT: DW_AT_{{.*}}linkage_name {{.*}}D1
|
; CHECK-NEXT: DW_AT_{{.*}}linkage_name {{.*}}D1
|
||||||
; CHECK-NEXT: DW_AT_specification {{.*}} {[[DTOR_DECL]]}
|
; CHECK-NEXT: DW_AT_specification {{.*}} {[[DTOR_DECL]]}
|
||||||
|
; CHECK-NEXT: DW_AT_inline
|
||||||
; CHECK-NOT: DW_AT
|
; CHECK-NOT: DW_AT
|
||||||
; CHECK: [[D1_THIS_ABS:.*]]: DW_TAG_formal_parameter
|
; CHECK: [[D1_THIS_ABS:.*]]: DW_TAG_formal_parameter
|
||||||
|
|
||||||
@ -49,9 +49,11 @@
|
|||||||
; and then that a TAG_subprogram refers to it with AT_abstract_origin.
|
; 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-NOT: DW_TAG
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}} {[[D1_ABS]]}
|
||||||
; CHECK: DW_TAG_formal_parameter
|
; CHECK: DW_TAG_formal_parameter
|
||||||
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D1_THIS_ABS]]}
|
; CHECK-NOT: DW_TAG
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}} {[[D1_THIS_ABS]]}
|
||||||
; CHECK: DW_TAG_inlined_subroutine
|
; CHECK: DW_TAG_inlined_subroutine
|
||||||
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D2_ABS]]}
|
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[D2_ABS]]}
|
||||||
|
|
||||||
|
@ -5,12 +5,16 @@
|
|||||||
; RUN: llc -mtriple=x86_64-apple-darwin < %s -filetype=obj -regalloc=basic \
|
; RUN: llc -mtriple=x86_64-apple-darwin < %s -filetype=obj -regalloc=basic \
|
||||||
; RUN: | llvm-dwarfdump -debug-dump=info - | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s
|
; RUN: | llvm-dwarfdump -debug-dump=info - | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s
|
||||||
|
|
||||||
; FIXME: This is both a concrete and abstract definition, which is
|
; CHECK: DW_TAG_subprogram
|
||||||
; incorrect. They should be separate
|
; CHECK: DW_AT_abstract_origin {{.*}}{[[ABS:.*]]}
|
||||||
; CHECK: [[ABS:.*]]: DW_TAG_subprogram
|
; FIXME: An out of line definition preceeding an inline usage doesn't properly
|
||||||
; CHECK-NOT: DW_TAG
|
; reference abstract variables.
|
||||||
; CHECK: DW_AT_high_pc
|
; CHECK: DW_TAG_formal_parameter
|
||||||
; CHECK-NOT: DW_TAG
|
; CHECK-NEXT: DW_AT_name {{.*}} "sp"
|
||||||
|
; CHECK: DW_TAG_formal_parameter
|
||||||
|
; CHECK-NEXT: DW_AT_name {{.*}} "nums"
|
||||||
|
|
||||||
|
; CHECK: [[ABS]]: DW_TAG_subprogram
|
||||||
; CHECK: DW_AT_name {{.*}} "foo"
|
; CHECK: DW_AT_name {{.*}} "foo"
|
||||||
; CHECK: [[ABS_SP:.*]]: DW_TAG_formal_parameter
|
; CHECK: [[ABS_SP:.*]]: DW_TAG_formal_parameter
|
||||||
; CHECK-NEXT: DW_AT_name {{.*}} "sp"
|
; CHECK-NEXT: DW_AT_name {{.*}} "sp"
|
||||||
@ -26,10 +30,9 @@
|
|||||||
|
|
||||||
;CHECK: DW_TAG_formal_parameter
|
;CHECK: DW_TAG_formal_parameter
|
||||||
;FIXME: Linux shouldn't drop this parameter either...
|
;FIXME: Linux shouldn't drop this parameter either...
|
||||||
;FIXME: These parameters should have DW_AT_abstract_origin, instead of names.
|
;DARWIN-NEXT: DW_AT_abstract_origin {{.*}}{[[ABS_SP]]}
|
||||||
;DARWIN-NEXT: DW_AT_name {{.*}} "sp"
|
|
||||||
;DARWIN: DW_TAG_formal_parameter
|
;DARWIN: DW_TAG_formal_parameter
|
||||||
;CHECK-NEXT: DW_AT_name {{.*}} "nums"
|
;CHECK-NEXT: DW_AT_abstract_origin {{.*}}{[[ABS_NUMS]]}
|
||||||
;CHECK-NOT: DW_TAG_formal_parameter
|
;CHECK-NOT: DW_TAG_formal_parameter
|
||||||
|
|
||||||
%struct.S1 = type { float*, i32 }
|
%struct.S1 = type { float*, i32 }
|
||||||
|
@ -25,9 +25,11 @@
|
|||||||
; CHECK: DW_TAG_subprogram
|
; CHECK: DW_TAG_subprogram
|
||||||
; CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000[[INT:.*]])
|
; CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000[[INT:.*]])
|
||||||
; CHECK: DW_TAG_inlined_subroutine
|
; CHECK: DW_TAG_inlined_subroutine
|
||||||
; CHECK-NEXT: DW_AT_abstract_origin {{.*}}[[ABS_FUNC:........]])
|
; CHECK-NOT: DW_TAG
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}}[[ABS_FUNC:........]])
|
||||||
; CHECK: DW_TAG_formal_parameter
|
; CHECK: DW_TAG_formal_parameter
|
||||||
; CHECK-NEXT: DW_AT_abstract_origin {{.*}}[[ABS_VAR:........]])
|
; CHECK-NOT: DW_TAG
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}}[[ABS_VAR:........]])
|
||||||
|
|
||||||
; Check the abstract definition is in the 'b.cpp' CU and doesn't contain any
|
; Check the abstract definition is in the 'b.cpp' CU and doesn't contain any
|
||||||
; concrete information (address range or variable location)
|
; concrete information (address range or variable location)
|
||||||
@ -48,10 +50,13 @@
|
|||||||
; Check the concrete out of line definition references the abstract and
|
; Check the concrete out of line definition references the abstract and
|
||||||
; provides the address range and variable location
|
; provides the address range and variable location
|
||||||
; CHECK: DW_TAG_subprogram
|
; CHECK: DW_TAG_subprogram
|
||||||
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {0x[[ABS_FUNC]]}
|
; CHECK-NOT: DW_TAG
|
||||||
; CHECK: DW_AT_low_pc
|
; CHECK: DW_AT_low_pc
|
||||||
|
; CHECK-NOT: DW_TAG
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}} {0x[[ABS_FUNC]]}
|
||||||
; CHECK: DW_TAG_formal_parameter
|
; CHECK: DW_TAG_formal_parameter
|
||||||
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {0x[[ABS_VAR]]}
|
; CHECK-NOT: DW_TAG
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}} {0x[[ABS_VAR]]}
|
||||||
; CHECK: DW_AT_location
|
; CHECK: DW_AT_location
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user