[Lldb-commits] [lldb] r216026 - This is a fairly bulky patch, but a lot of it involves rearranging existing code

Enrico Granata egranata at apple.com
Tue Aug 19 14:46:38 PDT 2014


Author: enrico
Date: Tue Aug 19 16:46:37 2014
New Revision: 216026

URL: http://llvm.org/viewvc/llvm-project?rev=216026&view=rev
Log:
This is a fairly bulky patch, but a lot of it involves rearranging existing code
What it does:

- it introduces a concept of EncodingToType to the ObjCLanguageRuntime
  The ObjC runtime has a "type encoding" feature that describes types as strings
  The EncodingToType is a decoder for that format, making types out of type encoding strings
This feature already existed in some shape as we were using it to create method signatures out of the runtime, but this checkin extends the parser to support the full syntax, and moves things so that more parts of LLDB have access to this decoder

- it splits the ClassDescriptorV2 object to its own file, it was starting to grow too large

- it adds to the ClassDescriptor mechanism a notion of ivar storage; the ObjC runtime vends ivar information as well as method information
While ivar information is not ready for prime type (i.e. we don't want to add it to the runtime generated types for expression evaluator usage), there are potentially useful scenarios in which realizing ivar types could be useful. For now, the ClassDescriptor is going to hold ivar information directly. Existing code already allows describing ivars, this patch hooks those moving parts up so that one can actually ask a ClassDescriptor about ivars for the class it represents

and as a couple minor niceties:
- it makes it possible to retrieve the LLDB ClangASTContext that is associated to a clang::ASTContext
- it extends the ValueObject-to-ClassDescriptor API in the language runtime to deal correctly with base-class hierarchies


Added:
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
Modified:
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h
    lldb/trunk/source/Symbol/ClangASTContext.cpp
    lldb/trunk/source/Target/ObjCLanguageRuntime.cpp

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Tue Aug 19 16:46:37 2014
@@ -43,6 +43,9 @@ public:
     ClangASTContext (const char *triple = NULL);
 
     ~ClangASTContext();
+    
+    static ClangASTContext*
+    GetASTContext (clang::ASTContext* ast_ctx);
 
     clang::ASTContext *
     getASTContext();

Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Tue Aug 19 16:46:37 2014
@@ -20,6 +20,7 @@
 // Project includes
 #include "lldb/lldb-private.h"
 #include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/ClangASTType.h"
 #include "lldb/Symbol/Type.h"
 #include "lldb/Symbol/TypeVendor.h"
 #include "lldb/Target/LanguageRuntime.h"
@@ -238,6 +239,25 @@ public:
             m_type_wp = type_sp;
         }
         
+        struct iVarDescriptor {
+            ConstString m_name;
+            ClangASTType m_type;
+            uint64_t m_size;
+            int32_t m_offset;
+        };
+        
+        virtual size_t
+        GetNumIVars ()
+        {
+            return 0;
+        }
+        
+        virtual iVarDescriptor
+        GetIVarAtIndex (size_t idx)
+        {
+            return iVarDescriptor();
+        }
+        
     protected:
         bool
         IsPointerValid (lldb::addr_t value,
@@ -252,6 +272,25 @@ public:
         lldb::TypeWP m_type_wp;
     };
     
+    class EncodingToType
+    {
+    public:
+        virtual ClangASTType RealizeType (ClangASTContext& ast_ctx, const char* name, bool allow_unknownanytype);
+        virtual ClangASTType RealizeType (const char* name, bool allow_unknownanytype);
+        
+        virtual ClangASTType RealizeType (clang::ASTContext& ast_ctx, const char* name, bool allow_unknownanytype) = 0;
+        
+        virtual ~EncodingToType();
+        
+    protected:
+        std::unique_ptr<ClangASTContext> m_scratch_ast_ctx_ap;
+    };
+    
+    typedef std::shared_ptr<EncodingToType> EncodingToTypeSP;
+    
+    virtual EncodingToTypeSP
+    GetEncodingToType ();
+    
     virtual ClassDescriptorSP
     GetClassDescriptor (ValueObject& in_value);
     

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Aug 19 16:46:37 2014
@@ -664,6 +664,8 @@
 		94CD704E16F8DDEA00CF1E42 /* Cocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD704C16F8DDEA00CF1E42 /* Cocoa.cpp */; };
 		94CD705016F8DF1C00CF1E42 /* LibCxxList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD704F16F8DF1C00CF1E42 /* LibCxxList.cpp */; };
 		94CD705216F8F5BC00CF1E42 /* LibCxxMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD705116F8F5BC00CF1E42 /* LibCxxMap.cpp */; };
+		94CD7D0919A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD7D0819A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp */; };
+		94CD7D0C19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD7D0B19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp */; };
 		94D0B10C16D5535900EA9C70 /* LibCxx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D0B10A16D5535900EA9C70 /* LibCxx.cpp */; };
 		94D0B10D16D5535900EA9C70 /* LibStdcpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */; };
 		94D6A0AA16CEB55F00833B6E /* NSArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A716CEB55F00833B6E /* NSArray.cpp */; };
