This patch is part of ongoing work to extract type
information from the Objective-C runtime.
This patch takes the old AppleObjCSymbolVendor and
replaces it with an AppleObjCTypeVendor, which is
much more lightweight. Specifically, the SymbolVendor
needs to pretend that there is a backing symbol file
for the Types it vends, whereas a TypeVendor only
vends bare ClangASTTypes. These ClangASTTypes only
need to exist in an ASTContext.
The ClangASTSource now falls back to the runtime's
TypeVendor (if one exists) if the debug information
doesn't find a complete type for a particular
Objective-C interface. The runtime's TypeVendor
maintains an ASTContext full of types it knows about,
and re-uses the ISA-based type query information used
by the ValueObjects.
Currently, the runtime's TypeVendor doesn't provide
useful answers because we haven't yet implemented a
way to iterate across all ISAs contained in the target
process's runtime. That's the next step.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@163651 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp
index f94eb9c..80a9ea3 100644
--- a/source/Expression/ClangASTSource.cpp
+++ b/source/Expression/ClangASTSource.cpp
@@ -622,9 +622,11 @@
name.GetCString(),
(name_string ? name_string : "<anonymous>"));
}
-
+
+ clang::ASTContext *type_ast = type_sp->GetClangAST();
+ lldb::clang_type_t full_type = type_sp->GetClangFullType();
- void *copied_type = GuardedCopyType(m_ast_context, type_sp->GetClangAST(), type_sp->GetClangFullType());
+ void *copied_type = GuardedCopyType(m_ast_context, type_ast, full_type);
if (!copied_type)
{
@@ -641,6 +643,87 @@
} while(0);
}
+static void
+FindObjCMethodDeclsWithOrigin (unsigned int current_id,
+ NameSearchContext &context,
+ ObjCInterfaceDecl *original_interface_decl,
+ clang::ASTContext *ast_context,
+ ClangASTImporter *ast_importer,
+ const char *log_info)
+{
+ const DeclarationName &decl_name(context.m_decl_name);
+ clang::ASTContext *original_ctx = &original_interface_decl->getASTContext();
+
+ Selector original_selector;
+
+ if (decl_name.isObjCZeroArgSelector())
+ {
+ IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString());
+ original_selector = original_ctx->Selectors.getSelector(0, &ident);
+ }
+ else if (decl_name.isObjCOneArgSelector())
+ {
+ const std::string &decl_name_string = decl_name.getAsString();
+ std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1);
+ IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str());
+ original_selector = original_ctx->Selectors.getSelector(1, &ident);
+ }
+ else
+ {
+ SmallVector<IdentifierInfo *, 4> idents;
+
+ clang::Selector sel = decl_name.getObjCSelector();
+
+ int num_args = sel.getNumArgs();
+
+ for (unsigned i = 0;
+ i != num_args;
+ ++i)
+ {
+ idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i)));
+ }
+
+ original_selector = original_ctx->Selectors.getSelector(num_args, idents.data());
+ }
+
+ DeclarationName original_decl_name(original_selector);
+
+ ObjCInterfaceDecl::lookup_result result = original_interface_decl->lookup(original_decl_name);
+
+ if (result.first == result.second)
+ return;
+
+ if (!*result.first)
+ return;
+
+ ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(*result.first);
+
+ if (!result_method)
+ return;
+
+ Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method);
+
+ if (!copied_decl)
+ return;
+
+ ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
+
+ if (!copied_method_decl)
+ return;
+
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ ASTDumper dumper((Decl*)copied_method_decl);
+ log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString());
+ }
+
+ context.AddNamedDecl(copied_method_decl);
+
+ return;
+}
+
void
ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
{
@@ -669,72 +752,12 @@
ObjCInterfaceDecl *original_interface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl);
- Selector original_selector;
-
- if (decl_name.isObjCZeroArgSelector())
- {
- IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString());
- original_selector = original_ctx->Selectors.getSelector(0, &ident);
- }
- else if (decl_name.isObjCOneArgSelector())
- {
- const std::string &decl_name_string = decl_name.getAsString();
- std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1);
- IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str());
- original_selector = original_ctx->Selectors.getSelector(1, &ident);
- }
- else
- {
- SmallVector<IdentifierInfo *, 4> idents;
-
- clang::Selector sel = decl_name.getObjCSelector();
-
- int num_args = sel.getNumArgs();
-
- for (unsigned i = 0;
- i != num_args;
- ++i)
- {
- idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i)));
- }
-
- original_selector = original_ctx->Selectors.getSelector(num_args, idents.data());
- }
-
- DeclarationName original_decl_name(original_selector);
-
- ObjCInterfaceDecl::lookup_result result = original_interface_decl->lookup(original_decl_name);
-
- if (result.first == result.second)
- break;
-
- if (!*result.first)
- break;
-
- ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(*result.first);
-
- if (!result_method)
- break;
-
- Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &result_method->getASTContext(), result_method);
-
- if (!copied_decl)
- continue;
-
- ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
-
- if (!copied_method_decl)
- continue;
-
- if (log)
- {
- ASTDumper dumper((Decl*)copied_method_decl);
- log->Printf(" CAS::FOMD[%d] found (in debug info) %s", current_id, dumper.GetCString());
- }
-
- context.AddNamedDecl(copied_method_decl);
-
- return;
+ FindObjCMethodDeclsWithOrigin(current_id,
+ context,
+ original_interface_decl,
+ m_ast_context,
+ m_ast_importer,
+ "in debug info");
} while (0);
StreamString ss;
@@ -845,54 +868,106 @@
}
while (0);
- for (uint32_t i = 0, e = sc_list.GetSize();
- i != e;
- ++i)
+ if (sc_list.GetSize())
{
- SymbolContext sc;
+ // We found a good function symbol. Use that.
- if (!sc_list.GetContextAtIndex(i, sc))
- continue;
-
- if (!sc.function)
- continue;
-
- DeclContext *function_ctx = sc.function->GetClangDeclContext();
-
- if (!function_ctx)
- continue;
-
- ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(function_ctx);
-
- if (!method_decl)
- continue;
-
- ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface();
-
- if (!found_interface_decl)
- continue;
-
- if (found_interface_decl->getName() == interface_decl->getName())
+ for (uint32_t i = 0, e = sc_list.GetSize();
+ i != e;
+ ++i)
{
- Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);
+ SymbolContext sc;
- if (!copied_decl)
+ if (!sc_list.GetContextAtIndex(i, sc))
continue;
- ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
-
- if (!copied_method_decl)
+ if (!sc.function)
continue;
- if (log)
+ DeclContext *function_ctx = sc.function->GetClangDeclContext();
+
+ if (!function_ctx)
+ continue;
+
+ ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(function_ctx);
+
+ if (!method_decl)
+ continue;
+
+ ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface();
+
+ if (!found_interface_decl)
+ continue;
+
+ if (found_interface_decl->getName() == interface_decl->getName())
{
- ASTDumper dumper((Decl*)copied_method_decl);
- log->Printf(" CAS::FOMD[%d] found (in debug info) %s", current_id, dumper.GetCString());
+ Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);
+
+ if (!copied_decl)
+ continue;
+
+ ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
+
+ if (!copied_method_decl)
+ continue;
+
+ if (log)
+ {
+ ASTDumper dumper((Decl*)copied_method_decl);
+ log->Printf(" CAS::FOMD[%d] found (in debug info) %s", current_id, dumper.GetCString());
+ }
+
+ context.AddNamedDecl(copied_method_decl);
}
-
- context.AddNamedDecl(copied_method_decl);
}
}
+ else
+ {
+ do
+ {
+ // We need to look at the runtime.
+
+ lldb::ProcessSP process(m_target->GetProcessSP());
+
+ if (!process)
+ break;
+
+ ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
+
+ TypeVendor *type_vendor = language_runtime->GetTypeVendor();
+
+ if (!type_vendor)
+ break;
+
+ ConstString interface_name(interface_decl->getNameAsString().c_str());
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <ClangASTType> types;
+
+ if (!type_vendor->FindTypes(interface_name,
+ append,
+ max_matches,
+ types))
+ break;
+
+ const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr();
+
+ const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type);
+
+ if (!runtime_interface_type)
+ break;
+
+ ObjCInterfaceDecl *runtime_interface_decl = runtime_interface_type->getDecl();
+
+ FindObjCMethodDeclsWithOrigin(current_id,
+ context,
+ runtime_interface_decl,
+ m_ast_context,
+ m_ast_importer,
+ "in runtime");
+ }
+ while(0);
+ }
}
template <class D> class TaggedASTDecl {
@@ -1055,41 +1130,89 @@
if (!language_runtime)
return;
- lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name));
+ do
+ {
+ // First see if any other debug information has this property/ivar.
+
+ lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name));
+
+ if (!complete_type_sp)
+ break;
+
+ TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType(), complete_type_sp->GetClangAST());
+ lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType();
+
+ if (!complete_opaque_type)
+ break;
+
+ const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr();
+ const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type);
+
+ if (!complete_interface_type)
+ break;
+
+ DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_type->getDecl());
+
+ if (complete_iface_decl.decl == origin_iface_decl.decl)
+ break; // already checked this one
+
+ if (log)
+ log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
+ current_id,
+ complete_iface_decl.decl,
+ &complete_iface_decl->getASTContext());
+
+ if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
+ context,
+ *m_ast_context,
+ m_ast_importer,
+ complete_iface_decl))
+ return;
+ }
+ while(0);
- if (!complete_type_sp)
- return;
-
- TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType(), complete_type_sp->GetClangAST());
- lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType();
-
- if (!complete_opaque_type)
- return;
-
- const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr();
- const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type);
-
- if (!complete_interface_type)
- return;
-
- DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_type->getDecl());
-
- if (complete_iface_decl.decl == origin_iface_decl.decl)
- return; // already checked this one
-
- if (log)
- log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
- current_id,
- complete_iface_decl.decl,
- &complete_iface_decl->getASTContext());
-
-
- if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
- context,
- *m_ast_context,
- m_ast_importer,
- complete_iface_decl))
- return;
+ do
+ {
+ // Now check the runtime.
+
+ TypeVendor *type_vendor = language_runtime->GetTypeVendor();
+
+ if (!type_vendor)
+ break;
+
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <ClangASTType> types;
+
+ if (!type_vendor->FindTypes(class_name,
+ append,
+ max_matches,
+ types))
+ break;
+
+ const clang::Type *runtime_clang_type = QualType::getFromOpaquePtr(types[0].GetOpaqueQualType()).getTypePtr();
+
+ const ObjCInterfaceType *runtime_interface_type = dyn_cast<ObjCInterfaceType>(runtime_clang_type);
+
+ if (!runtime_interface_type)
+ break;
+
+ DeclFromUser<const ObjCInterfaceDecl> runtime_iface_decl(runtime_interface_type->getDecl());
+
+ if (log)
+ log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
+ current_id,
+ runtime_iface_decl.decl,
+ &runtime_iface_decl->getASTContext());
+
+ if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
+ context,
+ *m_ast_context,
+ m_ast_importer,
+ runtime_iface_decl))
+ return;
+ }
+ while(0);
}
typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap;
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 7945270..e2deca5 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -32,6 +32,7 @@
#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -39,7 +40,7 @@
#include "lldb/Target/Thread.h"
#include "AppleObjCRuntimeV2.h"
-#include "AppleObjCSymbolVendor.h"
+#include "AppleObjCTypeVendor.h"
#include "AppleObjCTrampolineHandler.h"
#include <vector>
@@ -700,13 +701,13 @@
return descriptor->GetClassName();
}
-SymbolVendor *
-AppleObjCRuntimeV2::GetSymbolVendor()
+TypeVendor *
+AppleObjCRuntimeV2::GetTypeVendor()
{
- if (!m_symbol_vendor_ap.get())
- m_symbol_vendor_ap.reset(new AppleObjCSymbolVendor(m_process));
+ if (!m_type_vendor_ap.get())
+ m_type_vendor_ap.reset(new AppleObjCTypeVendor(*this));
- return m_symbol_vendor_ap.get();
+ return m_type_vendor_ap.get();
}
AppleObjCRuntimeV2::ClassDescriptorV2::ClassDescriptorV2 (ValueObject &isa_pointer)
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index ff94b81..90179ca 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -244,7 +244,7 @@
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA = 1;
virtual ObjCLanguageRuntime::ObjCISA
- GetISA(ValueObject& valobj);
+ GetISA(ValueObject& valobj);
virtual ConstString
GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa);
@@ -255,8 +255,8 @@
virtual ClassDescriptorSP
GetClassDescriptor (ObjCISA isa);
- virtual SymbolVendor *
- GetSymbolVendor();
+ virtual TypeVendor *
+ GetTypeVendor();
protected:
virtual lldb::BreakpointResolverSP
@@ -278,7 +278,7 @@
lldb::addr_t m_get_class_name_args;
Mutex m_get_class_name_args_mutex;
- std::auto_ptr<SymbolVendor> m_symbol_vendor_ap;
+ std::auto_ptr<TypeVendor> m_type_vendor_ap;
static const char *g_find_class_name_function_name;
static const char *g_find_class_name_function_body;
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp
deleted file mode 100644
index fba909b..0000000
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//===-- AppleObjCSymbolVendor.cpp -------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AppleObjCSymbolVendor.h"
-
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-
-#include "clang/AST/ASTContext.h"
-
-using namespace lldb_private;
-
-AppleObjCSymbolVendor::AppleObjCSymbolVendor(Process *process) :
- SymbolVendor(lldb::ModuleSP()),
- m_process(process->shared_from_this()),
- m_ast_ctx(process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str())
-{
-}
-
-uint32_t
-AppleObjCSymbolVendor::FindTypes (const SymbolContext& sc,
- const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
- bool append,
- uint32_t max_matches,
- TypeList& types)
-{
- lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); // FIXME - a more appropriate log channel?
-
- if (log)
- log->Printf("ObjC SymbolVendor asked for '%s'",
- name.AsCString());
-
- if (!append)
- types.Clear();
-
- uint32_t ret = 0;
-
- ModuleList &target_modules = m_process->GetTarget().GetImages();
- Mutex::Locker modules_locker(target_modules.GetMutex());
-
- for (size_t image_index = 0, end_index = target_modules.GetSize();
- image_index < end_index;
- ++image_index)
- {
- Module *image = target_modules.GetModulePointerAtIndexUnlocked(image_index);
-
- if (!image)
- continue;
-
- SymbolVendor *symbol_vendor = image->GetSymbolVendor();
-
- if (!symbol_vendor)
- continue;
-
- SymbolFile *symbol_file = image->GetSymbolVendor()->GetSymbolFile();
-
- // Don't use a symbol file if it actually has types. We are specifically
- // looking for something in runtime information, not from debug information,
- // as the data in debug information will get parsed by the debug info
- // symbol files. So we veto any symbol file that has actual variable
- // type parsing abilities.
- if (symbol_file == NULL || (symbol_file->GetAbilities() & SymbolFile::VariableTypes))
- continue;
-
- const bool inferior_append = true;
-
- ret += symbol_file->FindTypes (sc, name, namespace_decl, inferior_append, max_matches - ret, types);
-
- if (ret >= max_matches)
- break;
- }
-
- return ret;
-}
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h
deleted file mode 100644
index b426de5..0000000
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===-- AppleObjCSymbolVendor.h ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_AppleObjCSymbolVendor_h_
-#define liblldb_AppleObjCSymbolVendor_h_
-
-// C Includes
-// C++ Includes
-
-#include <map>
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/lldb-private.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/SymbolFile.h"
-
-namespace lldb_private {
-
-class AppleObjCSymbolVendor : public SymbolVendor
-{
-public:
- AppleObjCSymbolVendor(Process* process);
-
- virtual uint32_t
- FindTypes (const SymbolContext& sc,
- const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
- bool append,
- uint32_t max_matches,
- TypeList& types);
-
-private:
- lldb::ProcessSP m_process;
- ClangASTContext m_ast_ctx;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_AppleObjCSymbolVendor_h_
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp
new file mode 100644
index 0000000..e14e2e6
--- /dev/null
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp
@@ -0,0 +1,198 @@
+//===-- AppleObjCSymbolVendor.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCTypeVendor.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Expression/ASTDumper.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+
+using namespace lldb_private;
+
+class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCommon
+{
+public:
+ AppleObjCExternalASTSource (AppleObjCTypeVendor &type_vendor) :
+ m_type_vendor(type_vendor)
+ {
+ }
+
+ clang::DeclContextLookupResult
+ FindExternalVisibleDeclsByName (const clang::DeclContext *DC,
+ clang::DeclarationName Name)
+ {
+ return clang::DeclContextLookupResult();
+ }
+
+ clang::ExternalLoadResult
+ FindExternalLexicalDecls (const clang::DeclContext *DC,
+ bool (*isKindWeWant)(clang::Decl::Kind),
+ llvm::SmallVectorImpl<clang::Decl*> &Decls)
+ {
+ return clang::ELR_Success;
+ }
+
+ void
+ CompleteType (clang::TagDecl *Tag)
+ {
+ return;
+ }
+
+ void
+ CompleteType (clang::ObjCInterfaceDecl *Class)
+ {
+ return;
+ }
+
+ bool
+ layoutRecordType(const clang::RecordDecl *Record,
+ uint64_t &Size,
+ uint64_t &Alignment,
+ llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
+ llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets)
+ {
+ return false;
+ }
+
+ void StartTranslationUnit (clang::ASTConsumer *Consumer)
+ {
+ clang::TranslationUnitDecl *translation_unit_decl = m_type_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
+ translation_unit_decl->setHasExternalVisibleStorage();
+ translation_unit_decl->setHasExternalLexicalStorage();
+ }
+private:
+ AppleObjCTypeVendor &m_type_vendor;
+};
+
+AppleObjCTypeVendor::AppleObjCTypeVendor(ObjCLanguageRuntime &runtime) :
+ TypeVendor(),
+ m_runtime(runtime),
+ m_ast_ctx(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().getTriple().c_str())
+{
+ m_external_source = new AppleObjCExternalASTSource (*this);
+ llvm::OwningPtr<clang::ExternalASTSource> external_source_owning_ptr (m_external_source);
+ m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr);
+}
+
+uint32_t
+AppleObjCTypeVendor::FindTypes (const ConstString &name,
+ bool append,
+ uint32_t max_matches,
+ std::vector <ClangASTType> &types)
+{
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ if (log)
+ log->Printf("AppleObjCTypeVendor::FindTypes [%u] ('%s', %s, %u, )",
+ current_id,
+ (const char*)name.AsCString(),
+ append ? "true" : "false",
+ max_matches);
+
+ if (!append)
+ types.clear();
+
+ uint32_t ret = 0;
+
+ do
+ {
+ // See if the type is already in our ASTContext.
+
+ clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+
+ clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef());
+ clang::DeclarationName decl_name = ast_ctx->DeclarationNames.getIdentifier(&identifier_info);
+
+ clang::DeclContext::lookup_const_result lookup_result = ast_ctx->getTranslationUnitDecl()->lookup(decl_name);
+
+ if (lookup_result.first != lookup_result.second)
+ {
+ if (const clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.first))
+ {
+ clang::QualType result_iface_type = ast_ctx->getObjCInterfaceType(result_iface_decl);
+
+ if (log)
+ {
+ ASTDumper dumper(result_iface_type);
+ log->Printf("AOCTV::FT [%u] Found %s (isa 0x%llx) in the ASTContext",
+ current_id,
+ dumper.GetCString(),
+ m_external_source->GetMetadata((uintptr_t)result_iface_decl));
+ }
+
+ types.push_back(ClangASTType(ast_ctx, result_iface_type.getAsOpaquePtr()));
+ ret++;
+ break;
+ }
+ else
+ {
+ if (log)
+ log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but it's not something we know about",
+ current_id);
+ break;
+ }
+ }
+ else if(log)
+ {
+ log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext",
+ current_id,
+ name.AsCString());
+ }
+
+ // It's not. If it exists, we have to put it into our ASTContext.
+
+ // TODO Actually do this. But we have to search the class list first. Until then we'll just give up.
+ break;
+
+ ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name);
+
+ if (!isa)
+ {
+ if (log)
+ log->Printf("AOCTV::FT [%u] Couldn't find the isa",
+ current_id);
+
+ break;
+ }
+
+ clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(*ast_ctx,
+ ast_ctx->getTranslationUnitDecl(),
+ clang::SourceLocation(),
+ &identifier_info,
+ NULL);
+
+ m_external_source->SetMetadata((uintptr_t)new_iface_decl, (uint64_t)isa);
+
+ new_iface_decl->setHasExternalVisibleStorage();
+
+ clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(new_iface_decl);
+
+ if (log)
+ {
+ ASTDumper dumper(new_iface_type);
+ log->Printf("AOCTV::FT [%u] Created %s (isa 0x%llx)",
+ current_id,
+ dumper.GetCString(),
+ (uint64_t)isa);
+ }
+ } while (0);
+
+ return ret;
+}
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h
new file mode 100644
index 0000000..e060116
--- /dev/null
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h
@@ -0,0 +1,49 @@
+//===-- AppleObjCSymbolVendor.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AppleObjCSymbolVendor_h_
+#define liblldb_AppleObjCSymbolVendor_h_
+
+// C Includes
+// C++ Includes
+
+#include <map>
+
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/TypeVendor.h"
+
+namespace lldb_private {
+
+class AppleObjCExternalASTSource;
+
+class AppleObjCTypeVendor : public TypeVendor
+{
+public:
+ AppleObjCTypeVendor(ObjCLanguageRuntime &runtime);
+
+ virtual uint32_t
+ FindTypes (const ConstString &name,
+ bool append,
+ uint32_t max_matches,
+ std::vector <ClangASTType> &types);
+
+ friend class AppleObjCExternalASTSource;
+private:
+ ObjCLanguageRuntime &m_runtime;
+ ClangASTContext m_ast_ctx;
+ AppleObjCExternalASTSource *m_external_source;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_AppleObjCSymbolVendor_h_
diff --git a/source/Target/ObjCLanguageRuntime.cpp b/source/Target/ObjCLanguageRuntime.cpp
index a404ce4..df00c35 100644
--- a/source/Target/ObjCLanguageRuntime.cpp
+++ b/source/Target/ObjCLanguageRuntime.cpp
@@ -281,6 +281,16 @@
}
ObjCLanguageRuntime::ObjCISA
+ObjCLanguageRuntime::GetISA(const ConstString &name)
+{
+ for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
+ if (val.second && val.second->GetClassName() == name)
+ return val.first;
+
+ return 0;
+}
+
+ObjCLanguageRuntime::ObjCISA
ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
{
if (!IsValidISA(isa))