aboutsummaryrefslogtreecommitdiff
path: root/source/DataFormatters/NSIndexPath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/DataFormatters/NSIndexPath.cpp')
-rw-r--r--source/DataFormatters/NSIndexPath.cpp309
1 files changed, 309 insertions, 0 deletions
diff --git a/source/DataFormatters/NSIndexPath.cpp b/source/DataFormatters/NSIndexPath.cpp
new file mode 100644
index 000000000000..ee9583ef4cc1
--- /dev/null
+++ b/source/DataFormatters/NSIndexPath.cpp
@@ -0,0 +1,309 @@
+//===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Symbol/ClangASTContext.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_ast_ctx(nullptr),
+ m_uint_star_type()
+ {
+ m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
+ }
+
+ virtual size_t
+ CalculateNumChildren ()
+ {
+ return m_impl.GetNumIndexes();
+ }
+
+ virtual lldb::ValueObjectSP
+ GetChildAtIndex (size_t idx)
+ {
+ return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
+ }
+
+ virtual bool
+ Update()
+ {
+ m_impl.m_mode = Mode::Invalid;
+
+ m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext());
+ if (!m_ast_ctx)
+ return false;
+
+ m_uint_star_type = m_ast_ctx->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_mode = Mode::Inlined;
+ m_impl.m_inlined.SetIndexes(payload, *process_sp);
+ }
+ 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;
+ }
+
+ virtual bool
+ MightHaveChildren ()
+ {
+ if (m_impl.m_mode == Mode::Invalid)
+ return false;
+ return true;
+ }
+
+ virtual size_t
+ GetIndexOfChildWithName (const ConstString &name)
+ {
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+ }
+
+ virtual lldb::ValueObjectSP
+ GetSyntheticValue () { return nullptr; }
+
+ virtual
+ ~NSIndexPathSyntheticFrontEnd () {}
+
+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 ClangASTType& 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 ClangASTType& 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.SetClangType(desired_type);
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
+ }
+
+ 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->GetSyntheticArrayMemberFromPointer(idx, true));
+ return index_sp;
+ }
+ return nullptr;
+ }
+ };
+
+ union {
+ struct InlinedIndexes m_inlined;
+ struct OutsourcedIndexes m_outsourced;
+ };
+ } m_impl;
+
+ uint32_t m_ptr_size;
+ ClangASTContext* m_ast_ctx;
+ ClangASTType 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;
+ }
+ }
+}