@@ -1970,6 +1972,10 @@
 		94CD704C16F8DDEA00CF1E42 /* Cocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Cocoa.cpp; path = source/DataFormatters/Cocoa.cpp; sourceTree = "<group>"; };
 		94CD704F16F8DF1C00CF1E42 /* LibCxxList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxList.cpp; path = source/DataFormatters/LibCxxList.cpp; sourceTree = "<group>"; };
 		94CD705116F8F5BC00CF1E42 /* LibCxxMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxMap.cpp; path = source/DataFormatters/LibCxxMap.cpp; sourceTree = "<group>"; };
+		94CD7D0719A3FB8600908B7C /* AppleObjCClassDescriptorV2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCClassDescriptorV2.h; sourceTree = "<group>"; };
+		94CD7D0819A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCClassDescriptorV2.cpp; sourceTree = "<group>"; };
+		94CD7D0A19A3FBC300908B7C /* AppleObjCTypeEncodingParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCTypeEncodingParser.h; sourceTree = "<group>"; };
+		94CD7D0B19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCTypeEncodingParser.cpp; sourceTree = "<group>"; };
 		94D0B10A16D5535900EA9C70 /* LibCxx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxx.cpp; path = source/DataFormatters/LibCxx.cpp; sourceTree = "<group>"; };
 		94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibStdcpp.cpp; path = source/DataFormatters/LibStdcpp.cpp; sourceTree = "<group>"; };
 		94D6A0A716CEB55F00833B6E /* NSArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSArray.cpp; path = source/DataFormatters/NSArray.cpp; sourceTree = "<group>"; };
@@ -4045,6 +4051,8 @@
 		4CCA644113B40B82003BDF98 /* AppleObjCRuntime */ = {
 			isa = PBXGroup;
 			children = (
+				94CD7D0719A3FB8600908B7C /* AppleObjCClassDescriptorV2.h */,
+				94CD7D0819A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp */,
 				4CCA644213B40B82003BDF98 /* AppleObjCRuntime.cpp */,
 				4CCA644313B40B82003BDF98 /* AppleObjCRuntime.h */,
 				4CCA644413B40B82003BDF98 /* AppleObjCRuntimeV1.cpp */,
@@ -4053,6 +4061,8 @@
 				4CCA644713B40B82003BDF98 /* AppleObjCRuntimeV2.h */,
 				4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */,
 				4CCA644913B40B82003BDF98 /* AppleObjCTrampolineHandler.h */,
+				94CD7D0A19A3FBC300908B7C /* AppleObjCTypeEncodingParser.h */,
+				94CD7D0B19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp */,
 				49DA65041485C942005FF180 /* AppleObjCTypeVendor.h */,
 				49DA65021485C92A005FF180 /* AppleObjCTypeVendor.cpp */,
 				4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */,
@@ -5143,11 +5153,13 @@
 				26957D9813D381C900670048 /* RegisterContextDarwin_arm.cpp in Sources */,
 				26957D9A13D381C900670048 /* RegisterContextDarwin_i386.cpp in Sources */,
 				26957D9C13D381C900670048 /* RegisterContextDarwin_x86_64.cpp in Sources */,
+				94CD7D0919A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp in Sources */,
 				265205A813D3E3F700132FE2 /* RegisterContextKDP_arm.cpp in Sources */,
 				265205AA13D3E3F700132FE2 /* RegisterContextKDP_i386.cpp in Sources */,
 				265205AC13D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp in Sources */,
 				2628A4D513D4977900F5487A /* ThreadKDP.cpp in Sources */,
 				26D7E45D13D5E30A007FD12B /* SocketAddress.cpp in Sources */,
+				94CD7D0C19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp in Sources */,
 				94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */,
 				262D24E613FB8710002D1960 /* RegisterContextMemory.cpp in Sources */,
 				26F4A21C13FBA31A0064B613 /* ThreadMemory.cpp in Sources */,

Added: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp?rev=216026&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp (added)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp Tue Aug 19 16:46:37 2014
@@ -0,0 +1,526 @@
+//===-- AppleObjCClassDescriptorV2.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCClassDescriptorV2.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool
+ClassDescriptorV2::Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class) const
+{
+    objc_class.reset(new objc_class_t);
+    
+    bool ret = objc_class->Read (process, m_objc_class_ptr);
+    
+    if (!ret)
+        objc_class.reset();
+    
+    return ret;
+}
+
+bool
+ClassDescriptorV2::objc_class_t::Read(Process *process, lldb::addr_t addr)
+{
+    size_t ptr_size = process->GetAddressByteSize();
+    
+    size_t objc_class_size = ptr_size   // uintptr_t isa;
+    + ptr_size   // Class superclass;
+    + ptr_size   // void *cache;
+    + ptr_size   // IMP *vtable;
+    + ptr_size;  // uintptr_t data_NEVER_USE;
+    
+    DataBufferHeap objc_class_buf (objc_class_size, '\0');
+    Error error;
+    
+    process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
+    if (error.Fail())
+    {
+        return false;
+    }
+    
+    DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size, process->GetByteOrder(), process->GetAddressByteSize());
+    
+    lldb::offset_t cursor = 0;
+    
+    m_isa           = extractor.GetAddress_unchecked(&cursor);   // uintptr_t isa;
+    m_superclass    = extractor.GetAddress_unchecked(&cursor);   // Class superclass;
+    m_cache_ptr     = extractor.GetAddress_unchecked(&cursor);   // void *cache;
+    m_vtable_ptr    = extractor.GetAddress_unchecked(&cursor);   // IMP *vtable;
+    lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor);   // uintptr_t data_NEVER_USE;
+    
+    m_flags         = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
+    m_data_ptr      = data_NEVER_USE & ~(lldb::addr_t)3;
+    
+    return true;
+}
+
+bool
+ClassDescriptorV2::class_rw_t::Read(Process *process, lldb::addr_t addr)
+{
+    size_t ptr_size = process->GetAddressByteSize();
+    
+    size_t size = sizeof(uint32_t)  // uint32_t flags;
+    + sizeof(uint32_t)  // uint32_t version;
+    + ptr_size          // const class_ro_t *ro;
+    + ptr_size          // union { method_list_t **method_lists; method_list_t *method_list; };
+    + ptr_size          // struct chained_property_list *properties;
+    + ptr_size          // const protocol_list_t **protocols;
+    + ptr_size          // Class firstSubclass;
+    + ptr_size;         // Class nextSiblingClass;
+    
+    DataBufferHeap buffer (size, '\0');
+    Error error;
+    
+    process->ReadMemory(addr, buffer.GetBytes(), size, error);
+    if (error.Fail())
+    {
+        return false;
+    }
+    
+    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+    
+    lldb::offset_t cursor = 0;
+    
+    m_flags             = extractor.GetU32_unchecked(&cursor);
+    m_version           = extractor.GetU32_unchecked(&cursor);
+    m_ro_ptr            = extractor.GetAddress_unchecked(&cursor);
+    m_method_list_ptr   = extractor.GetAddress_unchecked(&cursor);
+    m_properties_ptr    = extractor.GetAddress_unchecked(&cursor);
+    m_firstSubclass     = extractor.GetAddress_unchecked(&cursor);
+    m_nextSiblingClass  = extractor.GetAddress_unchecked(&cursor);
+    
+    return true;
+}
+
+bool
+ClassDescriptorV2::class_ro_t::Read(Process *process, lldb::addr_t addr)
+{
+    size_t ptr_size = process->GetAddressByteSize();
+    
+    size_t size = sizeof(uint32_t)             // uint32_t flags;
+    + sizeof(uint32_t)                         // uint32_t instanceStart;
+    + sizeof(uint32_t)                         // uint32_t instanceSize;
+    + (ptr_size == 8 ? sizeof(uint32_t) : 0)   // uint32_t reserved; // __LP64__ only
+    + ptr_size                                 // const uint8_t *ivarLayout;
+    + ptr_size                                 // const char *name;
+    + ptr_size                                 // const method_list_t *baseMethods;
+    + ptr_size                                 // const protocol_list_t *baseProtocols;
+    + ptr_size                                 // const ivar_list_t *ivars;
+    + ptr_size                                 // const uint8_t *weakIvarLayout;
+    + ptr_size;                                // const property_list_t *baseProperties;
+    
+    DataBufferHeap buffer (size, '\0');
+    Error error;
+    
+    process->ReadMemory(addr, buffer.GetBytes(), size, error);
+    if (error.Fail())
+    {
+        return false;
+    }
+    
+    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+    
+    lldb::offset_t cursor = 0;
+    
+    m_flags             = extractor.GetU32_unchecked(&cursor);
+    m_instanceStart     = extractor.GetU32_unchecked(&cursor);
+    m_instanceSize      = extractor.GetU32_unchecked(&cursor);
+    if (ptr_size == 8)
+        m_reserved      = extractor.GetU32_unchecked(&cursor);
+    else
+        m_reserved      = 0;
+    m_ivarLayout_ptr     = extractor.GetAddress_unchecked(&cursor);
+    m_name_ptr           = extractor.GetAddress_unchecked(&cursor);
+    m_baseMethods_ptr    = extractor.GetAddress_unchecked(&cursor);
+    m_baseProtocols_ptr  = extractor.GetAddress_unchecked(&cursor);
+    m_ivars_ptr          = extractor.GetAddress_unchecked(&cursor);
+    m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
+    m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
+    
+    DataBufferHeap name_buf(1024, '\0');
+    
+    process->ReadCStringFromMemory(m_name_ptr, (char*)name_buf.GetBytes(), name_buf.GetByteSize(), error);
+    
+    if (error.Fail())
+    {
+        return false;
+    }
+    
+    m_name.assign((char*)name_buf.GetBytes());
+    
+    return true;
+}
+
+bool
+ClassDescriptorV2::Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw) const
+{
+    class_ro.reset();
+    class_rw.reset();
+    
+    Error error;
+    uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
+    if (!error.Success())
+        return false;
+    
+    if (class_row_t_flags & RW_REALIZED)
+    {
+        class_rw.reset(new class_rw_t);
+        
+        if (!class_rw->Read(process, objc_class.m_data_ptr))
+        {
+            class_rw.reset();
+            return false;
+        }
+        
+        class_ro.reset(new class_ro_t);
+        
+        if (!class_ro->Read(process, class_rw->m_ro_ptr))
+        {
+            class_rw.reset();
+            class_ro.reset();
+            return false;
+        }
+    }
+    else
+    {
+        class_ro.reset(new class_ro_t);
+        
+        if (!class_ro->Read(process, objc_class.m_data_ptr))
+        {
+            class_ro.reset();
+            return false;
+        }
+    }
+    
+    return true;
+}
+
+bool
+ClassDescriptorV2::method_list_t::Read(Process *process, lldb::addr_t addr)
+{
+    size_t size = sizeof(uint32_t)  // uint32_t entsize_NEVER_USE;
+    + sizeof(uint32_t); // uint32_t count;
+    
+    DataBufferHeap buffer (size, '\0');
+    Error error;
+    
+    process->ReadMemory(addr, buffer.GetBytes(), size, error);
+    if (error.Fail())
+    {
+        return false;
+    }
+    
+    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+    
+    lldb::offset_t cursor = 0;
+    
+    m_entsize   = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
+    m_count     = extractor.GetU32_unchecked(&cursor);
+    m_first_ptr  = addr + cursor;
+    
+    return true;
+}
+
+bool
+ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr)
+{
+    size_t size = GetSize(process);
+    
+    DataBufferHeap buffer (size, '\0');
+    Error error;
+    
+    process->ReadMemory(addr, buffer.GetBytes(), size, error);
+    if (error.Fail())
+    {
+        return false;
+    }
+    
+    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+    
+    lldb::offset_t cursor = 0;
+    
+    m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
+    m_types_ptr  = extractor.GetAddress_unchecked(&cursor);
+    m_imp_ptr    = extractor.GetAddress_unchecked(&cursor);
+    
+    const size_t buffer_size = 1024;
+    size_t count;
+    
+    DataBufferHeap string_buf(buffer_size, 0);
+    
+    count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
+    m_name.assign((char*)string_buf.GetBytes(), count);
+    
+    count = process->ReadCStringFromMemory(m_types_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
+    m_types.assign((char*)string_buf.GetBytes(), count);
+    
+    return true;
+}
+
+bool
+ClassDescriptorV2::ivar_list_t::Read(Process *process, lldb::addr_t addr)
+{
+    size_t size = sizeof(uint32_t)  // uint32_t entsize;
+    + sizeof(uint32_t); // uint32_t count;
+    
+    DataBufferHeap buffer (size, '\0');
+    Error error;
+    
+    process->ReadMemory(addr, buffer.GetBytes(), size, error);
+    if (error.Fail())
+    {
+        return false;
+    }
+    
+    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+    
+    lldb::offset_t cursor = 0;
+    
+    m_entsize   = extractor.GetU32_unchecked(&cursor);
+    m_count     = extractor.GetU32_unchecked(&cursor);
+    m_first_ptr = addr + cursor;
+    
+    return true;
+}
+
+bool
+ClassDescriptorV2::ivar_t::Read(Process *process, lldb::addr_t addr)
+{
+    size_t size = GetSize(process);
+    
+    DataBufferHeap buffer (size, '\0');
+    Error error;
+    
+    process->ReadMemory(addr, buffer.GetBytes(), size, error);
+    if (error.Fail())
+    {
+        return false;
+    }
+    
+    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+    
+    lldb::offset_t cursor = 0;
+    
+    m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
+    m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
+    m_type_ptr   = extractor.GetAddress_unchecked(&cursor);
+    m_alignment  = extractor.GetU32_unchecked(&cursor);
+    m_size       = extractor.GetU32_unchecked(&cursor);
+    
+    const size_t buffer_size = 1024;
+    size_t count;
+    
+    DataBufferHeap string_buf(buffer_size, 0);
+    
+    count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
+    m_name.assign((char*)string_buf.GetBytes(), count);
+    
+    count = process->ReadCStringFromMemory(m_type_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
+    m_type.assign((char*)string_buf.GetBytes(), count);
+    
+    return true;
+}
+
+bool
+ClassDescriptorV2::Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+                             std::function <bool (const char *, const char *)> const &instance_method_func,
+                             std::function <bool (const char *, const char *)> const &class_method_func,
+                             std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const
+{
+    lldb_private::Process *process = m_runtime.GetProcess();
+    
+    std::unique_ptr<objc_class_t> objc_class;
+    std::unique_ptr<class_ro_t> class_ro;
+    std::unique_ptr<class_rw_t> class_rw;
+    
+    if (!Read_objc_class(process, objc_class))
+        return 0;
+    if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+        return 0;
+    
+    static ConstString NSObject_name("NSObject");
+    
+    if (m_name != NSObject_name && superclass_func)
+        superclass_func(objc_class->m_superclass);
+    
+    if (instance_method_func)
+    {
+        std::unique_ptr<method_list_t> base_method_list;
+        
+        base_method_list.reset(new method_list_t);
+        if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
+            return false;
+        
+        if (base_method_list->m_entsize != method_t::GetSize(process))
+            return false;
+        
+        std::unique_ptr<method_t> method;
+        method.reset(new method_t);
+        
+        for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i)
+        {
+            method->Read(process, base_method_list->m_first_ptr + (i * base_method_list->m_entsize));
+            
+            if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
+                break;
+        }
+    }
+    
+    if (class_method_func)
+    {
+        ClassDescriptorV2 metaclass(m_runtime, objc_class->m_isa, NULL); // The metaclass is not in the cache
+        
+        // We don't care about the metaclass's superclass, or its class methods.  Its instance methods are
+        // our class methods.
+        
+        metaclass.Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> (nullptr),
+                           class_method_func,
+                           std::function <bool (const char *, const char *)> (nullptr),
+                           std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> (nullptr));
+    }
+    
+    if (ivar_func)
+    {
+        ivar_list_t ivar_list;
+        if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
+            return false;
+        
+        if (ivar_list.m_entsize != ivar_t::GetSize(process))
+            return false;
+        
+        ivar_t ivar;
+        
+        for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i)
+        {
+            ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
+            
+            if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(), ivar.m_offset_ptr, ivar.m_size))
+                break;
+        }
+    }
+    
+    return true;
+}
+
+ConstString
+ClassDescriptorV2::GetClassName ()
+{
+    if (!m_name)
+    {
+        lldb_private::Process *process = m_runtime.GetProcess();
+        
+        if (process)
+        {
+            std::unique_ptr<objc_class_t> objc_class;
+            std::unique_ptr<class_ro_t> class_ro;
+            std::unique_ptr<class_rw_t> class_rw;
+            
+            if (!Read_objc_class(process, objc_class))
+                return m_name;
+            if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+                return m_name;
+            
+            m_name = ConstString(class_ro->m_name.c_str());
+        }
+    }
+    return m_name;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+ClassDescriptorV2::GetSuperclass ()
+{
+    lldb_private::Process *process = m_runtime.GetProcess();
+    
+    if (!process)
+        return ObjCLanguageRuntime::ClassDescriptorSP();
+    
+    std::unique_ptr<objc_class_t> objc_class;
+    
+    if (!Read_objc_class(process, objc_class))
+        return ObjCLanguageRuntime::ClassDescriptorSP();
+    
+    return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(objc_class->m_superclass);
+}
+
+uint64_t
+ClassDescriptorV2::GetInstanceSize ()
+{
+    lldb_private::Process *process = m_runtime.GetProcess();
+    
+    if (process)
+    {
+        std::unique_ptr<objc_class_t> objc_class;
+        std::unique_ptr<class_ro_t> class_ro;
+        std::unique_ptr<class_rw_t> class_rw;
+        
+        if (!Read_objc_class(process, objc_class))
+            return 0;
+        if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+            return 0;
+        
+        return class_ro->m_instanceSize;
+    }
+    
+    return 0;
+}
+
+ClassDescriptorV2::iVarsStorage::iVarsStorage ():
+m_filled(false),
+m_ivars(),
+m_mutex(Mutex::eMutexTypeRecursive)
+{}
+
+size_t
+ClassDescriptorV2::iVarsStorage::size ()
+{
+    return m_ivars.size();
+}
+
+ClassDescriptorV2::iVarDescriptor&
+ClassDescriptorV2::iVarsStorage::operator[] (size_t idx)
+{
+    return m_ivars[idx];
+}
+
+void
+ClassDescriptorV2::iVarsStorage::fill (AppleObjCRuntimeV2& runtime, ClassDescriptorV2& descriptor)
+{
+    if (m_filled)
+        return;
+    Mutex::Locker lock(m_mutex);
+    m_filled = true;
+    ObjCLanguageRuntime::EncodingToTypeSP encoding_to_type_sp(runtime.GetEncodingToType());
+    Process* process(runtime.GetProcess());
+    if (!encoding_to_type_sp)
+        return;
+    descriptor.Describe(nullptr,
+                        nullptr,
+                        nullptr,
+                        [this,process,encoding_to_type_sp](const char * name, const char * type, lldb::addr_t offset_ptr, uint64_t size) -> bool {
+                 const bool allow_unknownanytype = false;
+                 const bool stop_loop = false;
+                 ClangASTType ivar_type = encoding_to_type_sp->RealizeType(type, allow_unknownanytype);
+                 if (ivar_type)
+                 {
+                     Scalar offset_scalar;
+                     Error error;
+                     size_t read = process->ReadScalarIntegerFromMemory(offset_ptr, 4, true, offset_scalar, error);
+                     if (error.Success() && 4 == read)
+                         m_ivars.push_back({ ConstString(name), ivar_type, size, offset_scalar.SInt() });
+                 }
+                 return stop_loop;
+             });
+}
+
+void
+ClassDescriptorV2::GetIVarInformation ()
+{
+    m_ivars_storage.fill(m_runtime, *this);
+}

Added: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h?rev=216026&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h (added)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h Tue Aug 19 16:46:37 2014
@@ -0,0 +1,411 @@
+//===-- AppleObjCClassDescriptorV2.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_AppleObjCClassDescriptorV2_h_
+#define liblldb_AppleObjCClassDescriptorV2_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "AppleObjCRuntimeV2.h"
+
+namespace lldb_private {
+
+class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
+{
+public:
+    friend class lldb_private::AppleObjCRuntimeV2;
+    
+private:
+    // The constructor should only be invoked by the runtime as it builds its caches
+    // or populates them.  A ClassDescriptorV2 should only ever exist in a cache.
+    ClassDescriptorV2 (AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name) :
+    m_runtime (runtime),
+    m_objc_class_ptr (isa),
+    m_name (name),
+    m_ivars_storage()
+    {
+    }
+    
+public:
+    virtual ConstString
+    GetClassName ();
+    
+    virtual ObjCLanguageRuntime::ClassDescriptorSP
+    GetSuperclass ();
+    
+    virtual bool
+    IsValid ()
+    {
+        return true;    // any Objective-C v2 runtime class descriptor we vend is valid
+    }
+    
+    // a custom descriptor is used for tagged pointers
+    virtual bool
+    GetTaggedPointerInfo (uint64_t* info_bits = NULL,
+                          uint64_t* value_bits = NULL,
+                          uint64_t* payload = NULL)
+    {
+        return false;
+    }
+    
+    virtual uint64_t
+    GetInstanceSize ();
+    
+    virtual ObjCLanguageRuntime::ObjCISA
+    GetISA ()
+    {
+        return m_objc_class_ptr;
+    }
+    
+    virtual bool
+    Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+              std::function <bool (const char *, const char *)> const &instance_method_func,
+              std::function <bool (const char *, const char *)> const &class_method_func,
+              std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const;
+    
+    virtual
+    ~ClassDescriptorV2 ()
+    {
+    }
+    
+    virtual size_t
+    GetNumIVars ()
+    {
+        GetIVarInformation();
+        return m_ivars_storage.size();
+    }
+    
+    virtual iVarDescriptor
+    GetIVarAtIndex (size_t idx)
+    {
+        if (idx >= GetNumIVars())
+            return iVarDescriptor();
+        return m_ivars_storage[idx];
+    }
+    
+protected:
+    void
+    GetIVarInformation ();
+    
+private:
+    static const uint32_t RW_REALIZED = (1 << 31);
+    
+    struct objc_class_t {
+        ObjCLanguageRuntime::ObjCISA    m_isa;              // The class's metaclass.
+        ObjCLanguageRuntime::ObjCISA    m_superclass;
+        lldb::addr_t                    m_cache_ptr;
+        lldb::addr_t                    m_vtable_ptr;
+        lldb::addr_t                    m_data_ptr;
+        uint8_t                         m_flags;
+        
+        objc_class_t () :
+        m_isa (0),
+        m_superclass (0),
+        m_cache_ptr (0),
+        m_vtable_ptr (0),
+        m_data_ptr (0),
+        m_flags (0)
+        {
+        }
+        
+        void
+        Clear()
+        {
+            m_isa = 0;
+            m_superclass = 0;
+            m_cache_ptr = 0;
+            m_vtable_ptr = 0;
+            m_data_ptr = 0;
+            m_flags = 0;
+        }
+        
+        bool
+        Read(Process *process, lldb::addr_t addr);
+    };
+    
+    struct class_ro_t {
+        uint32_t                        m_flags;
+        uint32_t                        m_instanceStart;
+        uint32_t                        m_instanceSize;
+        uint32_t                        m_reserved;
+        
+        lldb::addr_t                    m_ivarLayout_ptr;
+        lldb::addr_t                    m_name_ptr;
+        lldb::addr_t                    m_baseMethods_ptr;
+        lldb::addr_t                    m_baseProtocols_ptr;
+        lldb::addr_t                    m_ivars_ptr;
+        
+        lldb::addr_t                    m_weakIvarLayout_ptr;
+        lldb::addr_t                    m_baseProperties_ptr;
+        
+        std::string                     m_name;
+        
+        bool
+        Read(Process *process, lldb::addr_t addr);
+    };
+    
+    struct class_rw_t {
+        uint32_t                        m_flags;
+        uint32_t                        m_version;
+        
+        lldb::addr_t                    m_ro_ptr;
+        union {
+            lldb::addr_t                m_method_list_ptr;
+            lldb::addr_t                m_method_lists_ptr;
+        };
+        lldb::addr_t                    m_properties_ptr;
+        lldb::addr_t                    m_protocols_ptr;
+        
+        ObjCLanguageRuntime::ObjCISA    m_firstSubclass;
+        ObjCLanguageRuntime::ObjCISA    m_nextSiblingClass;
+        
+        bool
+        Read(Process *process, lldb::addr_t addr);
+    };
+    
+    struct method_list_t
+    {
+        uint32_t        m_entsize;
+        uint32_t        m_count;
+        lldb::addr_t    m_first_ptr;
+        
+        bool
+        Read(Process *process, lldb::addr_t addr);
+    };
+    
+    struct method_t
+    {
+        lldb::addr_t    m_name_ptr;
+        lldb::addr_t    m_types_ptr;
+        lldb::addr_t    m_imp_ptr;
+        
+        std::string     m_name;
+        std::string     m_types;
+        
+        static size_t GetSize(Process *process)
+        {
+            size_t ptr_size = process->GetAddressByteSize();
+            
+            return ptr_size     // SEL name;
+            + ptr_size   // const char *types;
+            + ptr_size;  // IMP imp;
+        }
+        
+        bool
+        Read(Process *process, lldb::addr_t addr);
+    };
+    
+    struct ivar_list_t
+    {
+        uint32_t        m_entsize;
+        uint32_t        m_count;
+        lldb::addr_t    m_first_ptr;
+        
+        bool Read(Process *process, lldb::addr_t addr);
+    };
+    
+    struct ivar_t
+    {
+        lldb::addr_t    m_offset_ptr;
+        lldb::addr_t    m_name_ptr;
+        lldb::addr_t    m_type_ptr;
+        uint32_t        m_alignment;
+        uint32_t        m_size;
+        
+        std::string     m_name;
+        std::string     m_type;
+        
+        static size_t GetSize(Process *process)
+        {
+            size_t ptr_size = process->GetAddressByteSize();
+            
+            return ptr_size             // uintptr_t *offset;
+            + ptr_size             // const char *name;
+            + ptr_size             // const char *type;
+            + sizeof(uint32_t)     // uint32_t alignment;
+            + sizeof(uint32_t);    // uint32_t size;
+        }
+        
+        bool
+        Read(Process *process, lldb::addr_t addr);
+    };
+    
+    class iVarsStorage
+    {
+    public:
+        iVarsStorage ();
+        
+        size_t
+        size ();
+        
+        iVarDescriptor&
+        operator[] (size_t idx);
+        
+        void
+        fill (AppleObjCRuntimeV2& runtime, ClassDescriptorV2& descriptor);
+        
+    private:
+        bool m_filled;
+        std::vector<iVarDescriptor> m_ivars;
+        Mutex m_mutex;
+    };
+    
+    bool
+    Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class) const;
+    
+    bool
+    Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw) const;
+    
+    AppleObjCRuntimeV2 &m_runtime;          // The runtime, so we can read information lazily.
+    lldb::addr_t        m_objc_class_ptr;   // The address of the objc_class_t.  (I.e., objects of this class type have this as their ISA)
+    ConstString         m_name;             // May be NULL
+    iVarsStorage        m_ivars_storage;
+};
+
+// tagged pointer descriptor
+class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
+{
+public:
+    ClassDescriptorV2Tagged (ConstString class_name,
+                             uint64_t payload)
+    {
+        m_name = class_name;
+        if (!m_name)
+        {
+            m_valid = false;
+            return;
+        }
+        m_valid = true;
+        m_payload = payload;
+        m_info_bits = (m_payload & 0xF0ULL) >> 4;
+        m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
+    }
+    
+    ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
+                             uint64_t payload)
+    {
+        if (!actual_class_sp)
+        {
+            m_valid = false;
+            return;
+        }
+        m_name = actual_class_sp->GetClassName();
+        if (!m_name)
+        {
+            m_valid = false;
+            return;
+        }
+        m_valid = true;
+        m_payload = payload;
+        m_info_bits = (m_payload & 0x0FULL);
+        m_value_bits = (m_payload & ~0x0FULL) >> 4;
+    }
+    
+    virtual ConstString
+    GetClassName ()
+    {
+        return m_name;
+    }
+    
+    virtual ObjCLanguageRuntime::ClassDescriptorSP
+    GetSuperclass ()
+    {
+        // tagged pointers can represent a class that has a superclass, but since that information is not
+        // stored in the object itself, we would have to query the runtime to discover the hierarchy
+        // for the time being, we skip this step in the interest of static discovery
+        return ObjCLanguageRuntime::ClassDescriptorSP();
+    }
+    
+    virtual bool
+    IsValid ()
+    {
+        return m_valid;
+    }
+    
+    virtual bool
+    IsKVO ()
+    {
+        return false; // tagged pointers are not KVO'ed
+    }
+    
+    virtual bool
+    IsCFType ()
+    {
+        return false; // tagged pointers are not CF objects
+    }
+    
+    virtual bool
+    GetTaggedPointerInfo (uint64_t* info_bits = NULL,
+                          uint64_t* value_bits = NULL,
+                          uint64_t* payload = NULL)
+    {
+        if (info_bits)
+            *info_bits = GetInfoBits();
+        if (value_bits)
+            *value_bits = GetValueBits();
+        if (payload)
+            *payload = GetPayload();
+        return true;
+    }
+    
+    virtual uint64_t
+    GetInstanceSize ()
+    {
+        return (IsValid() ? m_pointer_size : 0);
+    }
+    
+    virtual ObjCLanguageRuntime::ObjCISA
+    GetISA ()
+    {
+        return 0; // tagged pointers have no ISA
+    }
+    
+    // these calls are not part of any formal tagged pointers specification
+    virtual uint64_t
+    GetValueBits ()
+    {
+        return (IsValid() ? m_value_bits : 0);
+    }
+    
+    virtual uint64_t
+    GetInfoBits ()
+    {
+        return (IsValid() ? m_info_bits : 0);
+    }
+    
+    virtual uint64_t
+    GetPayload ()
+    {
+        return (IsValid() ? m_payload : 0);
+    }
+    
+    virtual
+    ~ClassDescriptorV2Tagged ()
+    {}
+    
+private:
+    ConstString m_name;
+    uint8_t m_pointer_size;
+    bool m_valid;
+    uint64_t m_info_bits;
+    uint64_t m_value_bits;
+    uint64_t m_payload;
+    
+};
+    
+} // namespace lldb_private
+
+#endif  // liblldb_AppleObjCRuntime_h_
+

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Tue Aug 19 16:46:37 2014
@@ -42,9 +42,13 @@
 #include "lldb/Target/Thread.h"
 
 #include "AppleObjCRuntimeV2.h"
