aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
new file mode 100644
index 000000000000..245f6da80c7f
--- /dev/null
+++ b/contrib/llvm/tools/lldb/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