diff options
Diffstat (limited to 'source/Plugins/Language/ObjC/NSIndexPath.cpp')
| -rw-r--r-- | source/Plugins/Language/ObjC/NSIndexPath.cpp | 349 | 
1 files changed, 349 insertions, 0 deletions
diff --git a/source/Plugins/Language/ObjC/NSIndexPath.cpp b/source/Plugins/Language/ObjC/NSIndexPath.cpp new file mode 100644 index 0000000000000..245f6da80c7f1 --- /dev/null +++ b/source/Plugins/Language/ObjC/NSIndexPath.cpp @@ -0,0 +1,349 @@ +//===-- NSIndexPath.cpp -----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "Cocoa.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: +    NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +    SyntheticChildrenFrontEnd (*valobj_sp.get()), +    m_ptr_size(0), +    m_uint_star_type() +    { +        m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize(); +    } + +    ~NSIndexPathSyntheticFrontEnd() override = default; + +    size_t +    CalculateNumChildren() override +    { +        return m_impl.GetNumIndexes(); +    } +     +    lldb::ValueObjectSP +    GetChildAtIndex(size_t idx) override +    { +        return m_impl.GetIndexAtIndex(idx, m_uint_star_type); +    } +     +    bool +    Update() override +    { +        m_impl.Clear(); +         +        TypeSystem* type_system = m_backend.GetCompilerType().GetTypeSystem(); +        if (!type_system) +            return false; + +        ClangASTContext *ast = m_backend.GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext(); +        if (!ast) +            return false; + +        m_uint_star_type = ast->GetPointerSizedIntType(false); +         +        static ConstString g__indexes("_indexes"); +        static ConstString g__length("_length"); + +        ProcessSP process_sp = m_backend.GetProcessSP(); +        if (!process_sp) +            return false; +         +        ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +         +        if (!runtime) +            return false; +         +        ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend)); +         +        if (!descriptor.get() || !descriptor->IsValid()) +            return false; +         +        uint64_t info_bits(0),value_bits(0),payload(0); +         +        if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) +        { +            m_impl.m_inlined.SetIndexes(payload, *process_sp); +            m_impl.m_mode = Mode::Inlined; +        } +        else +        { +            ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id; +            ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id; +             +            bool has_indexes(false),has_length(false); +             +            for (size_t x = 0; +                 x < descriptor->GetNumIVars(); +                 x++) +            { +                const auto& ivar = descriptor->GetIVarAtIndex(x); +                if (ivar.m_name == g__indexes) +                { +                    _indexes_id = ivar; +                    has_indexes = true; +                } +                else if (ivar.m_name == g__length) +                { +                    _length_id = ivar; +                    has_length = true; +                } +                 +                if (has_length && has_indexes) +                    break; +            } +             +            if (has_length && has_indexes) +            { +                m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset, +                                                                                    m_uint_star_type.GetPointerType(), +                                                                                    true).get(); +                ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset, +                                                                            m_uint_star_type, +                                                                            true)); +                if (length_sp) +                { +                    m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0); +                    if (m_impl.m_outsourced.m_indexes) +                        m_impl.m_mode = Mode::Outsourced; +                } +            } +        } +        return false; +    } +     +    bool +    MightHaveChildren() override +    { +        if (m_impl.m_mode == Mode::Invalid) +            return false; +        return true; +    } +     +    size_t +    GetIndexOfChildWithName(const ConstString &name) override +    { +        const char* item_name = name.GetCString(); +        uint32_t idx = ExtractIndexFromString(item_name); +        if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +            return UINT32_MAX; +        return idx; +    } +     +    lldb::ValueObjectSP +    GetSyntheticValue() override +    { +        return nullptr; +    } + +protected: +    ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp; +     +    enum class Mode { +        Inlined, +        Outsourced, +        Invalid +    }; +     +    struct Impl { +        Mode m_mode; + +        size_t +        GetNumIndexes () +        { +            switch (m_mode) +            { +                case Mode::Inlined: +                    return m_inlined.GetNumIndexes(); +                case Mode::Outsourced: +                    return m_outsourced.m_count; +                default: +                    return 0; +            } +        } +         +        lldb::ValueObjectSP +        GetIndexAtIndex (size_t idx, const CompilerType& desired_type) +        { +            if (idx >= GetNumIndexes()) +                return nullptr; +            switch (m_mode) +            { +                default: return nullptr; +                case Mode::Inlined: +                    return m_inlined.GetIndexAtIndex (idx, desired_type); +                case Mode::Outsourced: +                    return m_outsourced.GetIndexAtIndex (idx); +            } +        } + +        struct InlinedIndexes { +        public: +          void SetIndexes(uint64_t value, Process& p) +          { +              m_indexes = value; +              _lengthForInlinePayload(p.GetAddressByteSize()); +              m_process = &p; +          } +               +          size_t +          GetNumIndexes () +          { +              return m_count; +          } + +          lldb::ValueObjectSP +          GetIndexAtIndex (size_t idx, const CompilerType& desired_type) +          { +              std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx)); +              if (!value.second) +                  return nullptr; +               +              Value v; +              if (m_ptr_size == 8) +              { +                  Scalar scalar( (unsigned long long)value.first ); +                  v = Value(scalar); +              } +              else +              { +                  Scalar scalar( (unsigned int)value.first ); +                  v = Value(scalar); +              } + +              v.SetCompilerType(desired_type); + +              StreamString idx_name; +              idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); + +              return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData())); +          } +             +            void +            Clear () +            { +                m_indexes = 0; +                m_count = 0; +                m_ptr_size = 0; +                m_process = nullptr; +            } +                     +        private: +          uint64_t m_indexes; +          size_t m_count; +          uint32_t m_ptr_size; +          Process *m_process; +                     +          // cfr. Foundation for the details of this code +          size_t _lengthForInlinePayload(uint32_t ptr_size) { +              m_ptr_size = ptr_size; +              if (m_ptr_size == 8) +              m_count = ((m_indexes >> 3) & 0x7); +              else +              m_count = ((m_indexes >> 3) & 0x3); +              return m_count; +          } +                     +          std::pair<uint64_t, bool> +          _indexAtPositionForInlinePayload(size_t pos) +          { +              if (m_ptr_size == 8) +              { +                switch (pos) { +                    case 5: return {((m_indexes >> 51) & 0x1ff),true}; +                    case 4: return {((m_indexes >> 42) & 0x1ff),true}; +                    case 3: return {((m_indexes >> 33) & 0x1ff),true}; +                    case 2: return {((m_indexes >> 24) & 0x1ff),true}; +                    case 1: return {((m_indexes >> 15) & 0x1ff),true}; +                    case 0: return {((m_indexes >>  6) & 0x1ff),true}; +                } +              } +              else +                  { +                  switch (pos) { +                      case 2: return {((m_indexes >> 23) & 0x1ff),true}; +                      case 1: return {((m_indexes >> 14) & 0x1ff),true}; +                      case 0: return {((m_indexes >>  5) & 0x1ff),true}; +                  } +              } +              return {0,false}; +          } + +        }; +        struct OutsourcedIndexes { +            ValueObject *m_indexes; +            size_t m_count; +                     +            lldb::ValueObjectSP +            GetIndexAtIndex (size_t idx) +            { +                if (m_indexes) +                { +                    ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true)); +                    return index_sp; +                } +                return nullptr; +            } +             +            void +            Clear () +            { +                m_indexes = nullptr; +                m_count = 0; +            } +        }; + +        union { +            struct InlinedIndexes m_inlined; +            struct OutsourcedIndexes m_outsourced; +        }; +         +        void +        Clear () +        { +            m_mode = Mode::Invalid; +            m_inlined.Clear(); +            m_outsourced.Clear(); +        } +    } m_impl; +     +    uint32_t m_ptr_size; +    CompilerType m_uint_star_type; +}; + +namespace lldb_private { +    namespace formatters { +         +        SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +        { +            if (valobj_sp) +                return new NSIndexPathSyntheticFrontEnd(valobj_sp); +            return nullptr; +        } + +    } // namespace formatters +} // namespace lldb_private  | 
