Emit method definition DIE at module level (even for methods with inlined functino body at soure level) so that the debugger can invoke it. This fixes many test failures in gdb test suite.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@90375 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Devang Patel
2009-12-03 01:25:38 +00:00
parent b8e675c3c1
commit 1d5cc1db59
2 changed files with 90 additions and 28 deletions

View File

@ -891,8 +891,8 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
continue; continue;
DIE *ElemDie = NULL; DIE *ElemDie = NULL;
if (Element.getTag() == dwarf::DW_TAG_subprogram) if (Element.getTag() == dwarf::DW_TAG_subprogram)
ElemDie = createSubprogramDIE(DW_Unit, ElemDie = createMemberSubprogramDIE(DW_Unit,
DISubprogram(Element.getNode())); DISubprogram(Element.getNode()));
else else
ElemDie = createMemberDIE(DW_Unit, ElemDie = createMemberDIE(DW_Unit,
DIDerivedType(Element.getNode())); DIDerivedType(Element.getNode()));
@ -1082,16 +1082,12 @@ DIE *DwarfDebug::createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT){
return MemberDie; return MemberDie;
} }
/// createSubprogramDIE - Create new DIE using SP. /// createRawSubprogramDIE - Create new partially incomplete DIE. This is
DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit, /// a helper routine used by createMemberSubprogramDIE and
const DISubprogram &SP, /// createSubprogramDIE.
bool IsConstructor, DIE *DwarfDebug::createRawSubprogramDIE(CompileUnit *DW_Unit,
bool IsInlined) { const DISubprogram &SP) {
DIE *SPDie = ModuleCU->getDIE(SP.getNode()); DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram);
if (SPDie)
return SPDie;
SPDie = new DIE(dwarf::DW_TAG_subprogram);
addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName()); addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName());
StringRef LinkageName = SP.getLinkageName(); StringRef LinkageName = SP.getLinkageName();
@ -1107,9 +1103,6 @@ DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit,
} }
addSourceLine(SPDie, &SP); addSourceLine(SPDie, &SP);
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
// Add prototyped tag, if C or ObjC. // Add prototyped tag, if C or ObjC.
unsigned Lang = SP.getCompileUnit().getLanguage(); unsigned Lang = SP.getCompileUnit().getLanguage();
if (Lang == dwarf::DW_LANG_C99 || Lang == dwarf::DW_LANG_C89 || if (Lang == dwarf::DW_LANG_C99 || Lang == dwarf::DW_LANG_C89 ||
@ -1117,19 +1110,70 @@ DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit,
addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1);
// Add Return Type. // Add Return Type.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
unsigned SPTag = SPTy.getTag(); unsigned SPTag = SPTy.getTag();
if (!IsConstructor) { if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type)
if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type) addType(DW_Unit, SPDie, SPTy);
addType(DW_Unit, SPDie, SPTy); else
else addType(DW_Unit, SPDie, DIType(Args.getElement(0).getNode()));
addType(DW_Unit, SPDie, DIType(Args.getElement(0).getNode()));
} return SPDie;
}
/// createMemberSubprogramDIE - Create new member DIE using SP. This routine
/// always returns a die with DW_AT_declaration attribute.
DIE *DwarfDebug::createMemberSubprogramDIE(CompileUnit *DW_Unit,
const DISubprogram &SP) {
DIE *SPDie = ModuleCU->getDIE(SP.getNode());
if (!SPDie)
SPDie = createSubprogramDIE(DW_Unit, SP);
// If SPDie has DW_AT_declaration then reuse it.
if (!SP.isDefinition())
return SPDie;
// Otherwise create new DIE for the declaration. First push definition
// DIE at the top level.
if (TopLevelDIEs.insert(SPDie))
TopLevelDIEsVector.push_back(SPDie);
SPDie = createRawSubprogramDIE(DW_Unit, SP);
// Add arguments.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
unsigned SPTag = SPTy.getTag();
if (SPTag == dwarf::DW_TAG_subroutine_type)
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
addType(DW_Unit, Arg, DIType(Args.getElement(i).getNode()));
addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ??
SPDie->addChild(Arg);
}
addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
return SPDie;
}
/// createSubprogramDIE - Create new DIE using SP.
DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit,
const DISubprogram &SP) {
DIE *SPDie = ModuleCU->getDIE(SP.getNode());
if (SPDie)
return SPDie;
SPDie = createRawSubprogramDIE(DW_Unit, SP);
if (!SP.isDefinition()) { if (!SP.isDefinition()) {
addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
// Add arguments. Do not add arguments for subprogram definition. They will // Add arguments. Do not add arguments for subprogram definition. They will
// be handled through RecordVariable. // be handled while processing variables.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
unsigned SPTag = SPTy.getTag();
if (SPTag == dwarf::DW_TAG_subroutine_type) if (SPTag == dwarf::DW_TAG_subroutine_type)
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
@ -1641,7 +1685,8 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
ModuleCU->insertDIE(N, VariableDie); ModuleCU->insertDIE(N, VariableDie);
// Add to context owner. // Add to context owner.
ModuleCU->getCUDie()->addChild(VariableDie); if (TopLevelDIEs.insert(VariableDie))
TopLevelDIEsVector.push_back(VariableDie);
// Expose as global. FIXME - need to check external flag. // Expose as global. FIXME - need to check external flag.
ModuleCU->addGlobal(DI_GV.getName(), VariableDie); ModuleCU->addGlobal(DI_GV.getName(), VariableDie);
@ -1674,7 +1719,8 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) {
// Add to context owner. // Add to context owner.
if (SP.getContext().getNode() == SP.getCompileUnit().getNode()) if (SP.getContext().getNode() == SP.getCompileUnit().getNode())
ModuleCU->getCUDie()->addChild(SubprogramDie); if (TopLevelDIEs.insert(SubprogramDie))
TopLevelDIEsVector.push_back(SubprogramDie);
// Expose as global. // Expose as global.
ModuleCU->addGlobal(SP.getName(), SubprogramDie); ModuleCU->addGlobal(SP.getName(), SubprogramDie);
@ -1775,6 +1821,11 @@ void DwarfDebug::endModule() {
addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
} }
// Insert top level DIEs.
for (SmallVector<DIE *, 4>::iterator TI = TopLevelDIEsVector.begin(),
TE = TopLevelDIEsVector.end(); TI != TE; ++TI)
ModuleCU->getCUDie()->addChild(*TI);
// Standard sections final addresses. // Standard sections final addresses.
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
EmitLabel("text_end", 0); EmitLabel("text_end", 0);

View File

@ -157,6 +157,10 @@ class DwarfDebug : public Dwarf {
/// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs. /// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs.
SmallPtrSet<DIE *, 4> AbstractSubprogramDIEs; SmallPtrSet<DIE *, 4> AbstractSubprogramDIEs;
/// TopLevelDIEs - Collection of top level DIEs.
SmallPtrSet<DIE *, 4> TopLevelDIEs;
SmallVector<DIE *, 4> TopLevelDIEsVector;
/// ScopedGVs - Tracks global variables that are not at file scope. /// ScopedGVs - Tracks global variables that are not at file scope.
/// For example void f() { static int b = 42; } /// For example void f() { static int b = 42; }
SmallVector<WeakVH, 4> ScopedGVs; SmallVector<WeakVH, 4> ScopedGVs;
@ -342,10 +346,17 @@ class DwarfDebug : public Dwarf {
DIE *createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT); DIE *createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT);
/// createSubprogramDIE - Create new DIE using SP. /// createSubprogramDIE - Create new DIE using SP.
DIE *createSubprogramDIE(CompileUnit *DW_Unit, DIE *createSubprogramDIE(CompileUnit *DW_Unit, const DISubprogram &SP);
const DISubprogram &SP,
bool IsConstructor = false, /// createMemberSubprogramDIE - Create new member DIE using SP. This
bool IsInlined = false); /// routine always returns a die with DW_AT_declaration attribute.
DIE *createMemberSubprogramDIE(CompileUnit *DW_Unit, const DISubprogram &SP);
/// createRawSubprogramDIE - Create new partially incomplete DIE. This is
/// a helper routine used by createMemberSubprogramDIE and
/// createSubprogramDIE.
DIE *createRawSubprogramDIE(CompileUnit *DW_Unit, const DISubprogram &SP);
/// findCompileUnit - Get the compile unit for the given descriptor. /// findCompileUnit - Get the compile unit for the given descriptor.
/// ///