blob: a07be9e4a7bfd570d15a99cc5474a841cf6b7918 [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"
20#include "lldb/Target/ObjCLanguageRuntime.h"
21#include "lldb/Target/Process.h"
22#include "lldb/Symbol/ClangASTContext.h"
23
24using namespace lldb;
25using namespace lldb_private;
26using namespace lldb_private::formatters;
27
28class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd
29{
30public:
31 NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
32 SyntheticChildrenFrontEnd (*valobj_sp.get()),
33 m_ptr_size(0),
Enrico Granata5510a572014-10-15 21:38:32 +000034 m_uint_star_type()
35 {
36 m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
37 }
Eugene Zelenko8d15f332015-10-20 01:10:59 +000038
39 ~NSIndexPathSyntheticFrontEnd() override = default;
40
41 size_t
42 CalculateNumChildren() override
Enrico Granata5510a572014-10-15 21:38:32 +000043 {
44 return m_impl.GetNumIndexes();
45 }
46
Eugene Zelenko8d15f332015-10-20 01:10:59 +000047 lldb::ValueObjectSP
48 GetChildAtIndex(size_t idx) override
Enrico Granata5510a572014-10-15 21:38:32 +000049 {
50 return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
51 }
52
Eugene Zelenko8d15f332015-10-20 01:10:59 +000053 bool
54 Update() override
Enrico Granata5510a572014-10-15 21:38:32 +000055 {
Enrico Granata7569f232015-06-16 20:48:49 +000056 m_impl.Clear();
Enrico Granata5510a572014-10-15 21:38:32 +000057
Greg Clayton99558cc42015-08-24 23:46:31 +000058 TypeSystem* type_system = m_backend.GetCompilerType().GetTypeSystem();
Greg Claytond8d4a572015-08-11 21:38:15 +000059 if (!type_system)
60 return false;
Greg Claytonf73034f2015-09-08 18:15:05 +000061
62 ClangASTContext *ast = m_backend.GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext();
63 if (!ast)
Enrico Granata5510a572014-10-15 21:38:32 +000064 return false;
Greg Claytonf73034f2015-09-08 18:15:05 +000065
66 m_uint_star_type = ast->GetPointerSizedIntType(false);
Enrico Granata5510a572014-10-15 21:38:32 +000067
68 static ConstString g__indexes("_indexes");
69 static ConstString g__length("_length");
70
71 ProcessSP process_sp = m_backend.GetProcessSP();
72 if (!process_sp)
73 return false;
74
75 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
76
77 if (!runtime)
78 return false;
79
80 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend));
81
82 if (!descriptor.get() || !descriptor->IsValid())
83 return false;
84
85 uint64_t info_bits(0),value_bits(0),payload(0);
86
87 if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
88 {
Enrico Granata5510a572014-10-15 21:38:32 +000089 m_impl.m_inlined.SetIndexes(payload, *process_sp);
Enrico Granata7569f232015-06-16 20:48:49 +000090 m_impl.m_mode = Mode::Inlined;
Enrico Granata5510a572014-10-15 21:38:32 +000091 }
92 else
93 {
94 ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id;
95 ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id;
96
97 bool has_indexes(false),has_length(false);
98
Zachary Turner225cc302015-01-09 20:15:03 +000099 for (size_t x = 0;
Enrico Granata5510a572014-10-15 21:38:32 +0000100 x < descriptor->GetNumIVars();
101 x++)
102 {
103 const auto& ivar = descriptor->GetIVarAtIndex(x);
104 if (ivar.m_name == g__indexes)
105 {
106 _indexes_id = ivar;
107 has_indexes = true;
108 }
109 else if (ivar.m_name == g__length)
110 {
111 _length_id = ivar;
112 has_length = true;
113 }
114
115 if (has_length && has_indexes)
116 break;
117 }
118
119 if (has_length && has_indexes)
120 {
121 m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset,
122 m_uint_star_type.GetPointerType(),
123 true).get();
124 ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset,
125 m_uint_star_type,
126 true));
127 if (length_sp)
128 {
129 m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
130 if (m_impl.m_outsourced.m_indexes)
131 m_impl.m_mode = Mode::Outsourced;
132 }
133 }
134 }
135 return false;
136 }
137
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000138 bool
139 MightHaveChildren() override
Enrico Granata5510a572014-10-15 21:38:32 +0000140 {
141 if (m_impl.m_mode == Mode::Invalid)
142 return false;
143 return true;
144 }
145
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000146 size_t
147 GetIndexOfChildWithName(const ConstString &name) override
Enrico Granata5510a572014-10-15 21:38:32 +0000148 {
149 const char* item_name = name.GetCString();
150 uint32_t idx = ExtractIndexFromString(item_name);
151 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
152 return UINT32_MAX;
153 return idx;
154 }
155
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000156 lldb::ValueObjectSP
157 GetSyntheticValue() override
158 {
159 return nullptr;
160 }
161
Enrico Granata5510a572014-10-15 21:38:32 +0000162protected:
163 ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
164
165 enum class Mode {
166 Inlined,
167 Outsourced,
168 Invalid
169 };
170
171 struct Impl {
172 Mode m_mode;
173
174 size_t
175 GetNumIndexes ()
176 {
177 switch (m_mode)
178 {
179 case Mode::Inlined:
180 return m_inlined.GetNumIndexes();
181 case Mode::Outsourced:
182 return m_outsourced.m_count;
183 default:
184 return 0;
185 }
186 }
187
188 lldb::ValueObjectSP
Greg Claytona1e5dc82015-08-11 22:53:00 +0000189 GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
Enrico Granata5510a572014-10-15 21:38:32 +0000190 {
191 if (idx >= GetNumIndexes())
192 return nullptr;
193 switch (m_mode)
194 {
195 default: return nullptr;
196 case Mode::Inlined:
197 return m_inlined.GetIndexAtIndex (idx, desired_type);
198 case Mode::Outsourced:
199 return m_outsourced.GetIndexAtIndex (idx);
200 }
201 }
Enrico Granata5510a572014-10-15 21:38:32 +0000202
Eric Christopher098f8982014-10-21 20:39:34 +0000203 struct InlinedIndexes {
Enrico Granata7569f232015-06-16 20:48:49 +0000204 public:
205 void SetIndexes(uint64_t value, Process& p)
206 {
207 m_indexes = value;
208 _lengthForInlinePayload(p.GetAddressByteSize());
209 m_process = &p;
210 }
211
212 size_t
213 GetNumIndexes ()
214 {
215 return m_count;
216 }
Eric Christopher098f8982014-10-21 20:39:34 +0000217
Enrico Granata7569f232015-06-16 20:48:49 +0000218 lldb::ValueObjectSP
Greg Claytona1e5dc82015-08-11 22:53:00 +0000219 GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
Enrico Granata7569f232015-06-16 20:48:49 +0000220 {
221 std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
222 if (!value.second)
223 return nullptr;
224
225 Value v;
226 if (m_ptr_size == 8)
227 {
228 Scalar scalar( (unsigned long long)value.first );
229 v = Value(scalar);
230 }
231 else
232 {
233 Scalar scalar( (unsigned int)value.first );
234 v = Value(scalar);
235 }
236
Greg Clayton99558cc42015-08-24 23:46:31 +0000237 v.SetCompilerType(desired_type);
Enrico Granata7569f232015-06-16 20:48:49 +0000238
239 StreamString idx_name;
240 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
241
242 return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
243 }
244
245 void
246 Clear ()
247 {
248 m_indexes = 0;
249 m_count = 0;
250 m_ptr_size = 0;
251 m_process = nullptr;
252 }
253
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000254 private:
Enrico Granata7569f232015-06-16 20:48:49 +0000255 uint64_t m_indexes;
256 size_t m_count;
257 uint32_t m_ptr_size;
258 Process *m_process;
259
260 // cfr. Foundation for the details of this code
261 size_t _lengthForInlinePayload(uint32_t ptr_size) {
262 m_ptr_size = ptr_size;
263 if (m_ptr_size == 8)
264 m_count = ((m_indexes >> 3) & 0x7);
265 else
266 m_count = ((m_indexes >> 3) & 0x3);
267 return m_count;
268 }
269
270 std::pair<uint64_t, bool>
271 _indexAtPositionForInlinePayload(size_t pos)
272 {
273 if (m_ptr_size == 8)
274 {
275 switch (pos) {
276 case 5: return {((m_indexes >> 51) & 0x1ff),true};
277 case 4: return {((m_indexes >> 42) & 0x1ff),true};
278 case 3: return {((m_indexes >> 33) & 0x1ff),true};
279 case 2: return {((m_indexes >> 24) & 0x1ff),true};
280 case 1: return {((m_indexes >> 15) & 0x1ff),true};
281 case 0: return {((m_indexes >> 6) & 0x1ff),true};
282 }
283 }
284 else
285 {
286 switch (pos) {
287 case 2: return {((m_indexes >> 23) & 0x1ff),true};
288 case 1: return {((m_indexes >> 14) & 0x1ff),true};
289 case 0: return {((m_indexes >> 5) & 0x1ff),true};
290 }
291 }
292 return {0,false};
293 }
294
295 };
Eric Christopher098f8982014-10-21 20:39:34 +0000296 struct OutsourcedIndexes {
Enrico Granata7569f232015-06-16 20:48:49 +0000297 ValueObject *m_indexes;
298 size_t m_count;
299
300 lldb::ValueObjectSP
301 GetIndexAtIndex (size_t idx)
302 {
303 if (m_indexes)
304 {
305 ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true));
306 return index_sp;
307 }
308 return nullptr;
309 }
310
311 void
312 Clear ()
313 {
314 m_indexes = nullptr;
315 m_count = 0;
316 }
317 };
Eric Christopher098f8982014-10-21 20:39:34 +0000318
319 union {
Enrico Granata7569f232015-06-16 20:48:49 +0000320 struct InlinedIndexes m_inlined;
321 struct OutsourcedIndexes m_outsourced;
Enrico Granata5510a572014-10-15 21:38:32 +0000322 };
Enrico Granata7569f232015-06-16 20:48:49 +0000323
324 void
325 Clear ()
326 {
327 m_mode = Mode::Invalid;
328 m_inlined.Clear();
329 m_outsourced.Clear();
330 }
Enrico Granata5510a572014-10-15 21:38:32 +0000331 } m_impl;
332
333 uint32_t m_ptr_size;
Greg Claytona1e5dc82015-08-11 22:53:00 +0000334 CompilerType m_uint_star_type;
Enrico Granata5510a572014-10-15 21:38:32 +0000335};
336
337namespace lldb_private {
338 namespace formatters {
339
340 SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
341 {
342 if (valobj_sp)
343 return new NSIndexPathSyntheticFrontEnd(valobj_sp);
344 return nullptr;
345 }
Eugene Zelenko8d15f332015-10-20 01:10:59 +0000346
347 } // namespace formatters
348} // namespace lldb_private