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 //===----------------------------------------------------------------------===//
10 #include "lldb/DataFormatters/CXXFormatterFunctions.h"
12 #include "lldb/Core/ValueObject.h"
13 #include "lldb/Core/ValueObjectConstResult.h"
14 #include "lldb/DataFormatters/TypeSynthetic.h"
15 #include "lldb/Target/ObjCLanguageRuntime.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Symbol/ClangASTContext.h"
20 using namespace lldb_private;
21 using namespace lldb_private::formatters;
23 class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd
26 NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
27 SyntheticChildrenFrontEnd (*valobj_sp.get()),
32 m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
36 CalculateNumChildren ()
38 return m_impl.GetNumIndexes();
41 virtual lldb::ValueObjectSP
42 GetChildAtIndex (size_t idx)
44 return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
52 m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext());
56 m_uint_star_type = m_ast_ctx->GetPointerSizedIntType(false);
58 static ConstString g__indexes("_indexes");
59 static ConstString g__length("_length");
61 ProcessSP process_sp = m_backend.GetProcessSP();
65 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
70 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend));
72 if (!descriptor.get() || !descriptor->IsValid())
75 uint64_t info_bits(0),value_bits(0),payload(0);
77 if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
79 m_impl.m_inlined.SetIndexes(payload, *process_sp);
80 m_impl.m_mode = Mode::Inlined;
84 ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id;
85 ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id;
87 bool has_indexes(false),has_length(false);
90 x < descriptor->GetNumIVars();
93 const auto& ivar = descriptor->GetIVarAtIndex(x);
94 if (ivar.m_name == g__indexes)
99 else if (ivar.m_name == g__length)
105 if (has_length && has_indexes)
109 if (has_length && has_indexes)
111 m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset,
112 m_uint_star_type.GetPointerType(),
114 ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset,
119 m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
120 if (m_impl.m_outsourced.m_indexes)
121 m_impl.m_mode = Mode::Outsourced;
131 if (m_impl.m_mode == Mode::Invalid)
137 GetIndexOfChildWithName (const ConstString &name)
139 const char* item_name = name.GetCString();
140 uint32_t idx = ExtractIndexFromString(item_name);
141 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
146 virtual lldb::ValueObjectSP
147 GetSyntheticValue () { return nullptr; }
150 ~NSIndexPathSyntheticFrontEnd () {}
153 ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
170 return m_inlined.GetNumIndexes();
171 case Mode::Outsourced:
172 return m_outsourced.m_count;
179 GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
181 if (idx >= GetNumIndexes())
185 default: return nullptr;
187 return m_inlined.GetIndexAtIndex (idx, desired_type);
188 case Mode::Outsourced:
189 return m_outsourced.GetIndexAtIndex (idx);
193 struct InlinedIndexes {
195 void SetIndexes(uint64_t value, Process& p)
198 _lengthForInlinePayload(p.GetAddressByteSize());
209 GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
211 std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
218 Scalar scalar( (unsigned long long)value.first );
223 Scalar scalar( (unsigned int)value.first );
227 v.SetClangType(desired_type);
229 StreamString idx_name;
230 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
232 return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
250 // cfr. Foundation for the details of this code
251 size_t _lengthForInlinePayload(uint32_t ptr_size) {
252 m_ptr_size = ptr_size;
254 m_count = ((m_indexes >> 3) & 0x7);
256 m_count = ((m_indexes >> 3) & 0x3);
260 std::pair<uint64_t, bool>
261 _indexAtPositionForInlinePayload(size_t pos)
266 case 5: return {((m_indexes >> 51) & 0x1ff),true};
267 case 4: return {((m_indexes >> 42) & 0x1ff),true};
268 case 3: return {((m_indexes >> 33) & 0x1ff),true};
269 case 2: return {((m_indexes >> 24) & 0x1ff),true};
270 case 1: return {((m_indexes >> 15) & 0x1ff),true};
271 case 0: return {((m_indexes >> 6) & 0x1ff),true};
277 case 2: return {((m_indexes >> 23) & 0x1ff),true};
278 case 1: return {((m_indexes >> 14) & 0x1ff),true};
279 case 0: return {((m_indexes >> 5) & 0x1ff),true};
286 struct OutsourcedIndexes {
287 ValueObject *m_indexes;
291 GetIndexAtIndex (size_t idx)
295 ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true));
310 struct InlinedIndexes m_inlined;
311 struct OutsourcedIndexes m_outsourced;
317 m_mode = Mode::Invalid;
319 m_outsourced.Clear();
324 ClangASTContext* m_ast_ctx;
325 ClangASTType m_uint_star_type;
328 namespace lldb_private {
329 namespace formatters {
331 SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
334 return new NSIndexPathSyntheticFrontEnd(valobj_sp);