<rdar://problem/10212450>

Don't parse function types all the time, only parse them lazily.

llvm-svn: 140842
This commit is contained in:
Greg Clayton 2011-09-30 03:20:47 +00:00
parent 61e256aa69
commit 2bc22f83ad
4 changed files with 175 additions and 121 deletions

View File

@ -73,7 +73,7 @@ public:
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Destructor. /// Destructor.
//------------------------------------------------------------------ //------------------------------------------------------------------
~Block (); virtual ~Block ();
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Add a child to this object. /// Add a child to this object.

View File

@ -659,36 +659,36 @@ SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompile
if (die->Tag() != DW_TAG_subprogram) if (die->Tag() != DW_TAG_subprogram)
return NULL; return NULL;
clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die); // clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die);
const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind(); // const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind();
//
switch (containing_decl_kind) // switch (containing_decl_kind)
{ // {
case clang::Decl::Record: // case clang::Decl::Record:
case clang::Decl::CXXRecord: // case clang::Decl::CXXRecord:
case clang::Decl::ObjCClass: // case clang::Decl::ObjCClass:
case clang::Decl::ObjCImplementation: // case clang::Decl::ObjCImplementation:
case clang::Decl::ObjCInterface: // case clang::Decl::ObjCInterface:
// We have methods of a class or struct // // We have methods of a class or struct
{ // {
const DWARFDebugInfoEntry *containing_decl_die = m_decl_ctx_to_die[containing_decl_ctx]; // const DWARFDebugInfoEntry *containing_decl_die = m_decl_ctx_to_die[containing_decl_ctx];
assert (containing_decl_die); // assert (containing_decl_die);
Type *class_type = ResolveType (dwarf_cu, containing_decl_die); // Type *class_type = ResolveType (dwarf_cu, containing_decl_die);
if (class_type) // if (class_type)
class_type->GetClangFullType(); // class_type->GetClangFullType();
// Make sure the class definition contains the funciton DIE // // Make sure the class definition contains the funciton DIE
// we wanted to parse. If it does, we are done. Else, we need // // we wanted to parse. If it does, we are done. Else, we need
// to fall through and parse the function DIE stil... // // to fall through and parse the function DIE stil...
if (containing_decl_die->Contains (die)) // if (containing_decl_die->Contains (die))
break; // DIE has been parsed, we are done // break; // DIE has been parsed, we are done
} // }
// Fall through... // // Fall through...
//
default: // default:
// Parse the function prototype as a type that can then be added to concrete function instance // // Parse the function prototype as a type that can then be added to concrete function instance
ParseTypes (sc, dwarf_cu, die, false, false); // //ParseTypes (sc, dwarf_cu, die, false, false);
break; // break;
} // }
//FixupTypes(); //FixupTypes();
@ -2053,7 +2053,9 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
uint32_t uint32_t
SymbolFileDWARF::ResolveFunctions (const DIEArray &die_offsets, SymbolFileDWARF::ResolveFunctions (const DIEArray &die_offsets,
SymbolContextList& sc_list) SymbolContextList& sc_list,
const ConstString &name,
uint32_t name_type_mask)
{ {
DWARFDebugInfo* info = DebugInfo(); DWARFDebugInfo* info = DebugInfo();
if (info == NULL) if (info == NULL)
@ -2071,9 +2073,22 @@ SymbolFileDWARF::ResolveFunctions (const DIEArray &die_offsets,
const dw_offset_t die_offset = die_offsets[i]; const dw_offset_t die_offset = die_offsets[i];
const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
// If we aren't doing full names,
if ((name_type_mask & eFunctionNameTypeFull) == 0)
{
const char *name_cstr = name.GetCString();
if (ObjCLanguageRuntime::IsPossibleObjCMethodName(name_cstr))
continue;
}
const DWARFDebugInfoEntry* inlined_die = NULL; const DWARFDebugInfoEntry* inlined_die = NULL;
if (die->Tag() == DW_TAG_inlined_subroutine) if (die->Tag() == DW_TAG_inlined_subroutine)
{ {
// We only are looking for selectors, which disallows anything inlined
if (name_type_mask == eFunctionNameTypeSelector)
continue;
inlined_die = die; inlined_die = die;
while ((die = die->GetParent()) != NULL) while ((die = die->GetParent()) != NULL)
@ -2278,13 +2293,10 @@ SymbolFileDWARF::FindFunctions
} }
uint32_t uint32_t
SymbolFileDWARF::FindFunctions SymbolFileDWARF::FindFunctions (const ConstString &name,
( uint32_t name_type_mask,
const ConstString &name, bool append,
uint32_t name_type_mask, SymbolContextList& sc_list)
bool append,
SymbolContextList& sc_list
)
{ {
Timer scoped_timer (__PRETTY_FUNCTION__, Timer scoped_timer (__PRETTY_FUNCTION__,
"SymbolFileDWARF::FindFunctions (name = '%s')", "SymbolFileDWARF::FindFunctions (name = '%s')",
@ -2321,7 +2333,7 @@ SymbolFileDWARF::FindFunctions
DIEArray die_offsets; DIEArray die_offsets;
const uint32_t num_matches = m_apple_names.Find(name.GetCString(), die_offsets); const uint32_t num_matches = m_apple_names.Find(name.GetCString(), die_offsets);
if (num_matches > 0) if (num_matches > 0)
ResolveFunctions (die_offsets, sc_list_apple); ResolveFunctions (die_offsets, sc_list_apple, name, name_type_mask);
if (sc_list != sc_list_apple) if (sc_list != sc_list_apple)
assert (!"__apple_names results differ from DWARF index results"); assert (!"__apple_names results differ from DWARF index results");
} }
@ -2975,104 +2987,120 @@ SymbolFileDWARF::GetClangDeclContextForDIE (const SymbolContext &sc, DWARFCompil
} }
clang::DeclContext * clang::DeclContext *
SymbolFileDWARF::GetClangDeclContextContainingDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die) SymbolFileDWARF::GetClangDeclContextContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
{ {
if (m_clang_tu_decl == NULL) if (m_clang_tu_decl == NULL)
m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl(); m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl();
//printf ("SymbolFileDWARF::GetClangDeclContextContainingDIE ( die = 0x%8.8x )\n", die->GetOffset()); const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die);
const DWARFDebugInfoEntry * const decl_die = die;
clang::DeclContext *decl_ctx = NULL; if (decl_ctx_die)
while (die != NULL)
{ {
// If this is the original DIE that we are searching for a declaration DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find (decl_ctx_die);
// for, then don't look in the cache as we don't want our own decl if (pos != m_die_to_decl_ctx.end())
// context to be our decl context... return pos->second;
if (decl_die != die)
switch (decl_ctx_die->Tag())
{ {
DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die); case DW_TAG_compile_unit:
if (pos != m_die_to_decl_ctx.end()) return m_clang_tu_decl;
{
//printf ("SymbolFileDWARF::GetClangDeclContextContainingDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset());
return pos->second;
}
//printf ("SymbolFileDWARF::GetClangDeclContextContainingDIE ( die = 0x%8.8x ) checking parent 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset()); case DW_TAG_namespace:
switch (die->Tag())
{ {
case DW_TAG_namespace: const char *namespace_name = decl_ctx_die->GetAttributeValueAsString(this, cu, DW_AT_name, NULL);
if (namespace_name)
{ {
const char *namespace_name = die->GetAttributeValueAsString(this, curr_cu, DW_AT_name, NULL); Declaration decl; // TODO: fill in the decl object
if (namespace_name) clang::NamespaceDecl *namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, decl, GetClangDeclContextContainingDIE (cu, decl_ctx_die));
if (namespace_decl)
LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, decl_ctx_die);
return namespace_decl;
}
}
break;
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_class_type:
{
Type* type = ResolveType (cu, decl_ctx_die);
if (type)
{
clang::DeclContext *decl_ctx = ClangASTContext::GetDeclContextForType (type->GetClangForwardType ());
if (decl_ctx)
{ {
Declaration decl; // TODO: fill in the decl object LinkDeclContextToDIE (decl_ctx, decl_ctx_die);
clang::NamespaceDecl *namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, decl, GetClangDeclContextContainingDIE (curr_cu, die)); if (decl_ctx)
if (namespace_decl) return decl_ctx;
{
//printf ("SymbolFileDWARF::GetClangDeclContextContainingDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset());
LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die);
}
return namespace_decl;
} }
} }
break;
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_class_type:
{
Type* type = ResolveType (curr_cu, die);
pos = m_die_to_decl_ctx.find(die);
if (pos != m_die_to_decl_ctx.end())
{
//printf ("SymbolFileDWARF::GetClangDeclContextContainingDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset());
return pos->second;
}
else
{
if (type)
{
decl_ctx = ClangASTContext::GetDeclContextForType (type->GetClangForwardType ());
LinkDeclContextToDIE (decl_ctx, die);
if (decl_ctx)
return decl_ctx;
}
}
}
break;
default:
break;
} }
} break;
dw_offset_t die_offset = die->GetAttributeValueAsReference(this, curr_cu, DW_AT_specification, DW_INVALID_OFFSET); default:
if (die_offset != DW_INVALID_OFFSET) break;
{
//printf ("SymbolFileDWARF::GetClangDeclContextContainingDIE ( die = 0x%8.8x ) check DW_AT_specification 0x%8.8x\n", decl_die->GetOffset(), die_offset);
decl_ctx = GetClangDeclContextContainingDIEOffset (die_offset);
if (decl_ctx != m_clang_tu_decl)
return decl_ctx;
} }
die_offset = die->GetAttributeValueAsReference(this, curr_cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
if (die_offset != DW_INVALID_OFFSET)
{
//printf ("SymbolFileDWARF::GetClangDeclContextContainingDIE ( die = 0x%8.8x ) check DW_AT_abstract_origin 0x%8.8x\n", decl_die->GetOffset(), die_offset);
decl_ctx = GetClangDeclContextContainingDIEOffset (die_offset);
if (decl_ctx != m_clang_tu_decl)
return decl_ctx;
}
die = die->GetParent();
} }
// Right now we have only one translation unit per module...
//printf ("SymbolFileDWARF::GetClangDeclContextContainingDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), curr_cu->GetFirstDIEOffset());
return m_clang_tu_decl; return m_clang_tu_decl;
} }
const DWARFDebugInfoEntry *
SymbolFileDWARF::GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
{
if (cu && die)
{
const DWARFDebugInfoEntry * const decl_die = die;
while (die != NULL)
{
// If this is the original DIE that we are searching for a declaration
// for, then don't look in the cache as we don't want our own decl
// context to be our decl context...
if (decl_die != die)
{
switch (die->Tag())
{
case DW_TAG_compile_unit:
case DW_TAG_namespace:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_class_type:
return die;
default:
break;
}
}
dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET);
if (die_offset != DW_INVALID_OFFSET)
{
DWARFCompileUnit *spec_cu = cu;
const DWARFDebugInfoEntry *spec_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &spec_cu);
const DWARFDebugInfoEntry *spec_die_decl_ctx_die = GetDeclContextDIEContainingDIE (spec_cu, spec_die);
if (spec_die_decl_ctx_die)
return spec_die_decl_ctx_die;
}
die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
if (die_offset != DW_INVALID_OFFSET)
{
DWARFCompileUnit *abs_cu = cu;
const DWARFDebugInfoEntry *abs_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &abs_cu);
const DWARFDebugInfoEntry *abs_die_decl_ctx_die = GetDeclContextDIEContainingDIE (abs_cu, abs_die);
if (abs_die_decl_ctx_die)
return abs_die_decl_ctx_die;
}
die = die->GetParent();
}
}
return NULL;
}
// This function can be used when a DIE is found that is a forward declaration // This function can be used when a DIE is found that is a forward declaration
// DIE and we want to try and find a type that has the complete definition. // DIE and we want to try and find a type that has the complete definition.
TypeSP TypeSP