+#include "AppleObjCClassDescriptorV2.h"
+#include "AppleObjCTypeEncodingParser.h"
 #include "AppleObjCTypeVendor.h"
 #include "AppleObjCTrampolineHandler.h"
 
+#include "clang/AST/ASTContext.h"
+
 #include <vector>
 
 using namespace lldb;
@@ -348,7 +352,8 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2 (
     m_has_object_getClass (false),
     m_loaded_objc_opt (false),
     m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)),
-    m_tagged_pointer_vendor_ap(TaggedPointerVendor::CreateInstance(*this,objc_module_sp))
+    m_tagged_pointer_vendor_ap(TaggedPointerVendor::CreateInstance(*this,objc_module_sp)),
+    m_encoding_to_type_sp()
 {
     static const ConstString g_gdb_object_getClass("gdb_object_getClass");
     m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
@@ -855,757 +860,6 @@ AppleObjCRuntimeV2::HashTableSignature::
     return true;
 }
 
-class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
-{
-public:
-    friend class lldb_private::AppleObjCRuntimeV2;
-    
-private:
-    // The constructor should only be invoked by the runtime as it builds its caches
-    // or populates them.  A ClassDescriptorV2 should only ever exist in a cache.
-    ClassDescriptorV2 (AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name) :
-        m_runtime (runtime),
-        m_objc_class_ptr (isa),
-        m_name (name)
-    {
-    }
-
-public:
-    virtual ConstString
-    GetClassName ()
-    {
-        if (!m_name)
-        {
-            lldb_private::Process *process = m_runtime.GetProcess();
-
-            if (process)
-            {
-                std::unique_ptr<objc_class_t> objc_class;
-                std::unique_ptr<class_ro_t> class_ro;
-                std::unique_ptr<class_rw_t> class_rw;
-                
-                if (!Read_objc_class(process, objc_class))
-                    return m_name;
-                if (!Read_class_row(process, *objc_class, class_ro, class_rw))
-                    return m_name;
-                
-                m_name = ConstString(class_ro->m_name.c_str());
-            }
-        }
-        return m_name;
-    }
-    
-    virtual ObjCLanguageRuntime::ClassDescriptorSP
-    GetSuperclass ()
-    {
-        lldb_private::Process *process = m_runtime.GetProcess();
-
-        if (!process)
-            return ObjCLanguageRuntime::ClassDescriptorSP();
-        
-        std::unique_ptr<objc_class_t> objc_class;
-
-        if (!Read_objc_class(process, objc_class))
-            return ObjCLanguageRuntime::ClassDescriptorSP();
-
-        return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(objc_class->m_superclass);
-    }
-    
-    virtual bool
-    IsValid ()
-    {
-        return true;    // any Objective-C v2 runtime class descriptor we vend is valid
-    }
-    
-    // a custom descriptor is used for tagged pointers
-    virtual bool
-    GetTaggedPointerInfo (uint64_t* info_bits = NULL,
-                          uint64_t* value_bits = NULL,
-                          uint64_t* payload = NULL)
-    {
-        return false;
-    }
-    
-    virtual uint64_t
-    GetInstanceSize ()
-    {
-        lldb_private::Process *process = m_runtime.GetProcess();
-        
-        if (process)
-        {
-            std::unique_ptr<objc_class_t> objc_class;
-            std::unique_ptr<class_ro_t> class_ro;
-            std::unique_ptr<class_rw_t> class_rw;
-            
-            if (!Read_objc_class(process, objc_class))
-                return 0;
-            if (!Read_class_row(process, *objc_class, class_ro, class_rw))
-                return 0;
-            
-            return class_ro->m_instanceSize;
-        }
-        
-        return 0;
-    }
-    
-    virtual ObjCLanguageRuntime::ObjCISA
-    GetISA ()
-    {        
-        return m_objc_class_ptr;
-    }
-    
-    virtual bool
-    Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
-              std::function <bool (const char *, const char *)> const &instance_method_func,
-              std::function <bool (const char *, const char *)> const &class_method_func,
-              std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func)
-    {
-        lldb_private::Process *process = m_runtime.GetProcess();
-
-        std::unique_ptr<objc_class_t> objc_class;
-        std::unique_ptr<class_ro_t> class_ro;
-        std::unique_ptr<class_rw_t> class_rw;
-        
-        if (!Read_objc_class(process, objc_class))
-            return 0;
-        if (!Read_class_row(process, *objc_class, class_ro, class_rw))
-            return 0;
-    
-        static ConstString NSObject_name("NSObject");
-        
-        if (m_name != NSObject_name && superclass_func)
-            superclass_func(objc_class->m_superclass);
-        
-        if (instance_method_func)
-        {
-            std::unique_ptr<method_list_t> base_method_list;
-            
-            base_method_list.reset(new method_list_t);
-            if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
-                return false;
-            
-            if (base_method_list->m_entsize != method_t::GetSize(process))
-                return false;
-            
-            std::unique_ptr<method_t> method;
-            method.reset(new method_t);
-            
-            for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i)
-            {
-                method->Read(process, base_method_list->m_first_ptr + (i * base_method_list->m_entsize));
-                
-                if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
-                    break;
-            }
-        }
-        
-        if (class_method_func)
-        {
-            ClassDescriptorV2 metaclass(m_runtime, objc_class->m_isa, NULL); // The metaclass is not in the cache
-            
-            // We don't care about the metaclass's superclass, or its class methods.  Its instance methods are
-            // our class methods.
-            
-            metaclass.Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> (nullptr),
-                               class_method_func,
-                               std::function <bool (const char *, const char *)> (nullptr),
-                               std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> (nullptr));
-        }
-        
-        if (ivar_func)
-        {
-            ivar_list_t ivar_list;
-            if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
-                return false;
-            
-            if (ivar_list.m_entsize != ivar_t::GetSize(process))
-                return false;
-            
-            ivar_t ivar;
-            
-            for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i)
-            {
-                ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
-                
-                if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(), ivar.m_offset_ptr, ivar.m_size))
-                    break;
-            }
-        }
-            
-        return true;
-    }
-    
-    virtual
-    ~ClassDescriptorV2 ()
-    {
-    }
-        
-private:
-    static const uint32_t RW_REALIZED = (1 << 31);
-    
-    struct objc_class_t {
-        ObjCLanguageRuntime::ObjCISA    m_isa;              // The class's metaclass.
-        ObjCLanguageRuntime::ObjCISA    m_superclass;
-        lldb::addr_t                    m_cache_ptr;
-        lldb::addr_t                    m_vtable_ptr;
-        lldb::addr_t                    m_data_ptr;
-        uint8_t                         m_flags;
-        
-        objc_class_t () :
-            m_isa (0),
-            m_superclass (0),
-            m_cache_ptr (0),
-            m_vtable_ptr (0),
-            m_data_ptr (0),
-            m_flags (0)
-        {
-        }
-        
-        void
-        Clear()
-        {
-            m_isa = 0;
-            m_superclass = 0;
-            m_cache_ptr = 0;
-            m_vtable_ptr = 0;
-            m_data_ptr = 0;
-            m_flags = 0;
-        }
-
-        bool Read(Process *process, lldb::addr_t addr)
-        {
-            size_t ptr_size = process->GetAddressByteSize();
-            
-            size_t objc_class_size = ptr_size   // uintptr_t isa;
-            + ptr_size   // Class superclass;
-            + ptr_size   // void *cache;
-            + ptr_size   // IMP *vtable;
-            + ptr_size;  // uintptr_t data_NEVER_USE;
-            
-            DataBufferHeap objc_class_buf (objc_class_size, '\0');
-            Error error;
-            
-            process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
-            if (error.Fail())
-            {
-                return false;
-            }
-            
-            DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size, process->GetByteOrder(), process->GetAddressByteSize());
-            
-            lldb::offset_t cursor = 0;
-            
-            m_isa           = extractor.GetAddress_unchecked(&cursor);   // uintptr_t isa;
-            m_superclass    = extractor.GetAddress_unchecked(&cursor);   // Class superclass;
-            m_cache_ptr     = extractor.GetAddress_unchecked(&cursor);   // void *cache;
-            m_vtable_ptr    = extractor.GetAddress_unchecked(&cursor);   // IMP *vtable;
-            lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor);   // uintptr_t data_NEVER_USE;
-            
-            m_flags         = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
-            m_data_ptr      = data_NEVER_USE & ~(lldb::addr_t)3;
-            
-            return true;
-        }
-    };
-    
-    struct class_ro_t {
-        uint32_t                        m_flags;
-        uint32_t                        m_instanceStart;
-        uint32_t                        m_instanceSize;
-        uint32_t                        m_reserved;
-        
-        lldb::addr_t                    m_ivarLayout_ptr;
-        lldb::addr_t                    m_name_ptr;
-        lldb::addr_t                    m_baseMethods_ptr;
-        lldb::addr_t                    m_baseProtocols_ptr;
-        lldb::addr_t                    m_ivars_ptr;
-        
-        lldb::addr_t                    m_weakIvarLayout_ptr;
-        lldb::addr_t                    m_baseProperties_ptr;
-        
-        std::string                     m_name;
-        
-        bool Read(Process *process, lldb::addr_t addr)
-        {
-            size_t ptr_size = process->GetAddressByteSize();
-            
-            size_t size = sizeof(uint32_t)             // uint32_t flags;
-            + sizeof(uint32_t)                         // uint32_t instanceStart;
-            + sizeof(uint32_t)                         // uint32_t instanceSize;
-            + (ptr_size == 8 ? sizeof(uint32_t) : 0)   // uint32_t reserved; // __LP64__ only
-            + ptr_size                                 // const uint8_t *ivarLayout;
-            + ptr_size                                 // const char *name;
-            + ptr_size                                 // const method_list_t *baseMethods;
-            + ptr_size                                 // const protocol_list_t *baseProtocols;
-            + ptr_size                                 // const ivar_list_t *ivars;
-            + ptr_size                                 // const uint8_t *weakIvarLayout;
-            + ptr_size;                                // const property_list_t *baseProperties;
-            
-            DataBufferHeap buffer (size, '\0');
-            Error error;
-            
-            process->ReadMemory(addr, buffer.GetBytes(), size, error);
-            if (error.Fail())
-            {
-                return false;
-            }
-            
-            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-            
-            lldb::offset_t cursor = 0;
-            
-            m_flags             = extractor.GetU32_unchecked(&cursor);
-            m_instanceStart     = extractor.GetU32_unchecked(&cursor);
-            m_instanceSize      = extractor.GetU32_unchecked(&cursor);
-            if (ptr_size == 8)
-                m_reserved      = extractor.GetU32_unchecked(&cursor);
-            else
-                m_reserved      = 0;
-            m_ivarLayout_ptr     = extractor.GetAddress_unchecked(&cursor);
-            m_name_ptr           = extractor.GetAddress_unchecked(&cursor);
-            m_baseMethods_ptr    = extractor.GetAddress_unchecked(&cursor);
-            m_baseProtocols_ptr  = extractor.GetAddress_unchecked(&cursor);
-            m_ivars_ptr          = extractor.GetAddress_unchecked(&cursor);
-            m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
-            m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
-            
-            DataBufferHeap name_buf(1024, '\0');
-            
-            process->ReadCStringFromMemory(m_name_ptr, (char*)name_buf.GetBytes(), name_buf.GetByteSize(), error);
-            
-            if (error.Fail())
-            {
-                return false;
-            }
-            
-            m_name.assign((char*)name_buf.GetBytes());
-                
-            return true;
-        }
-    };
-    
-    struct class_rw_t {
-        uint32_t                        m_flags;
-        uint32_t                        m_version;
-        
-        lldb::addr_t                    m_ro_ptr;
-        union {
-            lldb::addr_t                m_method_list_ptr;
-            lldb::addr_t                m_method_lists_ptr;
-        };
-        lldb::addr_t                    m_properties_ptr;
-        lldb::addr_t                    m_protocols_ptr;
-        
-        ObjCLanguageRuntime::ObjCISA    m_firstSubclass;
-        ObjCLanguageRuntime::ObjCISA    m_nextSiblingClass;
-        
-        bool Read(Process *process, lldb::addr_t addr)
-        {
-            size_t ptr_size = process->GetAddressByteSize();
-            
-            size_t size = sizeof(uint32_t)  // uint32_t flags;
-            + sizeof(uint32_t)  // uint32_t version;
-            + ptr_size          // const class_ro_t *ro;
-            + ptr_size          // union { method_list_t **method_lists; method_list_t *method_list; };
-            + ptr_size          // struct chained_property_list *properties;
-            + ptr_size          // const protocol_list_t **protocols;
-            + ptr_size          // Class firstSubclass;
-            + ptr_size;         // Class nextSiblingClass;
-            
-            DataBufferHeap buffer (size, '\0');
-            Error error;
-            
-            process->ReadMemory(addr, buffer.GetBytes(), size, error);
-            if (error.Fail())
-            {
-                return false;
-            }
-            
-            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-            
-            lldb::offset_t cursor = 0;
-            
-            m_flags             = extractor.GetU32_unchecked(&cursor);
-            m_version           = extractor.GetU32_unchecked(&cursor);
-            m_ro_ptr            = extractor.GetAddress_unchecked(&cursor);
-            m_method_list_ptr   = extractor.GetAddress_unchecked(&cursor);
-            m_properties_ptr    = extractor.GetAddress_unchecked(&cursor);
-            m_firstSubclass     = extractor.GetAddress_unchecked(&cursor);
-            m_nextSiblingClass  = extractor.GetAddress_unchecked(&cursor);
-            
-            return true;
-        }
-    };
-    
-    struct method_list_t
-    {
-        uint32_t        m_entsize;
-        uint32_t        m_count;
-        lldb::addr_t    m_first_ptr;
-        
-        bool Read(Process *process, lldb::addr_t addr)
-        {
-            size_t size = sizeof(uint32_t)  // uint32_t entsize_NEVER_USE;
-            + sizeof(uint32_t); // uint32_t count;
-            
-            DataBufferHeap buffer (size, '\0');
-            Error error;
-            
-            process->ReadMemory(addr, buffer.GetBytes(), size, error);
-            if (error.Fail())
-            {
-                return false;
-            }
-            
-            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-            
-            lldb::offset_t cursor = 0;
-            
-            m_entsize   = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
-            m_count     = extractor.GetU32_unchecked(&cursor);
-            m_first_ptr  = addr + cursor;
-            
-            return true;
-        }
-    };
-    
-    struct method_t
-    {
-        lldb::addr_t    m_name_ptr;
-        lldb::addr_t    m_types_ptr;
-        lldb::addr_t    m_imp_ptr;
-        
-        std::string     m_name;
-        std::string     m_types;
-        
-        static size_t GetSize(Process *process)
-        {
-            size_t ptr_size = process->GetAddressByteSize();
-            
-            return ptr_size     // SEL name;
-            + ptr_size   // const char *types;
-            + ptr_size;  // IMP imp;
-        }
-        
-        bool Read(Process *process, lldb::addr_t addr)
-        {
-            size_t size = GetSize(process);
-            
-            DataBufferHeap buffer (size, '\0');
-            Error error;
-            
-            process->ReadMemory(addr, buffer.GetBytes(), size, error);
-            if (error.Fail())
-            {
-                return false;
-            }
-            
-            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-            
-            lldb::offset_t cursor = 0;
-            
-            m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
-            m_types_ptr  = extractor.GetAddress_unchecked(&cursor);
-            m_imp_ptr    = extractor.GetAddress_unchecked(&cursor);
-            
-            const size_t buffer_size = 1024;
-            size_t count;
-            
-            DataBufferHeap string_buf(buffer_size, 0);
-            
-            count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
-            m_name.assign((char*)string_buf.GetBytes(), count);
-            
-            count = process->ReadCStringFromMemory(m_types_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
-            m_types.assign((char*)string_buf.GetBytes(), count);
-            
-            return true;
-        }
-    };
-    
-    struct ivar_list_t
-    {
-        uint32_t        m_entsize;
-        uint32_t        m_count;
-        lldb::addr_t    m_first_ptr;
-        
-        bool Read(Process *process, lldb::addr_t addr)
-        {
-            size_t size = sizeof(uint32_t)  // uint32_t entsize;
-                        + sizeof(uint32_t); // uint32_t count;
-            
-            DataBufferHeap buffer (size, '\0');
-            Error error;
-            
-            process->ReadMemory(addr, buffer.GetBytes(), size, error);
-            if (error.Fail())
-            {
-                return false;
-            }
-            
-            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-            
-            lldb::offset_t cursor = 0;
-            
-            m_entsize   = extractor.GetU32_unchecked(&cursor);
-            m_count     = extractor.GetU32_unchecked(&cursor);
-            m_first_ptr = addr + cursor;
-            
-            return true;
-        }
-    };
-    
-    struct ivar_t
-    {
-        lldb::addr_t    m_offset_ptr;
-        lldb::addr_t    m_name_ptr;
-        lldb::addr_t    m_type_ptr;
-        uint32_t        m_alignment;
-        uint32_t        m_size;
-        
-        std::string     m_name;
-        std::string     m_type;
-        
-        static size_t GetSize(Process *process)
-        {
-            size_t ptr_size = process->GetAddressByteSize();
-            
-            return ptr_size             // uintptr_t *offset;
-                 + ptr_size             // const char *name;
-                 + ptr_size             // const char *type;
-                 + sizeof(uint32_t)     // uint32_t alignment;
-                 + sizeof(uint32_t);    // uint32_t size;
-        }
-        
-        bool Read(Process *process, lldb::addr_t addr)
-        {
-            size_t size = GetSize(process);
-            
-            DataBufferHeap buffer (size, '\0');
-            Error error;
-            
-            process->ReadMemory(addr, buffer.GetBytes(), size, error);
-            if (error.Fail())
-            {
-                return false;
-            }
-            
-            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-            
-            lldb::offset_t cursor = 0;
-            
-            m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
-            m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
-            m_type_ptr   = extractor.GetAddress_unchecked(&cursor);
-            m_alignment  = extractor.GetU32_unchecked(&cursor);
-            m_size       = extractor.GetU32_unchecked(&cursor);
-            
-            const size_t buffer_size = 1024;
-            size_t count;
-            
-            DataBufferHeap string_buf(buffer_size, 0);
-            
-            count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
-            m_name.assign((char*)string_buf.GetBytes(), count);
-            
-            count = process->ReadCStringFromMemory(m_type_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
-            m_type.assign((char*)string_buf.GetBytes(), count);
-            
-            return true;
-        }
-    };
-    
-    bool Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class)
-    {
-        objc_class.reset(new objc_class_t);
-        
-        bool ret = objc_class->Read (process, m_objc_class_ptr);
-        
-        if (!ret)
-            objc_class.reset();
-        
-        return ret;
-    }
-    
-    bool Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw)
-    {
-        class_ro.reset();
-        class_rw.reset();
-        
-        Error error;
-        uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
-        if (!error.Success())
-            return false;
-
-        if (class_row_t_flags & RW_REALIZED)
-        {
-            class_rw.reset(new class_rw_t);
-            
-            if (!class_rw->Read(process, objc_class.m_data_ptr))
-            {
-                class_rw.reset();
-                return false;
-            }
-            
-            class_ro.reset(new class_ro_t);
-            
-            if (!class_ro->Read(process, class_rw->m_ro_ptr))
-            {
-                class_rw.reset();
-                class_ro.reset();
-                return false;
-            }
-        }
-        else
-        {
-            class_ro.reset(new class_ro_t);
-            
-            if (!class_ro->Read(process, objc_class.m_data_ptr))
-            {
-                class_ro.reset();
-                return false;
-            }
-        }
-        
-        return true;
-    }
-
-    AppleObjCRuntimeV2 &m_runtime;          // The runtime, so we can read information lazily.
-    lldb::addr_t        m_objc_class_ptr;   // The address of the objc_class_t.  (I.e., objects of this class type have this as their ISA)
-    ConstString         m_name;             // May be NULL
-};
-
-// tagged pointer descriptor
-class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
-{
-public:
-    ClassDescriptorV2Tagged (ConstString class_name,
-                             uint64_t payload)
-    {
-        m_name = class_name;
-        if (!m_name)
-        {
-            m_valid = false;
-            return;
-        }
-        m_valid = true;
-        m_payload = payload;
-        m_info_bits = (m_payload & 0xF0ULL) >> 4;
-        m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
-    }
-    
-    ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
-                             uint64_t payload)
-    {
-        if (!actual_class_sp)
-        {
-            m_valid = false;
-            return;
-        }
-        m_name = actual_class_sp->GetClassName();
-        if (!m_name)
-        {
-            m_valid = false;
-            return;
-        }
-        m_valid = true;
-        m_payload = payload;
-        m_info_bits = (m_payload & 0x0FULL);
-        m_value_bits = (m_payload & ~0x0FULL) >> 4;
-    }
-    
-    virtual ConstString
-    GetClassName ()
-    {
-        return m_name;
-    }
-    
-    virtual ObjCLanguageRuntime::ClassDescriptorSP
-    GetSuperclass ()
-    {
-        // tagged pointers can represent a class that has a superclass, but since that information is not
-        // stored in the object itself, we would have to query the runtime to discover the hierarchy
-        // for the time being, we skip this step in the interest of static discovery
-        return ObjCLanguageRuntime::ClassDescriptorSP();
-    }
-    
-    virtual bool
-    IsValid ()
-    {
-        return m_valid;
-    }
-    
-    virtual bool
-    IsKVO ()
-    {
-        return false; // tagged pointers are not KVO'ed
-    }
-    
-    virtual bool
-    IsCFType ()
-    {
-        return false; // tagged pointers are not CF objects
-    }
-    
-    virtual bool
-    GetTaggedPointerInfo (uint64_t* info_bits = NULL,
-                          uint64_t* value_bits = NULL,
-                          uint64_t* payload = NULL)
-    {
-        if (info_bits)
-            *info_bits = GetInfoBits();
-        if (value_bits)
-            *value_bits = GetValueBits();
-        if (payload)
-            *payload = GetPayload();
-        return true;
-    }
-    
-    virtual uint64_t
-    GetInstanceSize ()
-    {
-        return (IsValid() ? m_pointer_size : 0);
-    }
-    
-    virtual ObjCLanguageRuntime::ObjCISA
-    GetISA ()
-    {
-        return 0; // tagged pointers have no ISA
-    }
-    
-    // these calls are not part of any formal tagged pointers specification
-    virtual uint64_t
-    GetValueBits ()
-    {
-        return (IsValid() ? m_value_bits : 0);
-    }
-    
-    virtual uint64_t
-    GetInfoBits ()
-    {
-        return (IsValid() ? m_info_bits : 0);
-    }
-    
-    virtual uint64_t
-    GetPayload ()
-    {
-        return (IsValid() ? m_payload : 0);
-    }
-    
-    virtual
-    ~ClassDescriptorV2Tagged ()
-    {}
-
-private:
-    ConstString m_name;
-    uint8_t m_pointer_size;
-    bool m_valid;
-    uint64_t m_info_bits;
-    uint64_t m_value_bits;
-    uint64_t m_payload;
-
-};
-
 ObjCLanguageRuntime::ClassDescriptorSP
 AppleObjCRuntimeV2::GetClassDescriptorFromISA (ObjCISA isa)
 {
@@ -1621,6 +875,18 @@ ObjCLanguageRuntime::ClassDescriptorSP
 AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
 {
     ClassDescriptorSP objc_class_sp;
+    if (valobj.IsBaseClass())
+    {
+        ValueObject *parent = valobj.GetParent();
+        // if I am my own parent, bail out of here fast..
+        if (parent && parent != &valobj)
+        {
+            ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
+            if (parent_descriptor_sp)
+                return parent_descriptor_sp->GetSuperclass();
+        }
+        return nullptr;
+    }
     // if we get an invalid VO (which might still happen when playing around
     // with pointers returned by the expression parser, don't consider this
     // a valid ObjC object)
@@ -2651,3 +1917,11 @@ AppleObjCRuntimeV2::NonPointerISACache::
     }
     return false;
 }
