Revise debug info machinery to digest nested functions and classes.

A certain GDB testsuite case (local.cc) has a function nested inside a
class nested inside another function.  GCC presents the innermost
function to llvm-convert first.  Heretofore, the debug info mistakenly
placed the inner function at module scope.  This patch walks the GCC
context links and instantiates the outer class and function so the
debug info is properly nested.  Radar 7426545.

llvm-svn: 100530
This commit is contained in:
Stuart Hastings 2010-04-06 17:19:32 +00:00
parent 3d45e17d15
commit c067196984
3 changed files with 28 additions and 9 deletions

View File

@ -800,12 +800,26 @@ void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) {
} else if (Context.isNameSpace()) { } else if (Context.isNameSpace()) {
DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context.getNode())); DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context.getNode()));
ContextDIE->addChild(Die); ContextDIE->addChild(Die);
} else if (Context.isSubprogram()) {
DIE *ContextDIE = createSubprogramDIE(DISubprogram(Context.getNode()),
/*MakeDecl=*/false);
ContextDIE->addChild(Die);
} else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode())) } else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode()))
ContextDIE->addChild(Die); ContextDIE->addChild(Die);
else else
ModuleCU->addDie(Die); ModuleCU->addDie(Die);
} }
/// isFunctionContext - True if given Context is nested within a function.
bool DwarfDebug::isFunctionContext(DIE *context) {
if (context == (DIE *)0)
return false;
if (context->getTag() == dwarf::DW_TAG_subprogram)
return true;
else
return isFunctionContext(context->getParent());
}
/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
/// given DIType. /// given DIType.
DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) { DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) {
@ -987,6 +1001,10 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
if (DIDescriptor(ContainingType.getNode()).isCompositeType()) if (DIDescriptor(ContainingType.getNode()).isCompositeType())
addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
getOrCreateTypeDIE(DIType(ContainingType.getNode()))); getOrCreateTypeDIE(DIType(ContainingType.getNode())));
else {
DIDescriptor Context = CTy.getContext();
addToContextOwner(&Buffer, Context);
}
break; break;
} }
default: default:
@ -1802,19 +1820,15 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
void DwarfDebug::constructSubprogramDIE(MDNode *N) { void DwarfDebug::constructSubprogramDIE(MDNode *N) {
DISubprogram SP(N); DISubprogram SP(N);
// Check for pre-existence.
if (ModuleCU->getDIE(N))
return;
if (!SP.isDefinition()) if (!SP.isDefinition())
// This is a method declaration which will be handled while constructing // This is a method declaration which will be handled while constructing
// class type. // class type.
return; return;
DIE *SubprogramDie = createSubprogramDIE(SP); // Check for pre-existence.
DIE *SubprogramDie = ModuleCU->getDIE(N);
// Add to map. if (!SubprogramDie)
ModuleCU->insertDIE(N, SubprogramDie); SubprogramDie = createSubprogramDIE(SP);
// Add to context owner. // Add to context owner.
addToContextOwner(SubprogramDie, SP.getContext()); addToContextOwner(SubprogramDie, SP.getContext());

View File

@ -332,6 +332,9 @@ private:
/// addToContextOwner - Add Die into the list of its context owner's children. /// addToContextOwner - Add Die into the list of its context owner's children.
void addToContextOwner(DIE *Die, DIDescriptor Context); void addToContextOwner(DIE *Die, DIDescriptor Context);
/// isFunctionContext - True if given Context is nested within a function.
bool isFunctionContext(DIE *context);
/// addType - Add a new type attribute to the specified entity. /// addType - Add a new type attribute to the specified entity.
void addType(DIE *Entity, DIType Ty); void addType(DIE *Entity, DIType Ty);

View File

@ -1,4 +1,4 @@
// RUN: %llvmgcc -g -S %s -o - | grep DW_TAG_pointer_type | grep "i32 524303, metadata .., metadata ..., metadata .., i32 ., i64 .., i64 .., i64 0, i32 64, metadata ..." // RUN: %llvmgcc -g -S %s -o - | FileCheck %s
// Here, second to last argument "i32 64" indicates that artificial type is set. // Here, second to last argument "i32 64" indicates that artificial type is set.
// Test to artificial attribute attahed to "this" pointer type. // Test to artificial attribute attahed to "this" pointer type.
// Radar 7655792 and 7655002 // Radar 7655792 and 7655002
@ -10,5 +10,7 @@ public:
int foo() { int foo() {
A a; A a;
// Matching "i32 64, metadata !<number>} ; [ DW_TAG_pointer_type ]"
// CHECK: i32 64, metadata {{![0-9]+\} ; \[ DW_TAG_pointer_type \]}}
return a.fn1(1); return a.fn1(1);
} }