1 //===-- NSIndexPath.cpp -----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
16 #include "lldb/Core/ValueObject.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/DataFormatters/FormattersHelpers.h"
19 #include "lldb/DataFormatters/TypeSynthetic.h"
20 #include "lldb/Symbol/ClangASTContext.h"
21 #include "lldb/Target/ObjCLanguageRuntime.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Target.h"
26 using namespace lldb_private;
27 using namespace lldb_private::formatters;
29 static constexpr size_t PACKED_INDEX_SHIFT_64(size_t i) {
30 return (60 - (13 * (4 - i)));
33 static constexpr size_t PACKED_INDEX_SHIFT_32(size_t i) {
34 return (32 - (13 * (2 - i)));
37 class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
39 NSIndexPathSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
40 : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_descriptor_sp(nullptr),
41 m_impl(), m_ptr_size(0), m_uint_star_type() {
43 m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
46 ~NSIndexPathSyntheticFrontEnd() override = default;
48 size_t CalculateNumChildren() override { return m_impl.GetNumIndexes(); }
50 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
51 return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
54 bool Update() override {
57 TypeSystem *type_system = m_backend.GetCompilerType().GetTypeSystem();
61 ClangASTContext *ast = m_backend.GetExecutionContextRef()
63 ->GetScratchClangASTContext();
67 m_uint_star_type = ast->GetPointerSizedIntType(false);
69 static ConstString g__indexes("_indexes");
70 static ConstString g__length("_length");
72 ProcessSP process_sp = m_backend.GetProcessSP();
76 ObjCLanguageRuntime *runtime =
77 (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime(
78 lldb::eLanguageTypeObjC);
83 ObjCLanguageRuntime::ClassDescriptorSP descriptor(
84 runtime->GetClassDescriptor(m_backend));
86 if (!descriptor.get() || !descriptor->IsValid())
89 uint64_t info_bits(0), value_bits(0), payload(0);
91 if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) {
92 m_impl.m_inlined.SetIndexes(payload, *process_sp);
93 m_impl.m_mode = Mode::Inlined;
95 ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id;
96 ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id;
98 bool has_indexes(false), has_length(false);
100 for (size_t x = 0; x < descriptor->GetNumIVars(); x++) {
101 const auto &ivar = descriptor->GetIVarAtIndex(x);
102 if (ivar.m_name == g__indexes) {
105 } else if (ivar.m_name == g__length) {
110 if (has_length && has_indexes)
114 if (has_length && has_indexes) {
115 m_impl.m_outsourced.m_indexes =
117 .GetSyntheticChildAtOffset(_indexes_id.m_offset,
118 m_uint_star_type.GetPointerType(),
121 ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(
122 _length_id.m_offset, m_uint_star_type, true));
124 m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
125 if (m_impl.m_outsourced.m_indexes)
126 m_impl.m_mode = Mode::Outsourced;
133 bool MightHaveChildren() override {
134 if (m_impl.m_mode == Mode::Invalid)
139 size_t GetIndexOfChildWithName(const ConstString &name) override {
140 const char *item_name = name.GetCString();
141 uint32_t idx = ExtractIndexFromString(item_name);
142 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
147 lldb::ValueObjectSP GetSyntheticValue() override { return nullptr; }
150 ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
152 enum class Mode { Inlined, Outsourced, Invalid };
155 size_t GetNumIndexes() {
158 return m_inlined.GetNumIndexes();
159 case Mode::Outsourced:
160 return m_outsourced.m_count;
166 lldb::ValueObjectSP GetIndexAtIndex(size_t idx,
167 const CompilerType &desired_type) {
168 if (idx >= GetNumIndexes())
174 return m_inlined.GetIndexAtIndex(idx, desired_type);
175 case Mode::Outsourced:
176 return m_outsourced.GetIndexAtIndex(idx);
180 struct InlinedIndexes {
182 void SetIndexes(uint64_t value, Process &p) {
184 _lengthForInlinePayload(p.GetAddressByteSize());
188 size_t GetNumIndexes() { return m_count; }
190 lldb::ValueObjectSP GetIndexAtIndex(size_t idx,
191 const CompilerType &desired_type) {
195 std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
200 if (m_ptr_size == 8) {
201 Scalar scalar((unsigned long long)value.first);
204 Scalar scalar((unsigned int)value.first);
208 v.SetCompilerType(desired_type);
210 StreamString idx_name;
211 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
213 return ValueObjectConstResult::Create(
214 m_process, v, ConstString(idx_name.GetString()));
225 : m_indexes(0), m_count(0), m_ptr_size(0), m_process(nullptr) {}
233 // cfr. Foundation for the details of this code
234 size_t _lengthForInlinePayload(uint32_t ptr_size) {
235 m_ptr_size = ptr_size;
237 m_count = ((m_indexes >> 3) & 0x7);
239 m_count = ((m_indexes >> 3) & 0x3);
243 std::pair<uint64_t, bool> _indexAtPositionForInlinePayload(size_t pos) {
244 static const uint64_t PACKED_INDEX_MASK = ((1 << 13) - 1);
245 if (m_ptr_size == 8) {
251 return {(m_indexes >> PACKED_INDEX_SHIFT_64(pos)) &
261 return {(m_indexes >> PACKED_INDEX_SHIFT_32(pos)) &
272 struct OutsourcedIndexes {
273 lldb::ValueObjectSP GetIndexAtIndex(size_t idx) {
275 ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true));
286 OutsourcedIndexes() : m_indexes(nullptr), m_count(0) {}
288 ValueObject *m_indexes;
293 struct InlinedIndexes m_inlined;
294 struct OutsourcedIndexes m_outsourced;
298 m_mode = Mode::Invalid;
300 m_outsourced.Clear();
303 Impl() : m_mode(Mode::Invalid) {}
309 CompilerType m_uint_star_type;
312 namespace lldb_private {
313 namespace formatters {
315 SyntheticChildrenFrontEnd *
316 NSIndexPathSyntheticFrontEndCreator(CXXSyntheticChildren *,
317 lldb::ValueObjectSP valobj_sp) {
319 return new NSIndexPathSyntheticFrontEnd(valobj_sp);
323 } // namespace formatters
324 } // namespace lldb_private