+
+ObjCLanguageRuntime::EncodingToTypeSP
+AppleObjCRuntimeV2::GetEncodingToType ()
+{
+    if (!m_encoding_to_type_sp)
+        m_encoding_to_type_sp.reset(new AppleObjCTypeEncodingParser(*this));
+    return m_encoding_to_type_sp;
+}

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h Tue Aug 19 16:46:37 2014
@@ -105,6 +105,9 @@ public:
     virtual lldb::addr_t
     LookupRuntimeSymbol (const ConstString &name);
     
+    virtual EncodingToTypeSP
+    GetEncodingToType ();
+    
 protected:
     virtual lldb::BreakpointResolverSP
     CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);
@@ -277,6 +280,7 @@ private:
     bool                                    m_loaded_objc_opt;
     std::unique_ptr<NonPointerISACache>       m_non_pointer_isa_cache_ap;
     std::unique_ptr<TaggedPointerVendor>    m_tagged_pointer_vendor_ap;
+    EncodingToTypeSP                        m_encoding_to_type_sp;
 };
     
 } // namespace lldb_private

Added: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp?rev=216026&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp (added)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp Tue Aug 19 16:46:37 2014
@@ -0,0 +1,275 @@
+//===-- AppleObjCTypeEncodingParser.cpp -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCTypeEncodingParser.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/StringLexer.h"
+
+#include <vector>
+
+using namespace lldb_private;
+using namespace lldb_utility;
+
+AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser (ObjCLanguageRuntime& runtime) :
+ObjCLanguageRuntime::EncodingToType()
+{
+    if (!m_scratch_ast_ctx_ap)
+        m_scratch_ast_ctx_ap.reset(new ClangASTContext(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().str().c_str()));
+}
+
+std::string
+AppleObjCTypeEncodingParser::ReadStructName(lldb_utility::StringLexer& type)
+{
+    StreamString buffer;
+    while (type.HasAtLeast(1) && type.Peek() != '=')
+        buffer.Printf("%c",type.Next());
+    return buffer.GetString();
+}
+
+std::string
+AppleObjCTypeEncodingParser::ReadStructElementName(lldb_utility::StringLexer& type)
+{
+    StreamString buffer;
+    while (type.HasAtLeast(1) && type.Peek() != '"')
+        buffer.Printf("%c",type.Next());
+    return buffer.GetString();
+}
+
+uint
+AppleObjCTypeEncodingParser::ReadNumber (lldb_utility::StringLexer& type)
+{
+    uint total = 0;
+    while (type.HasAtLeast(1) && isdigit(type.Peek()))
+           total = 10*total + (type.Next() - '0');
+    return total;
+}
+
+// as an extension to the published grammar recent runtimes emit structs like this:
+// "{CGRect=\"origin\"{CGPoint=\"x\"d\"y\"d}\"size\"{CGSize=\"width\"d\"height\"d}}"
+
+AppleObjCTypeEncodingParser::StructElement::StructElement() :
+name(""),
+type(clang::QualType()),
+bitfield(0)
+{}
+
+AppleObjCTypeEncodingParser::StructElement
+AppleObjCTypeEncodingParser::ReadStructElement (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype)
+{
+    StructElement retval;
+    if (type.NextIf('"'))
+        retval.name = ReadStructElementName(type);
+    if (!type.NextIf('"'))
+        return retval;
+    uint32_t bitfield_size = 0;
+    retval.type = BuildType(ast_ctx, type, allow_unknownanytype, &bitfield_size);
+    retval.bitfield = bitfield_size;
+    return retval;
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildStruct (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype)
+{
+    return BuildAggregate(ast_ctx, type, allow_unknownanytype, '{', '}', clang::TTK_Struct);
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildUnion (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype)
+{
+    return BuildAggregate(ast_ctx, type, allow_unknownanytype, '(', ')', clang::TTK_Union);
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildAggregate (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype, char opener, char closer, uint kind)
+{
+    if (!type.NextIf(opener))
+        return clang::QualType();
+    std::string name(ReadStructName(type));
+    if (!type.NextIf('='))
+        return clang::QualType();
+    bool in_union = true;
+    std::vector<StructElement> elements;
+    while (in_union && type.HasAtLeast(1))
+    {
+        if (type.NextIf(closer))
+        {
+            in_union = false;
+            break;
+        }
+        else
+        {
+            auto element = ReadStructElement(ast_ctx, type, allow_unknownanytype);
+            if (element.type.isNull())
+                break;
+            else
+                elements.push_back(element);
+        }
+    }
+    if (in_union)
+        return clang::QualType();
+    ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+    if (!lldb_ctx)
+        return clang::QualType();
+    ClangASTType union_type(lldb_ctx->CreateRecordType(nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC));
+    if (union_type)
+    {
+        union_type.StartTagDeclarationDefinition();
+        
+        unsigned int count = 0;
+        for (auto element: elements)
+        {
+            if (element.name.empty())
+            {
+                StreamString elem_name;
+                elem_name.Printf("__unnamed_%u",count);
+                element.name = std::string(elem_name.GetData());
+            }
+            union_type.AddFieldToRecordType(element.name.c_str(), ClangASTType(&ast_ctx,element.type.getAsOpaquePtr()), lldb::eAccessPublic, element.bitfield);
+            ++count;
+        }
+        
+        union_type.CompleteTagDeclarationDefinition();
+    }
+    return union_type.GetQualType();
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildArray (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype)
+{
+    if (!type.NextIf('['))
+        return clang::QualType();
+    uint size = ReadNumber(type);
+    clang::QualType element_type(BuildType(ast_ctx, type, allow_unknownanytype));
+    if (!type.NextIf(']'))
+        return clang::QualType();
+    ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+    if (!lldb_ctx)
+        return clang::QualType();
+    ClangASTType array_type(lldb_ctx->CreateArrayType(ClangASTType(&ast_ctx,element_type.getAsOpaquePtr()), size, false));
+    return array_type.GetQualType();
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildType (clang::ASTContext &ast_ctx, StringLexer& type, bool allow_unknownanytype, uint32_t *bitfield_bit_size)
+{
+    if (!type.HasAtLeast(1))
+        return clang::QualType();
+    
+    if (type.NextIf('c'))
+        return ast_ctx.CharTy;
+    if (type.NextIf('i'))
+        return ast_ctx.IntTy;
+    if (type.NextIf('s'))
+        return ast_ctx.ShortTy;
+    if (type.NextIf('l'))
+    {
+        ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+        if (!lldb_ctx)
+            return clang::QualType();
+        return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
+    }
+    if (type.NextIf('q'))
+        return ast_ctx.LongLongTy;
+    if (type.NextIf('C'))
+        return ast_ctx.UnsignedCharTy;
+    if (type.NextIf('I'))
+        return ast_ctx.UnsignedIntTy;
+    if (type.NextIf('S'))
+        return ast_ctx.UnsignedShortTy;
+    if (type.NextIf('L'))
+    {
+        ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+        if (!lldb_ctx)
+            return clang::QualType();
+        return lldb_ctx->GetIntTypeFromBitSize(32, false).GetQualType();
+    }
+    if (type.NextIf('Q'))
+        return ast_ctx.UnsignedLongLongTy;
+    if (type.NextIf('f'))
+        return ast_ctx.FloatTy;
+    if (type.NextIf('d'))
+        return ast_ctx.DoubleTy;
+    if (type.NextIf('B'))
+        return ast_ctx.BoolTy;
+    if (type.NextIf('v'))
+        return ast_ctx.VoidTy;
+    if (type.NextIf('*'))
+        return ast_ctx.getPointerType(ast_ctx.CharTy);
+    if (type.NextIf('@'))
+        return ast_ctx.getObjCIdType();
+    if (type.NextIf('#'))
+        return ast_ctx.getObjCClassType();
+    if (type.NextIf(':'))
+        return ast_ctx.getObjCSelType();
+    
+    if (type.NextIf('b'))
+    {
+        uint size = ReadNumber(type);
+        if (bitfield_bit_size)
+        {
+            *bitfield_bit_size = size;
+            return ast_ctx.UnsignedIntTy; // FIXME: the spec is fairly vague here.
+        }
+        else
+            return clang::QualType();
+    }
+    
+    if (type.NextIf('r'))
+    {
+        clang::QualType target_type = BuildType(ast_ctx, type, allow_unknownanytype);
+        if (target_type.isNull())
+            return clang::QualType();
+        else if (target_type == ast_ctx.UnknownAnyTy)
+            return ast_ctx.UnknownAnyTy;
+        else
+            return ast_ctx.getConstType(target_type);
+    }
+    
+    if (type.NextIf('^'))
+    {
+        clang::QualType target_type = BuildType(ast_ctx, type, allow_unknownanytype);
+        if (target_type.isNull())
+            return clang::QualType();
+        else if (target_type == ast_ctx.UnknownAnyTy)
+            return ast_ctx.UnknownAnyTy;
+        else
+            return ast_ctx.getPointerType(target_type);
+    }
+    
+    if (type.NextIf('?'))
+        return allow_unknownanytype ? ast_ctx.UnknownAnyTy : clang::QualType();
+    
+    if (type.Peek() == '{')
+        return BuildStruct(ast_ctx, type, allow_unknownanytype);
+    
+    if (type.Peek() == '[')
+        return BuildArray(ast_ctx, type, allow_unknownanytype);
+    
+    if (type.Peek() == '(')
+        return BuildUnion(ast_ctx, type, allow_unknownanytype);
+    
+    return clang::QualType();
+}
+
+ClangASTType
+AppleObjCTypeEncodingParser::RealizeType (clang::ASTContext &ast_ctx, const char* name, bool allow_unknownanytype)
+{
+    if (name && name[0])
+    {
+        StringLexer lexer(name);
+        clang::QualType qual_type = BuildType(ast_ctx, lexer, allow_unknownanytype);
+        return ClangASTType(&ast_ctx, qual_type.getAsOpaquePtr());
+    }
+    return ClangASTType();
+}
+

Added: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h?rev=216026&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h (added)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h Tue Aug 19 16:46:37 2014
@@ -0,0 +1,78 @@
+//===-- AppleObjCTypeEncodingParser.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_AppleObjCTypeEncodingParser_h_
+#define liblldb_AppleObjCTypeEncodingParser_h_
+
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+#include "clang/AST/ASTContext.h"
+
+namespace lldb_utility {
+    class StringLexer;
+}
+
+namespace lldb_private {
+
+    class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType
+    {
+    public:
+        AppleObjCTypeEncodingParser (ObjCLanguageRuntime& runtime);
+        virtual ClangASTType RealizeType (clang::ASTContext &ast_ctx, const char* name, bool allow_unknownanytype);
+        virtual ~AppleObjCTypeEncodingParser() {}
+        
+    private:
+        struct StructElement {
+            std::string name;
+            clang::QualType type;
+            uint32_t bitfield;
+            
+            StructElement ();
+            ~StructElement () = default;
+        };
+        
+        clang::QualType
+        BuildType (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype, uint32_t *bitfield_bit_size = nullptr);
+
+        clang::QualType
+        BuildStruct (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype);
+        
+        clang::QualType
+        BuildAggregate (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype, char opener, char closer, uint kind);
+        
+        clang::QualType
+        BuildUnion (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype);
+        
+        clang::QualType
+        BuildArray (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype);
+        
+        std::string
+        ReadStructName(lldb_utility::StringLexer& type);
+        
+        StructElement
+        ReadStructElement (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool allow_unknownanytype);
+        
+        std::string
+        ReadStructElementName(lldb_utility::StringLexer& type);
+        
+        uint
+        ReadNumber (lldb_utility::StringLexer& type);
+
+    };
+    
+} // namespace lldb_private
+
+#endif  // liblldb_AppleObjCTypeEncodingParser_h_

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp Tue Aug 19 16:46:37 2014
@@ -164,7 +164,8 @@ private:
 AppleObjCTypeVendor::AppleObjCTypeVendor(ObjCLanguageRuntime &runtime) :
     TypeVendor(),
     m_runtime(runtime),
-    m_ast_ctx(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().getTriple().c_str())
+    m_ast_ctx(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()),
+    m_type_realizer_sp(m_runtime.GetEncodingToType())
 {
     m_external_source = new AppleObjCExternalASTSource (*this);
     llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr (m_external_source);
@@ -323,7 +324,7 @@ public:
         }
     }
     
-    clang::ObjCMethodDecl *BuildMethod (clang::ObjCInterfaceDecl *interface_decl, const char *name, bool instance)
+    clang::ObjCMethodDecl *BuildMethod (clang::ObjCInterfaceDecl *interface_decl, const char *name, bool instance, ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp)
     {
         if (!m_is_valid || m_type_vector.size() < 3)
             return NULL;
@@ -339,12 +340,14 @@ public:
         const bool isDefined = false;
         const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
         const bool HasRelatedResultType = false;
+        const bool allow_unknownanytype = true;
         
         std::vector <clang::IdentifierInfo *> selector_components;
         
         const char *name_cursor = name;
         bool is_zero_argument = true;
         
+        
         while (*name_cursor != '\0')
         {
             const char *colon_loc = strchr(name_cursor, ':');
@@ -363,7 +366,7 @@ public:
         
         clang::Selector sel = ast_ctx.Selectors.getSelector(is_zero_argument ? 0 : selector_components.size(), selector_components.data());
         
-        clang::QualType ret_type = BuildType(ast_ctx, m_type_vector[0].c_str());
+        clang::QualType ret_type = type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), allow_unknownanytype).GetQualType();
         
         if (ret_type.isNull())
             return NULL;
@@ -389,7 +392,8 @@ public:
              ai != ae;
              ++ai)
         {
-            clang::QualType arg_type = BuildType(ast_ctx, m_type_vector[ai].c_str());
+            const bool allow_unknownanytype = true;
+            clang::QualType arg_type = type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), allow_unknownanytype).GetQualType();
             
             if (arg_type.isNull())
                 return NULL; // well, we just wasted a bunch of time.  Wish we could delete the stuff we'd just made!
@@ -410,81 +414,6 @@ public:
         return ret;
     }
 private:
-    clang::QualType BuildType (clang::ASTContext &ast_ctx, const char *type)
-    {
-        if (!type)
-            return clang::QualType();
-        
-        switch (*type)
-        {
-        default:
-            return ast_ctx.UnknownAnyTy;
-        case 'r':
-            {
-                clang::QualType target_type = BuildType(ast_ctx, type+1);
-                if (target_type.isNull())
-                    return clang::QualType();
-                else if (target_type == ast_ctx.UnknownAnyTy)
-                    return ast_ctx.UnknownAnyTy;
-                else
-                    return ast_ctx.getConstType(target_type);
-            }
-        case '^':
-        {
-            clang::QualType target_type = BuildType(ast_ctx, type+1);
-            if (target_type.isNull())
-                return clang::QualType();
-            else if (target_type == ast_ctx.UnknownAnyTy)
-                return ast_ctx.UnknownAnyTy;
-            else
-                return ast_ctx.getPointerType(target_type);
-        }
-        case 'c':
-            return ast_ctx.CharTy;
-        case 'i':
-            return ast_ctx.IntTy;
-        case 's':
-            return ast_ctx.ShortTy;
-        case 'l':
-            if (ast_ctx.getTypeSize(ast_ctx.VoidTy) == 64)
-                return ast_ctx.IntTy;
-            else
-                return ast_ctx.LongTy;
-        case 'q':
-            return ast_ctx.LongLongTy;
-        case 'C':
-            return ast_ctx.UnsignedCharTy;
-        case 'I':
-            return ast_ctx.UnsignedIntTy;
-        case 'S':
-            return ast_ctx.UnsignedShortTy;
-        case 'L':
-            if (ast_ctx.getTypeSize(ast_ctx.VoidTy) == 64)
-                return ast_ctx.UnsignedIntTy;
-            else
-                return ast_ctx.UnsignedLongTy;
-        case 'Q':
-            return ast_ctx.UnsignedLongLongTy;
-        case 'f':
-            return ast_ctx.FloatTy;
-        case 'd':
-            return ast_ctx.DoubleTy;
-        case 'B':
-            return ast_ctx.BoolTy;
-        case 'v':
-            return ast_ctx.VoidTy;
-        case '*':
-            return ast_ctx.getPointerType(ast_ctx.CharTy);
-        case '@':
-            return ast_ctx.getObjCIdType();
-        case '#':
-            return ast_ctx.getObjCClassType();
-        case ':':
-            return ast_ctx.getObjCSelType();
-        }
-        return clang::QualType();
-    }
-    
     typedef std::vector <std::string> TypeVector;
     
     TypeVector  m_type_vector;
@@ -532,7 +461,7 @@ AppleObjCTypeVendor::FinishDecl(clang::O
 
         ObjCRuntimeMethodType method_type(types);
         
-        clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, true);
+        clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, true, m_type_realizer_sp);
         
         if (log)
             log->Printf("[  AOTV::FD] Instance method [%s] [%s]", name, types);