View File

@ -195,7 +195,10 @@ public:
clang::DeclContext * clang::DeclContext *
GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset); GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset);
const DWARFDebugInfoEntry *
GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
void void
SearchDeclContext (const clang::DeclContext *decl_context, SearchDeclContext (const clang::DeclContext *decl_context,
const char *name, const char *name,
@ -309,7 +312,9 @@ protected:
uint32_t ResolveFunctions ( uint32_t ResolveFunctions (
const DIEArray &die_offsets, const DIEArray &die_offsets,
lldb_private::SymbolContextList& sc_list); lldb_private::SymbolContextList& sc_list,
const lldb_private::ConstString &name,
uint32_t name_type_mask);
void FindFunctions( void FindFunctions(
const lldb_private::ConstString &name, const lldb_private::ConstString &name,

View File

@ -449,6 +449,27 @@ Function::GetClangDeclContext()
Type* Type*
Function::GetType() Function::GetType()
{ {
if (m_type == NULL)
{
SymbolContext sc;
CalculateSymbolContext (&sc);
if (!sc.module_sp)
return NULL;
SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
if (sym_vendor == NULL)
return NULL;
SymbolFile *sym_file = sym_vendor->GetSymbolFile();
if (sym_file == NULL)
return NULL;
return sym_file->ResolveTypeUID(m_type_uid);
}
return m_type; return m_type;
} }