blob: 245f6da80c7f17e3078873516c403c8c2f9b2411 [file] [log] [blame]
Eugene Zelenko8d15f332015-10-20 01:10:59 +00001//===-- NSIndexPath.cpp -----------------------------------------*- C++ -*-===//
Enrico Granata5510a572014-10-15 21:38:32 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenko8d15f332015-10-20 01:10:59 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Enrico Granata170c3952015-09-14 22:18:32 +000014#include "Cocoa.h"
Enrico Granata5510a572014-10-15 21:38:32 +000015
16#include "lldb/Core/ValueObject.h"
17#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000018#include "lldb/DataFormatters/FormattersHelpers.h"
Enrico Granata5510a572014-10-15 21:38:32 +000019#include "lldb/DataFormatters/TypeSynthetic.h"
Enrico Granatad717cc92015-10-20 04:50:09 +000020#include "lldb/Symbol/ClangASTContext.h"
Enrico Granata5510a572014-10-15 21:38:32 +000021#include "lldb/Target/ObjCLanguageRuntime.h"
22#include "lldb/Target/Process.h"
Enrico Granatad717cc92015-10-20 04:50:09 +000023#include "lldb/Target/Target.h"
Enrico Granata5510a572014-10-15 21:38:32 +000024
25using namespace lldb;
26using namespace lldb_private;
27using namespace lldb_private::formatters;
28
29class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd
30{
31public:
32 NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
33 SyntheticChildrenFrontEnd (*valobj_sp.get()),
34 m_ptr_size(0),
Enrico Granata5510a572014-10-15 21:38:32 +000035 m_uint_star_type()
36 {
37 m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
38 }
Eugene Zelenko8d15f332015-10-20 01:10:59 +000039
40 ~NSIndexPathSyntheticFrontEnd() override = default;
41
42 size_t
43 CalculateNumChildren() override
Enrico Granata5510a572014-10-15 21:38:32 +000044 {
45 return m_impl.GetNumIndexes();
46 }
47
Eugene Zelenko8d15f332015-10-20 01:10:59 +000048 lldb::ValueObjectSP
49 GetChildAtIndex(size_t idx) override
Enrico Granata5510a572014-10-15 21:38:32 +000050 {
51 return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
52 }
53
Eugene Zelenko8d15f332015-10-20 01:10:59 +000054 bool
55 Update() override
Enrico Granata5510a572014-10-15 21:38:32 +000056 {
Enrico Granata7569f232015-06-16 20:48:49 +000057 m_impl.Clear();
Enrico Granata5510a572014-10-15 21:38:32 +000058
Greg Clayton99558cc42015-08-24 23:46:31 +000059 TypeSystem* type_system = m_backend.GetCompilerType().GetTypeSystem();
Greg Claytond8d4a572015-08-11 21:38:15 +000060 if (!type_system)
61 return false;
Greg Claytonf73034f2015-09-08 18:15:05 +000062
63 ClangASTContext *ast = m_backend.GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext();
64 if (!ast)
Enrico Granata5510a572014-10-15 21:38:32 +000065 return false;
Greg Claytonf73034f2015-09-08 18:15:05 +000066
67 m_uint_star_type = ast->GetPointerSizedIntType(false);
Enrico Granata5510a572014-10-15 21:38:32 +000068
69 static ConstString g__indexes("_indexes");
70 static ConstString g__length("_length");
71
72 ProcessSP process_sp = m_backend.GetProcessSP();
73 if (!process_sp)
74 return false;
75
76 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
77
78 if (!runtime)
79 return false;
80
81 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend));
82
83 if (!descriptor.get() || !descriptor->IsValid())
84 return false;
85
86 uint64_t info_bits(0),value_bits(0),payload(0);
87
88 if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
89 {
Enrico Granata5510a572014-10-15 21:38:32 +000090 m_impl.m_inlined.SetIndexes(payload, *process_sp);
Enrico Granata7569f232015-06-16 20:48:49 +000091 m_impl.m_mode = Mode::Inlined;
Enrico Granata5510a572014-10-15 21:38:32 +000092 }
93 else
94 {
95 ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id;
96 ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id;
97
98 bool has_indexes(false),has_length(false);
99
Zachary Turner225cc302015-01-09 20:15:03 +0000100 for (size_t x = 0;
Enrico Granata5510a572014-10-15 21:38:32 +0000101 x < descriptor->GetNumIVars();
102 x++)
103 {
104 const auto& ivar = descriptor->GetIVarAtIndex(x);
105 if (ivar.m_name == g__indexes)
106 {
107 _indexes_id = ivar;
108 has_indexes = true;
109 }
110 else if (ivar.m_name == g__length)
111 {
112 _length_id = ivar;
113 has_length = true;
114 }
115
116 if (has_length && has_indexes)
117 break;
118 }
119
120 if (has_length && has_indexes)
121 {
122 m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset,
123 m_uint_star_type.GetPointerType(),
124 true).get();
125 ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset,
126 m_uint_star_type,
127 true));
128 if (length_sp)
129 {
130 m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
131 if (m_impl.m_outsourced.m_indexes)
132 m_impl.m_mode = Mode::Outsourced;
133 }
134 }
135 }
136 return false;
137 }
138
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000139 bool
140 MightHaveChildren() override
Enrico Granata5510a572014-10-15 21:38:32 +0000141 {
142 if (m_impl.m_mode == Mode::Invalid)
143 return false;
144 return true;
145 }
146
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000147 size_t
148 GetIndexOfChildWithName(const ConstString &name) override
Enrico Granata5510a572014-10-15 21:38:32 +0000149 {
150 const char* item_name = name.GetCString();
151 uint32_t idx = ExtractIndexFromString(item_name);
152 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
153 return UINT32_MAX;
154 return idx;
155 }
156
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000157 lldb::ValueObjectSP
158 GetSyntheticValue() override
159 {
160 return nullptr;
161 }
162
Enrico Granata5510a572014-10-15 21:38:32 +0000163protected:
164 ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
165
166 enum class Mode {
167 Inlined,
168 Outsourced,
169 Invalid
170 };
171
172 struct Impl {
173 Mode m_mode;
174
175 size_t
176 GetNumIndexes ()
177 {
178 switch (m_mode)
179 {
180 case Mode::Inlined:
181 return m_inlined.GetNumIndexes();
182 case Mode::Outsourced:
183 return m_outsourced.m_count;
184 default:
185 return 0;
186 }
187 }
188
189 lldb::ValueObjectSP
Greg Claytona1e5dc82015-08-11 22:53:00 +0000190 GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
Enrico Granata5510a572014-10-15 21:38:32 +0000191 {
192 if (idx >= GetNumIndexes())
193 return nullptr;
194 switch (m_mode)
195 {
196 default: return nullptr;
197 case Mode::Inlined:
198 return m_inlined.GetIndexAtIndex (idx, desired_type);
199 case Mode::Outsourced:
200 return m_outsourced.GetIndexAtIndex (idx);
201 }
202 }
Enrico Granata5510a572014-10-15 21:38:32 +0000203
Eric Christopher098f8982014-10-21 20:39:34 +0000204 struct InlinedIndexes {
Enrico Granata7569f232015-06-16 20:48:49 +0000205 public:
206 void SetIndexes(uint64_t value, Process& p)
207 {
208 m_indexes = value;
209 _lengthForInlinePayload(p.GetAddressByteSize());
210 m_process = &p;
211 }
212
213 size_t
214 GetNumIndexes ()
215 {
216 return m_count;
217 }
Eric Christopher098f8982014-10-21 20:39:34 +0000218
Enrico Granata7569f232015-06-16 20:48:49 +0000219 lldb::ValueObjectSP
Greg Claytona1e5dc82015-08-11 22:53:00 +0000220 GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
Enrico Granata7569f232015-06-16 20:48:49 +0000221 {
222 std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
223 if (!value.second)
224 return nullptr;
225
226 Value v;
227 if (m_ptr_size == 8)
228 {
229 Scalar scalar( (unsigned long long)value.first );
230 v = Value(scalar);
231 }
232 else
233 {
234 Scalar scalar( (unsigned int)value.first );
235 v = Value(scalar);
236 }
237
Greg Clayton99558cc42015-08-24 23:46:31 +0000238 v.SetCompilerType(desired_type);
Enrico Granata7569f232015-06-16 20:48:49 +0000239
240 StreamString idx_name;
241 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
242
243 return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
244 }
245
246 void
247 Clear ()
248 {
249 m_indexes = 0;
250 m_count = 0;
251 m_ptr_size = 0;
252 m_process = nullptr;
253 }
254
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000255 private:
Enrico Granata7569f232015-06-16 20:48:49 +0000256 uint64_t m_indexes;
257 size_t m_count;
258 uint32_t m_ptr_size;
259 Process *m_process;
260
261 // cfr. Foundation for the details of this code
262 size_t _lengthForInlinePayload(uint32_t ptr_size) {
263 m_ptr_size = ptr_size;
264 if (m_ptr_size == 8)
265 m_count = ((m_indexes >> 3) & 0x7);
266 else
267 m_count = ((m_indexes >> 3) & 0x3);
268 return m_count;
269 }
270
271 std::pair<uint64_t, bool>
272 _indexAtPositionForInlinePayload(size_t pos)
273 {
274 if (m_ptr_size == 8)
275 {
276 switch (pos) {
277 case 5: return {((m_indexes >> 51) & 0x1ff),true};
278 case 4: return {((m_indexes >> 42) & 0x1ff),true};
279 case 3: return {((m_indexes >> 33) & 0x1ff),true};
280 case 2: return {((m_indexes >> 24) & 0x1ff),true};
281 case 1: return {((m_indexes >> 15) & 0x1ff),true};
282 case 0: return {((m_indexes >> 6) & 0x1ff),true};
283 }
284 }
285 else
286 {
287 switch (pos) {
288 case 2: return {((m_indexes >> 23) & 0x1ff),true};
289 case 1: return {((m_indexes >> 14) & 0x1ff),true};
290 case 0: return {((m_indexes >> 5) & 0x1ff),true};
291 }
292 }
293 return {0,false};
294 }
295
296 };
Eric Christopher098f8982014-10-21 20:39:34 +0000297 struct OutsourcedIndexes {
Enrico Granata7569f232015-06-16 20:48:49 +0000298 ValueObject *m_indexes;
299 size_t m_count;
300
301 lldb::ValueObjectSP
302 GetIndexAtIndex (size_t idx)
303 {
304 if (m_indexes)
305 {
306 ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true));
307 return index_sp;
308 }
309 return nullptr;
310 }
311
312 void
313 Clear ()
314 {
315 m_indexes = nullptr;
316 m_count = 0;
317 }
318 };
Eric Christopher098f8982014-10-21 20:39:34 +0000319
320 union {
Enrico Granata7569f232015-06-16 20:48:49 +0000321 struct InlinedIndexes m_inlined;
322 struct OutsourcedIndexes m_outsourced;
Enrico Granata5510a572014-10-15 21:38:32 +0000323 };
Enrico Granata7569f232015-06-16 20:48:49 +0000324
325 void
326 Clear ()
327 {
328 m_mode = Mode::Invalid;
329 m_inlined.Clear();
330 m_outsourced.Clear();
331 }
Enrico Granata5510a572014-10-15 21:38:32 +0000332 } m_impl;
333
334 uint32_t m_ptr_size;
Greg Claytona1e5dc82015-08-11 22:53:00 +0000335 CompilerType m_uint_star_type;
Enrico Granata5510a572014-10-15 21:38:32 +0000336};
337
338namespace lldb_private {
339 namespace formatters {
340
341 SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
342 {
343 if (valobj_sp)
344 return new NSIndexPathSyntheticFrontEnd(valobj_sp);
345 return nullptr;
346 }
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000347
348 } // namespace formatters
349} // namespace lldb_private