@@ -550,7 +479,7 @@ AppleObjCTypeVendor::FinishDecl(clang::O
         
         ObjCRuntimeMethodType method_type(types);
         
-        clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, false);
+        clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, false, m_type_realizer_sp);
         
         if (log)
             log->Printf("[  AOTV::FD] Class method [%s] [%s]", name, types);

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.h Tue Aug 19 16:46:37 2014
@@ -51,6 +51,7 @@ private:
     
     ObjCLanguageRuntime        &m_runtime;
     ClangASTContext             m_ast_ctx;
+    ObjCLanguageRuntime::EncodingToTypeSP m_type_realizer_sp;
     AppleObjCExternalASTSource *m_external_source;
     
     typedef llvm::DenseMap<ObjCLanguageRuntime::ObjCISA, clang::ObjCInterfaceDecl *> ISAToInterfaceMap;

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Tue Aug 19 16:46:37 2014
@@ -79,6 +79,16 @@ using namespace lldb_private;
 using namespace llvm;
 using namespace clang;
 
+typedef llvm::DenseMap<clang::ASTContext *, ClangASTContext*> ClangASTMap;
+
+static ClangASTMap &
+GetASTMap()
+{
+    static ClangASTMap g_map;
+    return g_map;
+}
+
+
 clang::AccessSpecifier
 ClangASTContext::ConvertAccessTypeToAccessSpecifier (AccessType access)
 {
@@ -291,6 +301,11 @@ ClangASTContext::ClangASTContext (const
 //----------------------------------------------------------------------
 ClangASTContext::~ClangASTContext()
 {
+    if (m_ast_ap.get())
+    {
+        GetASTMap().erase(m_ast_ap.get());
+    }
+
     m_builtins_ap.reset();
     m_selector_table_ap.reset();
     m_identifier_table_ap.reset();
@@ -393,10 +408,19 @@ ClangASTContext::getASTContext()
         }
         
         m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false);
+        
+        GetASTMap().insert(std::make_pair(m_ast_ap.get(), this));
     }
     return m_ast_ap.get();
 }
 
+ClangASTContext*
+ClangASTContext::GetASTContext (clang::ASTContext* ast)
+{
+    ClangASTContext *clang_ast = GetASTMap().lookup(ast);
+    return clang_ast;
+}
+
 Builtin::Context *
 ClangASTContext::getBuiltinContext()
 {

Modified: lldb/trunk/source/Target/ObjCLanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ObjCLanguageRuntime.cpp?rev=216026&r1=216025&r2=216026&view=diff
==============================================================================
--- lldb/trunk/source/Target/ObjCLanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Tue Aug 19 16:46:37 2014
@@ -602,4 +602,27 @@ ObjCLanguageRuntime::GetNonKVOClassDescr
 }
 
 
+ClangASTType
+ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool allow_unknownanytype)
+{
+    if (m_scratch_ast_ctx_ap)
+        return RealizeType(*m_scratch_ast_ctx_ap, name, allow_unknownanytype);
+    return ClangASTType();
+}
+
+ClangASTType
+ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool allow_unknownanytype)
+{
+    clang::ASTContext *clang_ast = ast_ctx.getASTContext();
+    if (!clang_ast)
+        return ClangASTType();
+    return RealizeType(*clang_ast, name, allow_unknownanytype);
+}
 
+ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
+
+ObjCLanguageRuntime::EncodingToTypeSP
+ObjCLanguageRuntime::GetEncodingToType ()
+{
+    return nullptr;
+}





More information about the lldb-commits mailing list