1170c395eSEnrico Granata //===-- NSArray.cpp ---------------------------------------------*- C++ -*-===//
2170c395eSEnrico Granata //
3170c395eSEnrico Granata //                     The LLVM Compiler Infrastructure
4170c395eSEnrico Granata //
5170c395eSEnrico Granata // This file is distributed under the University of Illinois Open Source
6170c395eSEnrico Granata // License. See LICENSE.TXT for details.
7170c395eSEnrico Granata //
8170c395eSEnrico Granata //===----------------------------------------------------------------------===//
9170c395eSEnrico Granata 
108d15f33bSEugene Zelenko // C Includes
118d15f33bSEugene Zelenko // C++ Includes
128d15f33bSEugene Zelenko // Other libraries and framework includes
138d15f33bSEugene Zelenko #include "clang/AST/ASTContext.h"
148d15f33bSEugene Zelenko 
158d15f33bSEugene Zelenko // Project includes
16170c395eSEnrico Granata #include "Cocoa.h"
17170c395eSEnrico Granata 
18b9c1b51eSKate Stone #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
19170c395eSEnrico Granata #include "lldb/Core/ValueObject.h"
20170c395eSEnrico Granata #include "lldb/Core/ValueObjectConstResult.h"
21170c395eSEnrico Granata #include "lldb/DataFormatters/FormattersHelpers.h"
22151c032cSJim Ingham #include "lldb/Expression/FunctionCaller.h"
23170c395eSEnrico Granata #include "lldb/Symbol/ClangASTContext.h"
24675f49bbSEnrico Granata #include "lldb/Target/Language.h"
25170c395eSEnrico Granata #include "lldb/Target/ObjCLanguageRuntime.h"
26170c395eSEnrico Granata #include "lldb/Target/Target.h"
27666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
2801c3243fSZachary Turner #include "lldb/Utility/Endian.h"
2997206d57SZachary Turner #include "lldb/Utility/Status.h"
30bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
31170c395eSEnrico Granata 
32170c395eSEnrico Granata using namespace lldb;
33170c395eSEnrico Granata using namespace lldb_private;
34170c395eSEnrico Granata using namespace lldb_private::formatters;
35170c395eSEnrico Granata 
36170c395eSEnrico Granata namespace lldb_private {
37170c395eSEnrico Granata namespace formatters {
38c28b3e88SEnrico Granata std::map<ConstString, CXXFunctionSummaryFormat::Callback> &
39b9c1b51eSKate Stone NSArray_Additionals::GetAdditionalSummaries() {
40c28b3e88SEnrico Granata   static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
41c28b3e88SEnrico Granata   return g_map;
42c28b3e88SEnrico Granata }
43c28b3e88SEnrico Granata 
44c28b3e88SEnrico Granata std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> &
45b9c1b51eSKate Stone NSArray_Additionals::GetAdditionalSynthetics() {
46b9c1b51eSKate Stone   static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>
47b9c1b51eSKate Stone       g_map;
48c28b3e88SEnrico Granata   return g_map;
49c28b3e88SEnrico Granata }
50c28b3e88SEnrico Granata 
51bb93483cSJason Molenda class NSArrayMSyntheticFrontEndBase : public SyntheticChildrenFrontEnd {
52170c395eSEnrico Granata public:
53bb93483cSJason Molenda   NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp);
54170c395eSEnrico Granata 
55bb93483cSJason Molenda   ~NSArrayMSyntheticFrontEndBase() override = default;
56170c395eSEnrico Granata 
57b9c1b51eSKate Stone   size_t CalculateNumChildren() override;
58170c395eSEnrico Granata 
59b9c1b51eSKate Stone   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
60170c395eSEnrico Granata 
61b9c1b51eSKate Stone   bool Update() override = 0;
62170c395eSEnrico Granata 
63b9c1b51eSKate Stone   bool MightHaveChildren() override;
64170c395eSEnrico Granata 
65b9c1b51eSKate Stone   size_t GetIndexOfChildWithName(const ConstString &name) override;
66170c395eSEnrico Granata 
67170c395eSEnrico Granata protected:
68b9c1b51eSKate Stone   virtual lldb::addr_t GetDataAddress() = 0;
69170c395eSEnrico Granata 
70b9c1b51eSKate Stone   virtual uint64_t GetUsedCount() = 0;
71170c395eSEnrico Granata 
72b9c1b51eSKate Stone   virtual uint64_t GetOffset() = 0;
73170c395eSEnrico Granata 
74b9c1b51eSKate Stone   virtual uint64_t GetSize() = 0;
75170c395eSEnrico Granata 
76170c395eSEnrico Granata   ExecutionContextRef m_exe_ctx_ref;
77170c395eSEnrico Granata   uint8_t m_ptr_size;
78170c395eSEnrico Granata   CompilerType m_id_type;
79170c395eSEnrico Granata };
80170c395eSEnrico Granata 
81bb93483cSJason Molenda template <typename D32, typename D64>
82bb93483cSJason Molenda class GenericNSArrayMSyntheticFrontEnd : public NSArrayMSyntheticFrontEndBase {
838d15f33bSEugene Zelenko public:
84bb93483cSJason Molenda   GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
858d15f33bSEugene Zelenko 
86bb93483cSJason Molenda   ~GenericNSArrayMSyntheticFrontEnd() override;
878d15f33bSEugene Zelenko 
88b9c1b51eSKate Stone   bool Update() override;
898d15f33bSEugene Zelenko 
908d15f33bSEugene Zelenko protected:
91b9c1b51eSKate Stone   lldb::addr_t GetDataAddress() override;
928d15f33bSEugene Zelenko 
93b9c1b51eSKate Stone   uint64_t GetUsedCount() override;
948d15f33bSEugene Zelenko 
95b9c1b51eSKate Stone   uint64_t GetOffset() override;
968d15f33bSEugene Zelenko 
97b9c1b51eSKate Stone   uint64_t GetSize() override;
988d15f33bSEugene Zelenko 
99170c395eSEnrico Granata private:
100bb93483cSJason Molenda   D32 *m_data_32;
101bb93483cSJason Molenda   D64 *m_data_64;
102bb93483cSJason Molenda };
103bb93483cSJason Molenda 
104bb93483cSJason Molenda namespace Foundation109 {
105b9c1b51eSKate Stone   struct DataDescriptor_32 {
106170c395eSEnrico Granata     uint32_t _used;
107170c395eSEnrico Granata     uint32_t _priv1 : 2;
108170c395eSEnrico Granata     uint32_t _size : 30;
109170c395eSEnrico Granata     uint32_t _priv2 : 2;
110170c395eSEnrico Granata     uint32_t _offset : 30;
111170c395eSEnrico Granata     uint32_t _priv3;
112170c395eSEnrico Granata     uint32_t _data;
113170c395eSEnrico Granata   };
1148d15f33bSEugene Zelenko 
115b9c1b51eSKate Stone   struct DataDescriptor_64 {
116170c395eSEnrico Granata     uint64_t _used;
117170c395eSEnrico Granata     uint64_t _priv1 : 2;
118170c395eSEnrico Granata     uint64_t _size : 62;
119170c395eSEnrico Granata     uint64_t _priv2 : 2;
120170c395eSEnrico Granata     uint64_t _offset : 62;
121170c395eSEnrico Granata     uint32_t _priv3;
122170c395eSEnrico Granata     uint64_t _data;
123170c395eSEnrico Granata   };
124170c395eSEnrico Granata 
125bb93483cSJason Molenda   using NSArrayMSyntheticFrontEnd =
126bb93483cSJason Molenda       GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
127170c395eSEnrico Granata };
128170c395eSEnrico Granata 
129bb93483cSJason Molenda namespace Foundation1010 {
130b9c1b51eSKate Stone   struct DataDescriptor_32 {
131170c395eSEnrico Granata     uint32_t _used;
132170c395eSEnrico Granata     uint32_t _offset;
133170c395eSEnrico Granata     uint32_t _size : 28;
134170c395eSEnrico Granata     uint64_t _priv1 : 4;
135170c395eSEnrico Granata     uint32_t _priv2;
136170c395eSEnrico Granata     uint32_t _data;
137170c395eSEnrico Granata   };
1388d15f33bSEugene Zelenko 
139b9c1b51eSKate Stone   struct DataDescriptor_64 {
140170c395eSEnrico Granata     uint64_t _used;
141170c395eSEnrico Granata     uint64_t _offset;
142170c395eSEnrico Granata     uint64_t _size : 60;
143170c395eSEnrico Granata     uint64_t _priv1 : 4;
144170c395eSEnrico Granata     uint32_t _priv2;
145170c395eSEnrico Granata     uint64_t _data;
146170c395eSEnrico Granata   };
147170c395eSEnrico Granata 
148bb93483cSJason Molenda   using NSArrayMSyntheticFrontEnd =
149bb93483cSJason Molenda       GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
150170c395eSEnrico Granata };
151170c395eSEnrico Granata 
152bb93483cSJason Molenda namespace Foundation1428 {
153f40da172SSean Callanan   struct DataDescriptor_32 {
154bb93483cSJason Molenda     uint32_t _used;
155bb93483cSJason Molenda     uint32_t _offset;
156bb93483cSJason Molenda     uint32_t _size;
157bb93483cSJason Molenda     uint32_t _data;
158f40da172SSean Callanan   };
159f40da172SSean Callanan 
160f40da172SSean Callanan   struct DataDescriptor_64 {
161bb93483cSJason Molenda     uint64_t _used;
162bb93483cSJason Molenda     uint64_t _offset;
163bb93483cSJason Molenda     uint64_t _size;
164bb93483cSJason Molenda     uint64_t _data;
165f40da172SSean Callanan   };
166f40da172SSean Callanan 
167bb93483cSJason Molenda   using NSArrayMSyntheticFrontEnd =
168bb93483cSJason Molenda       GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
169f40da172SSean Callanan };
170f40da172SSean Callanan 
171bb93483cSJason Molenda namespace Foundation1437 {
172bb93483cSJason Molenda   template <typename PtrType>
173bb93483cSJason Molenda   struct DataDescriptor {
174bb93483cSJason Molenda     PtrType _cow;
175bb93483cSJason Molenda     // __deque
176bb93483cSJason Molenda     PtrType _data;
177bb93483cSJason Molenda     uint32_t _offset;
178bb93483cSJason Molenda     uint32_t _size;
179bb93483cSJason Molenda     union {
180bb93483cSJason Molenda       PtrType _mutations;
181bb93483cSJason Molenda       struct {
182bb93483cSJason Molenda         uint32_t _muts;
183bb93483cSJason Molenda         uint32_t _used;
184bb93483cSJason Molenda       };
185bb93483cSJason Molenda     };
186bb93483cSJason Molenda   };
187bb93483cSJason Molenda 
188bb93483cSJason Molenda   using NSArrayMSyntheticFrontEnd =
189bb93483cSJason Molenda      GenericNSArrayMSyntheticFrontEnd<
190bb93483cSJason Molenda         DataDescriptor<uint32_t>, DataDescriptor<uint64_t>>;
191bb93483cSJason Molenda 
192bb93483cSJason Molenda   template <typename DD>
193bb93483cSJason Molenda   uint64_t
194bb93483cSJason Molenda   __NSArrayMSize_Impl(lldb_private::Process &process,
195bb93483cSJason Molenda                       lldb::addr_t valobj_addr, Status &error) {
196bb93483cSJason Molenda     const lldb::addr_t start_of_descriptor =
197bb93483cSJason Molenda     valobj_addr + process.GetAddressByteSize();
198bb93483cSJason Molenda     DD descriptor = DD();
199bb93483cSJason Molenda     process.ReadMemory(start_of_descriptor, &descriptor,
200bb93483cSJason Molenda                        sizeof(descriptor), error);
201bb93483cSJason Molenda     if (error.Fail()) {
202bb93483cSJason Molenda       return 0;
203bb93483cSJason Molenda     }
204bb93483cSJason Molenda     return descriptor._used;
205bb93483cSJason Molenda   }
206bb93483cSJason Molenda 
207bb93483cSJason Molenda   uint64_t
208bb93483cSJason Molenda   __NSArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr,
209bb93483cSJason Molenda                  Status &error) {
210bb93483cSJason Molenda     if (process.GetAddressByteSize() == 4) {
211bb93483cSJason Molenda       return __NSArrayMSize_Impl<DataDescriptor<uint32_t>>(process, valobj_addr,
212bb93483cSJason Molenda                                                            error);
213bb93483cSJason Molenda     } else {
214bb93483cSJason Molenda       return __NSArrayMSize_Impl<DataDescriptor<uint64_t>>(process, valobj_addr,
215bb93483cSJason Molenda                                                            error);
216bb93483cSJason Molenda     }
217bb93483cSJason Molenda   }
218bb93483cSJason Molenda 
219*c8bee2ceSDavide Italiano }
220bb93483cSJason Molenda 
221bb93483cSJason Molenda template <typename D32, typename D64, bool Inline>
222bb93483cSJason Molenda class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
223f40da172SSean Callanan public:
224bb93483cSJason Molenda   GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
225f40da172SSean Callanan 
226bb93483cSJason Molenda   ~GenericNSArrayISyntheticFrontEnd() override;
227f40da172SSean Callanan 
228f40da172SSean Callanan   size_t CalculateNumChildren() override;
229f40da172SSean Callanan 
230f40da172SSean Callanan   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
231f40da172SSean Callanan 
232f40da172SSean Callanan   bool Update() override;
233f40da172SSean Callanan 
234f40da172SSean Callanan   bool MightHaveChildren() override;
235f40da172SSean Callanan 
236f40da172SSean Callanan   size_t GetIndexOfChildWithName(const ConstString &name) override;
237f40da172SSean Callanan 
238f40da172SSean Callanan private:
239f40da172SSean Callanan   ExecutionContextRef m_exe_ctx_ref;
240f40da172SSean Callanan   uint8_t m_ptr_size;
241f40da172SSean Callanan 
242bb93483cSJason Molenda   D32 *m_data_32;
243bb93483cSJason Molenda   D64 *m_data_64;
244bb93483cSJason Molenda   CompilerType m_id_type;
245bb93483cSJason Molenda };
246bb93483cSJason Molenda 
247bb93483cSJason Molenda namespace Foundation1300 {
248bb93483cSJason Molenda     struct IDD32 {
249f40da172SSean Callanan         uint32_t used;
250f40da172SSean Callanan         uint32_t list;
251f40da172SSean Callanan     };
252f40da172SSean Callanan 
253bb93483cSJason Molenda     struct IDD64 {
254f40da172SSean Callanan         uint64_t used;
255f40da172SSean Callanan         uint64_t list;
256f40da172SSean Callanan     };
257f40da172SSean Callanan 
258bb93483cSJason Molenda     using NSArrayISyntheticFrontEnd =
259bb93483cSJason Molenda         GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>;
260*c8bee2ceSDavide Italiano }
261bb93483cSJason Molenda 
262bb93483cSJason Molenda namespace Foundation1430 {
263bb93483cSJason Molenda     using NSArrayISyntheticFrontEnd =
264bb93483cSJason Molenda         Foundation1428::NSArrayMSyntheticFrontEnd;
265*c8bee2ceSDavide Italiano }
266bb93483cSJason Molenda 
267bb93483cSJason Molenda namespace Foundation1436 {
268bb93483cSJason Molenda     struct IDD32 {
269bb93483cSJason Molenda         uint32_t used;
270bb93483cSJason Molenda         uint32_t list; // in Inline cases, this is the first element
271bb93483cSJason Molenda     };
272bb93483cSJason Molenda 
273bb93483cSJason Molenda     struct IDD64 {
274bb93483cSJason Molenda         uint64_t used;
275bb93483cSJason Molenda         uint64_t list; // in Inline cases, this is the first element
276bb93483cSJason Molenda     };
277bb93483cSJason Molenda 
278bb93483cSJason Molenda     using NSArrayI_TransferSyntheticFrontEnd =
279bb93483cSJason Molenda         GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, false>;
280bb93483cSJason Molenda 
281bb93483cSJason Molenda     using NSArrayISyntheticFrontEnd =
282bb93483cSJason Molenda         GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>;
283bb93483cSJason Molenda 
284bb93483cSJason Molenda     using NSFrozenArrayMSyntheticFrontEnd =
285bb93483cSJason Molenda         Foundation1437::NSArrayMSyntheticFrontEnd;
286bb93483cSJason Molenda 
287bb93483cSJason Molenda     uint64_t
288bb93483cSJason Molenda     __NSFrozenArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr,
289bb93483cSJason Molenda                          Status &error) {
290bb93483cSJason Molenda       return Foundation1437::__NSArrayMSize(process, valobj_addr, error);
291bb93483cSJason Molenda     }
292*c8bee2ceSDavide Italiano }
293f40da172SSean Callanan 
294b9c1b51eSKate Stone class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
295bbf1da3cSEnrico Granata public:
296bbf1da3cSEnrico Granata   NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
297bbf1da3cSEnrico Granata 
2988d15f33bSEugene Zelenko   ~NSArray0SyntheticFrontEnd() override = default;
299bbf1da3cSEnrico Granata 
300b9c1b51eSKate Stone   size_t CalculateNumChildren() override;
301bbf1da3cSEnrico Granata 
302b9c1b51eSKate Stone   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
303bbf1da3cSEnrico Granata 
304b9c1b51eSKate Stone   bool Update() override;
305bbf1da3cSEnrico Granata 
306b9c1b51eSKate Stone   bool MightHaveChildren() override;
307bbf1da3cSEnrico Granata 
308b9c1b51eSKate Stone   size_t GetIndexOfChildWithName(const ConstString &name) override;
309bbf1da3cSEnrico Granata };
310936499aeSEnrico Granata 
311b9c1b51eSKate Stone class NSArray1SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
312936499aeSEnrico Granata public:
313936499aeSEnrico Granata   NSArray1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
314936499aeSEnrico Granata 
315936499aeSEnrico Granata   ~NSArray1SyntheticFrontEnd() override = default;
316936499aeSEnrico Granata 
317b9c1b51eSKate Stone   size_t CalculateNumChildren() override;
318936499aeSEnrico Granata 
319b9c1b51eSKate Stone   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
320936499aeSEnrico Granata 
321b9c1b51eSKate Stone   bool Update() override;
322936499aeSEnrico Granata 
323b9c1b51eSKate Stone   bool MightHaveChildren() override;
324936499aeSEnrico Granata 
325b9c1b51eSKate Stone   size_t GetIndexOfChildWithName(const ConstString &name) override;
326936499aeSEnrico Granata };
3278d15f33bSEugene Zelenko } // namespace formatters
3288d15f33bSEugene Zelenko } // namespace lldb_private
329170c395eSEnrico Granata 
330b9c1b51eSKate Stone bool lldb_private::formatters::NSArraySummaryProvider(
331b9c1b51eSKate Stone     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
332675f49bbSEnrico Granata   static ConstString g_TypeHint("NSArray");
333675f49bbSEnrico Granata 
334170c395eSEnrico Granata   ProcessSP process_sp = valobj.GetProcessSP();
335170c395eSEnrico Granata   if (!process_sp)
336170c395eSEnrico Granata     return false;
337170c395eSEnrico Granata 
338b9c1b51eSKate Stone   ObjCLanguageRuntime *runtime =
339b9c1b51eSKate Stone       (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime(
340b9c1b51eSKate Stone           lldb::eLanguageTypeObjC);
341170c395eSEnrico Granata 
342170c395eSEnrico Granata   if (!runtime)
343170c395eSEnrico Granata     return false;
344170c395eSEnrico Granata 
345b9c1b51eSKate Stone   ObjCLanguageRuntime::ClassDescriptorSP descriptor(
346b9c1b51eSKate Stone       runtime->GetClassDescriptor(valobj));
347170c395eSEnrico Granata 
348bbd16815SEugene Zelenko   if (!descriptor || !descriptor->IsValid())
349170c395eSEnrico Granata     return false;
350170c395eSEnrico Granata 
351170c395eSEnrico Granata   uint32_t ptr_size = process_sp->GetAddressByteSize();
352170c395eSEnrico Granata 
353170c395eSEnrico Granata   lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
354170c395eSEnrico Granata 
355170c395eSEnrico Granata   if (!valobj_addr)
356170c395eSEnrico Granata     return false;
357170c395eSEnrico Granata 
358170c395eSEnrico Granata   uint64_t value = 0;
359170c395eSEnrico Granata 
360936499aeSEnrico Granata   ConstString class_name(descriptor->GetClassName());
361170c395eSEnrico Granata 
362936499aeSEnrico Granata   static const ConstString g_NSArrayI("__NSArrayI");
363936499aeSEnrico Granata   static const ConstString g_NSArrayM("__NSArrayM");
364bb93483cSJason Molenda   static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer");
365bb93483cSJason Molenda   static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM");
366936499aeSEnrico Granata   static const ConstString g_NSArray0("__NSArray0");
367936499aeSEnrico Granata   static const ConstString g_NSArray1("__NSSingleObjectArrayI");
368936499aeSEnrico Granata   static const ConstString g_NSArrayCF("__NSCFArray");
369f40da172SSean Callanan   static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
370f40da172SSean Callanan   static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
371936499aeSEnrico Granata 
372936499aeSEnrico Granata   if (class_name.IsEmpty())
373170c395eSEnrico Granata     return false;
374170c395eSEnrico Granata 
375b9c1b51eSKate Stone   if (class_name == g_NSArrayI) {
37697206d57SZachary Turner     Status error;
377b9c1b51eSKate Stone     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
378b9c1b51eSKate Stone                                                       ptr_size, 0, error);
379170c395eSEnrico Granata     if (error.Fail())
380170c395eSEnrico Granata       return false;
381b9c1b51eSKate Stone   } else if (class_name == g_NSArrayM) {
382bb93483cSJason Molenda     AppleObjCRuntime *apple_runtime =
383bb93483cSJason Molenda     llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
384bb93483cSJason Molenda     Status error;
385bb93483cSJason Molenda     if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {
386bb93483cSJason Molenda       value = Foundation1437::__NSArrayMSize(*process_sp, valobj_addr, error);
387bb93483cSJason Molenda     } else {
388bb93483cSJason Molenda       value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
389bb93483cSJason Molenda                                                         ptr_size, 0, error);
390bb93483cSJason Molenda     }
391bb93483cSJason Molenda     if (error.Fail())
392bb93483cSJason Molenda       return false;
393bb93483cSJason Molenda   } else if (class_name == g_NSArrayI_Transfer) {
39497206d57SZachary Turner     Status error;
395b9c1b51eSKate Stone     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
396b9c1b51eSKate Stone                                                       ptr_size, 0, error);
397170c395eSEnrico Granata     if (error.Fail())
398170c395eSEnrico Granata       return false;
399bb93483cSJason Molenda   } else if (class_name == g_NSFrozenArrayM) {
400bb93483cSJason Molenda     Status error;
401bb93483cSJason Molenda     value = Foundation1436::__NSFrozenArrayMSize(*process_sp, valobj_addr, error);
402bb93483cSJason Molenda     if (error.Fail())
403bb93483cSJason Molenda       return false;
404f40da172SSean Callanan   } else if (class_name == g_NSArrayMLegacy) {
405f40da172SSean Callanan     Status error;
406f40da172SSean Callanan     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
407f40da172SSean Callanan                                                       ptr_size, 0, error);
408f40da172SSean Callanan     if (error.Fail())
409f40da172SSean Callanan       return false;
410f40da172SSean Callanan   } else if (class_name == g_NSArrayMImmutable) {
411f40da172SSean Callanan     Status error;
412f40da172SSean Callanan     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
413f40da172SSean Callanan                                                       ptr_size, 0, error);
414f40da172SSean Callanan     if (error.Fail())
415f40da172SSean Callanan       return false;
416b9c1b51eSKate Stone   } else if (class_name == g_NSArray0) {
417bbf1da3cSEnrico Granata     value = 0;
418b9c1b51eSKate Stone   } else if (class_name == g_NSArray1) {
419936499aeSEnrico Granata     value = 1;
420b9c1b51eSKate Stone   } else if (class_name == g_NSArrayCF) {
42197206d57SZachary Turner     Status error;
422b9c1b51eSKate Stone     value = process_sp->ReadUnsignedIntegerFromMemory(
423b9c1b51eSKate Stone         valobj_addr + 2 * ptr_size, ptr_size, 0, error);
424170c395eSEnrico Granata     if (error.Fail())
425170c395eSEnrico Granata       return false;
426b9c1b51eSKate Stone   } else {
427c28b3e88SEnrico Granata     auto &map(NSArray_Additionals::GetAdditionalSummaries());
428c28b3e88SEnrico Granata     auto iter = map.find(class_name), end = map.end();
429c28b3e88SEnrico Granata     if (iter != end)
430c28b3e88SEnrico Granata       return iter->second(valobj, stream, options);
431c28b3e88SEnrico Granata     else
432170c395eSEnrico Granata       return false;
433c28b3e88SEnrico Granata   }
434170c395eSEnrico Granata 
435675f49bbSEnrico Granata   std::string prefix, suffix;
436b9c1b51eSKate Stone   if (Language *language = Language::FindPlugin(options.GetLanguage())) {
437b9c1b51eSKate Stone     if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
438b9c1b51eSKate Stone                                             suffix)) {
439675f49bbSEnrico Granata       prefix.clear();
440675f49bbSEnrico Granata       suffix.clear();
441675f49bbSEnrico Granata     }
442675f49bbSEnrico Granata   }
443675f49bbSEnrico Granata 
444b9c1b51eSKate Stone   stream.Printf("%s%" PRIu64 " %s%s%s", prefix.c_str(), value, "element",
445b9c1b51eSKate Stone                 value == 1 ? "" : "s", suffix.c_str());
446170c395eSEnrico Granata   return true;
447170c395eSEnrico Granata }
448170c395eSEnrico Granata 
449bb93483cSJason Molenda lldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontEndBase(
450b9c1b51eSKate Stone     lldb::ValueObjectSP valobj_sp)
451b9c1b51eSKate Stone     : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
452b9c1b51eSKate Stone       m_id_type() {
453b9c1b51eSKate Stone   if (valobj_sp) {
454b9c1b51eSKate Stone     clang::ASTContext *ast = valobj_sp->GetExecutionContextRef()
455b9c1b51eSKate Stone                                  .GetTargetSP()
456b9c1b51eSKate Stone                                  ->GetScratchClangASTContext()
457b9c1b51eSKate Stone                                  ->getASTContext();
458170c395eSEnrico Granata     if (ast)
459170c395eSEnrico Granata       m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy);
460170c395eSEnrico Granata     if (valobj_sp->GetProcessSP())
461170c395eSEnrico Granata       m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
462170c395eSEnrico Granata   }
463170c395eSEnrico Granata }
464170c395eSEnrico Granata 
465bb93483cSJason Molenda template <typename D32, typename D64>
466bb93483cSJason Molenda lldb_private::formatters::
467bb93483cSJason Molenda   GenericNSArrayMSyntheticFrontEnd<D32, D64>::
468bb93483cSJason Molenda     GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
469bb93483cSJason Molenda     : NSArrayMSyntheticFrontEndBase(valobj_sp), m_data_32(nullptr),
470f40da172SSean Callanan       m_data_64(nullptr) {}
471f40da172SSean Callanan 
472170c395eSEnrico Granata size_t
473bb93483cSJason Molenda lldb_private::formatters::NSArrayMSyntheticFrontEndBase::CalculateNumChildren() {
474170c395eSEnrico Granata   return GetUsedCount();
475170c395eSEnrico Granata }
476170c395eSEnrico Granata 
477170c395eSEnrico Granata lldb::ValueObjectSP
478bb93483cSJason Molenda lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetChildAtIndex(
479b9c1b51eSKate Stone     size_t idx) {
480170c395eSEnrico Granata   if (idx >= CalculateNumChildren())
481170c395eSEnrico Granata     return lldb::ValueObjectSP();
482170c395eSEnrico Granata   lldb::addr_t object_at_idx = GetDataAddress();
483170c395eSEnrico Granata   size_t pyhs_idx = idx;
484170c395eSEnrico Granata   pyhs_idx += GetOffset();
485170c395eSEnrico Granata   if (GetSize() <= pyhs_idx)
486170c395eSEnrico Granata     pyhs_idx -= GetSize();
487170c395eSEnrico Granata   object_at_idx += (pyhs_idx * m_ptr_size);
488170c395eSEnrico Granata   StreamString idx_name;
489170c395eSEnrico Granata   idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
490c156427dSZachary Turner   return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx,
491b9c1b51eSKate Stone                                       m_exe_ctx_ref, m_id_type);
492170c395eSEnrico Granata }
493170c395eSEnrico Granata 
494bb93483cSJason Molenda template <typename D32, typename D64>
495bb93483cSJason Molenda bool
496bb93483cSJason Molenda lldb_private::formatters::
497bb93483cSJason Molenda   GenericNSArrayMSyntheticFrontEnd<D32, D64>::Update() {
498170c395eSEnrico Granata   ValueObjectSP valobj_sp = m_backend.GetSP();
499170c395eSEnrico Granata   m_ptr_size = 0;
500170c395eSEnrico Granata   delete m_data_32;
501bbd16815SEugene Zelenko   m_data_32 = nullptr;
502170c395eSEnrico Granata   delete m_data_64;
503bbd16815SEugene Zelenko   m_data_64 = nullptr;
504170c395eSEnrico Granata   if (!valobj_sp)
505170c395eSEnrico Granata     return false;
506170c395eSEnrico Granata   m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
50797206d57SZachary Turner   Status error;
508170c395eSEnrico Granata   error.Clear();
509170c395eSEnrico Granata   lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
510170c395eSEnrico Granata   if (!process_sp)
511170c395eSEnrico Granata     return false;
512170c395eSEnrico Granata   m_ptr_size = process_sp->GetAddressByteSize();
513170c395eSEnrico Granata   uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
514b9c1b51eSKate Stone   if (m_ptr_size == 4) {
515bb93483cSJason Molenda     m_data_32 = new D32();
516bb93483cSJason Molenda     process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
517b9c1b51eSKate Stone                            error);
518b9c1b51eSKate Stone   } else {
519bb93483cSJason Molenda     m_data_64 = new D64();
520bb93483cSJason Molenda     process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
521b9c1b51eSKate Stone                            error);
522170c395eSEnrico Granata   }
523170c395eSEnrico Granata   if (error.Fail())
524170c395eSEnrico Granata     return false;
525170c395eSEnrico Granata   return false;
526170c395eSEnrico Granata }
527170c395eSEnrico Granata 
528bb93483cSJason Molenda bool
529bb93483cSJason Molenda lldb_private::formatters::NSArrayMSyntheticFrontEndBase::MightHaveChildren() {
530170c395eSEnrico Granata   return true;
531170c395eSEnrico Granata }
532170c395eSEnrico Granata 
533170c395eSEnrico Granata size_t
534bb93483cSJason Molenda lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetIndexOfChildWithName(
535b9c1b51eSKate Stone     const ConstString &name) {
536170c395eSEnrico Granata   const char *item_name = name.GetCString();
537170c395eSEnrico Granata   uint32_t idx = ExtractIndexFromString(item_name);
538170c395eSEnrico Granata   if (idx < UINT32_MAX && idx >= CalculateNumChildren())
539170c395eSEnrico Granata     return UINT32_MAX;
540170c395eSEnrico Granata   return idx;
541170c395eSEnrico Granata }
542170c395eSEnrico Granata 
543bb93483cSJason Molenda template <typename D32, typename D64>
544bb93483cSJason Molenda lldb_private::formatters::
545bb93483cSJason Molenda   GenericNSArrayMSyntheticFrontEnd<D32, D64>::
546bb93483cSJason Molenda     ~GenericNSArrayMSyntheticFrontEnd() {
5478d15f33bSEugene Zelenko   delete m_data_32;
548bbd16815SEugene Zelenko   m_data_32 = nullptr;
5498d15f33bSEugene Zelenko   delete m_data_64;
550bbd16815SEugene Zelenko   m_data_64 = nullptr;
5518d15f33bSEugene Zelenko }
5528d15f33bSEugene Zelenko 
553bb93483cSJason Molenda template <typename D32, typename D64>
554170c395eSEnrico Granata lldb::addr_t
555bb93483cSJason Molenda lldb_private::formatters::
556bb93483cSJason Molenda   GenericNSArrayMSyntheticFrontEnd<D32, D64>::
557bb93483cSJason Molenda     GenericNSArrayMSyntheticFrontEnd::GetDataAddress() {
558170c395eSEnrico Granata   if (!m_data_32 && !m_data_64)
559170c395eSEnrico Granata     return LLDB_INVALID_ADDRESS;
560b9c1b51eSKate Stone   return m_data_32 ? m_data_32->_data : m_data_64->_data;
561170c395eSEnrico Granata }
562170c395eSEnrico Granata 
563bb93483cSJason Molenda template <typename D32, typename D64>
564170c395eSEnrico Granata uint64_t
565bb93483cSJason Molenda lldb_private::formatters::
566bb93483cSJason Molenda   GenericNSArrayMSyntheticFrontEnd<D32, D64>::
567bb93483cSJason Molenda     GenericNSArrayMSyntheticFrontEnd::GetUsedCount() {
568170c395eSEnrico Granata   if (!m_data_32 && !m_data_64)
569170c395eSEnrico Granata     return 0;
570b9c1b51eSKate Stone   return m_data_32 ? m_data_32->_used : m_data_64->_used;
571170c395eSEnrico Granata }
572170c395eSEnrico Granata 
573bb93483cSJason Molenda template <typename D32, typename D64>
574bb93483cSJason Molenda uint64_t
575bb93483cSJason Molenda lldb_private::formatters::
576bb93483cSJason Molenda   GenericNSArrayMSyntheticFrontEnd<D32, D64>::
577bb93483cSJason Molenda     GenericNSArrayMSyntheticFrontEnd::GetOffset() {
578170c395eSEnrico Granata   if (!m_data_32 && !m_data_64)
579170c395eSEnrico Granata     return 0;
580b9c1b51eSKate Stone   return m_data_32 ? m_data_32->_offset : m_data_64->_offset;
581170c395eSEnrico Granata }
582170c395eSEnrico Granata 
583bb93483cSJason Molenda template <typename D32, typename D64>
584bb93483cSJason Molenda uint64_t
585bb93483cSJason Molenda lldb_private::formatters::
586bb93483cSJason Molenda   GenericNSArrayMSyntheticFrontEnd<D32, D64>::
587bb93483cSJason Molenda     GenericNSArrayMSyntheticFrontEnd::GetSize() {
588170c395eSEnrico Granata   if (!m_data_32 && !m_data_64)
589170c395eSEnrico Granata     return 0;
590b9c1b51eSKate Stone   return m_data_32 ? m_data_32->_size : m_data_64->_size;
591170c395eSEnrico Granata }
592170c395eSEnrico Granata 
593bb93483cSJason Molenda template <typename D32, typename D64, bool Inline>
594bb93483cSJason Molenda lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
595bb93483cSJason Molenda   GenericNSArrayISyntheticFrontEnd(
596f40da172SSean Callanan     lldb::ValueObjectSP valobj_sp)
597f40da172SSean Callanan     : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
598f40da172SSean Callanan       m_data_32(nullptr), m_data_64(nullptr) {
599f40da172SSean Callanan   if (valobj_sp) {
600f40da172SSean Callanan     CompilerType type = valobj_sp->GetCompilerType();
601f40da172SSean Callanan     if (type) {
602f40da172SSean Callanan       ClangASTContext *ast = valobj_sp->GetExecutionContextRef()
603f40da172SSean Callanan                                  .GetTargetSP()
604f40da172SSean Callanan                                  ->GetScratchClangASTContext();
605f40da172SSean Callanan       if (ast)
606f40da172SSean Callanan         m_id_type = CompilerType(ast->getASTContext(),
607f40da172SSean Callanan                                  ast->getASTContext()->ObjCBuiltinIdTy);
608f40da172SSean Callanan     }
609f40da172SSean Callanan   }
610f40da172SSean Callanan }
611f40da172SSean Callanan 
612bb93483cSJason Molenda template <typename D32, typename D64, bool Inline>
613bb93483cSJason Molenda lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
614bb93483cSJason Molenda   ~GenericNSArrayISyntheticFrontEnd() {
615f40da172SSean Callanan   delete m_data_32;
616f40da172SSean Callanan   m_data_32 = nullptr;
617f40da172SSean Callanan   delete m_data_64;
618f40da172SSean Callanan   m_data_64 = nullptr;
619f40da172SSean Callanan }
620f40da172SSean Callanan 
621bb93483cSJason Molenda template <typename D32, typename D64, bool Inline>
622f40da172SSean Callanan size_t
623bb93483cSJason Molenda lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
624bb93483cSJason Molenda   GetIndexOfChildWithName(const ConstString &name) {
625f40da172SSean Callanan   const char *item_name = name.GetCString();
626f40da172SSean Callanan   uint32_t idx = ExtractIndexFromString(item_name);
627f40da172SSean Callanan   if (idx < UINT32_MAX && idx >= CalculateNumChildren())
628f40da172SSean Callanan     return UINT32_MAX;
629f40da172SSean Callanan   return idx;
630f40da172SSean Callanan }
631f40da172SSean Callanan 
632bb93483cSJason Molenda template <typename D32, typename D64, bool Inline>
633f40da172SSean Callanan size_t
634bb93483cSJason Molenda lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
635bb93483cSJason Molenda   CalculateNumChildren() {
636f40da172SSean Callanan   return m_data_32 ? m_data_32->used : m_data_64->used;
637f40da172SSean Callanan }
638f40da172SSean Callanan 
639bb93483cSJason Molenda template <typename D32, typename D64, bool Inline>
640bb93483cSJason Molenda bool
641bb93483cSJason Molenda lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
642bb93483cSJason Molenda   Update() {
643f40da172SSean Callanan   ValueObjectSP valobj_sp = m_backend.GetSP();
644f40da172SSean Callanan   m_ptr_size = 0;
645f40da172SSean Callanan   delete m_data_32;
646f40da172SSean Callanan   m_data_32 = nullptr;
647f40da172SSean Callanan   delete m_data_64;
648f40da172SSean Callanan   m_data_64 = nullptr;
649f40da172SSean Callanan   if (!valobj_sp)
650f40da172SSean Callanan     return false;
651f40da172SSean Callanan   m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
652f40da172SSean Callanan   Status error;
653f40da172SSean Callanan   error.Clear();
654f40da172SSean Callanan   lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
655f40da172SSean Callanan   if (!process_sp)
656f40da172SSean Callanan     return false;
657f40da172SSean Callanan   m_ptr_size = process_sp->GetAddressByteSize();
658f40da172SSean Callanan   uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
659f40da172SSean Callanan   if (m_ptr_size == 4) {
660bb93483cSJason Molenda     m_data_32 = new D32();
661bb93483cSJason Molenda     process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
662f40da172SSean Callanan                            error);
663f40da172SSean Callanan   } else {
664bb93483cSJason Molenda     m_data_64 = new D64();
665bb93483cSJason Molenda     process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
666f40da172SSean Callanan                            error);
667f40da172SSean Callanan   }
668f40da172SSean Callanan   if (error.Fail())
669f40da172SSean Callanan     return false;
670f40da172SSean Callanan   return false;
671f40da172SSean Callanan }
672f40da172SSean Callanan 
673bb93483cSJason Molenda template <typename D32, typename D64, bool Inline>
674bb93483cSJason Molenda bool
675bb93483cSJason Molenda lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
676bb93483cSJason Molenda   MightHaveChildren() {
677f40da172SSean Callanan   return true;
678f40da172SSean Callanan }
679f40da172SSean Callanan 
680bb93483cSJason Molenda template <typename D32, typename D64, bool Inline>
681f40da172SSean Callanan lldb::ValueObjectSP
682bb93483cSJason Molenda lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
683bb93483cSJason Molenda   GetChildAtIndex(size_t idx) {
684f40da172SSean Callanan   if (idx >= CalculateNumChildren())
685f40da172SSean Callanan     return lldb::ValueObjectSP();
686bb93483cSJason Molenda   lldb::addr_t object_at_idx;
687bb93483cSJason Molenda   if (Inline) {
688bb93483cSJason Molenda     object_at_idx = m_backend.GetSP()->GetValueAsUnsigned(0) + m_ptr_size;
689bb93483cSJason Molenda     object_at_idx += m_ptr_size == 4 ? sizeof(D32) : sizeof(D64); // skip the data header
690bb93483cSJason Molenda     object_at_idx -= m_ptr_size; // we treat the last entry in the data header as the first pointer
691bb93483cSJason Molenda   } else {
692bb93483cSJason Molenda     object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list;
693bb93483cSJason Molenda   }
694f40da172SSean Callanan   object_at_idx += (idx * m_ptr_size);
695bb93483cSJason Molenda 
696f40da172SSean Callanan   ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
697f40da172SSean Callanan   if (!process_sp)
698f40da172SSean Callanan     return lldb::ValueObjectSP();
699f40da172SSean Callanan   Status error;
700f40da172SSean Callanan   if (error.Fail())
701f40da172SSean Callanan     return lldb::ValueObjectSP();
702f40da172SSean Callanan   StreamString idx_name;
703f40da172SSean Callanan   idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
704f40da172SSean Callanan   return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx,
705f40da172SSean Callanan                                       m_exe_ctx_ref, m_id_type);
706f40da172SSean Callanan }
707f40da172SSean Callanan 
708b9c1b51eSKate Stone lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd(
709b9c1b51eSKate Stone     lldb::ValueObjectSP valobj_sp)
710b9c1b51eSKate Stone     : SyntheticChildrenFrontEnd(*valobj_sp) {}
711bbf1da3cSEnrico Granata 
712bbf1da3cSEnrico Granata size_t
713b9c1b51eSKate Stone lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName(
714b9c1b51eSKate Stone     const ConstString &name) {
715bbf1da3cSEnrico Granata   return UINT32_MAX;
716bbf1da3cSEnrico Granata }
717bbf1da3cSEnrico Granata 
718bbf1da3cSEnrico Granata size_t
719b9c1b51eSKate Stone lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren() {
720bbf1da3cSEnrico Granata   return 0;
721bbf1da3cSEnrico Granata }
722bbf1da3cSEnrico Granata 
723b9c1b51eSKate Stone bool lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() {
724bbf1da3cSEnrico Granata   return false;
725bbf1da3cSEnrico Granata }
726bbf1da3cSEnrico Granata 
727b9c1b51eSKate Stone bool lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren() {
728bbf1da3cSEnrico Granata   return false;
729bbf1da3cSEnrico Granata }
730bbf1da3cSEnrico Granata 
731bbf1da3cSEnrico Granata lldb::ValueObjectSP
732b9c1b51eSKate Stone lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex(
733b9c1b51eSKate Stone     size_t idx) {
734bbf1da3cSEnrico Granata   return lldb::ValueObjectSP();
735bbf1da3cSEnrico Granata }
736bbf1da3cSEnrico Granata 
737b9c1b51eSKate Stone lldb_private::formatters::NSArray1SyntheticFrontEnd::NSArray1SyntheticFrontEnd(
738b9c1b51eSKate Stone     lldb::ValueObjectSP valobj_sp)
739b9c1b51eSKate Stone     : SyntheticChildrenFrontEnd(*valobj_sp.get()) {}
740936499aeSEnrico Granata 
741936499aeSEnrico Granata size_t
742b9c1b51eSKate Stone lldb_private::formatters::NSArray1SyntheticFrontEnd::GetIndexOfChildWithName(
743b9c1b51eSKate Stone     const ConstString &name) {
744936499aeSEnrico Granata   static const ConstString g_zero("[0]");
745936499aeSEnrico Granata 
746936499aeSEnrico Granata   if (name == g_zero)
747936499aeSEnrico Granata     return 0;
748936499aeSEnrico Granata 
749936499aeSEnrico Granata   return UINT32_MAX;
750936499aeSEnrico Granata }
751936499aeSEnrico Granata 
752936499aeSEnrico Granata size_t
753b9c1b51eSKate Stone lldb_private::formatters::NSArray1SyntheticFrontEnd::CalculateNumChildren() {
754936499aeSEnrico Granata   return 1;
755936499aeSEnrico Granata }
756936499aeSEnrico Granata 
757b9c1b51eSKate Stone bool lldb_private::formatters::NSArray1SyntheticFrontEnd::Update() {
758936499aeSEnrico Granata   return false;
759936499aeSEnrico Granata }
760936499aeSEnrico Granata 
761b9c1b51eSKate Stone bool lldb_private::formatters::NSArray1SyntheticFrontEnd::MightHaveChildren() {
762936499aeSEnrico Granata   return true;
763936499aeSEnrico Granata }
764936499aeSEnrico Granata 
765936499aeSEnrico Granata lldb::ValueObjectSP
766b9c1b51eSKate Stone lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex(
767b9c1b51eSKate Stone     size_t idx) {
768936499aeSEnrico Granata   static const ConstString g_zero("[0]");
769936499aeSEnrico Granata 
770b9c1b51eSKate Stone   if (idx == 0) {
771b9c1b51eSKate Stone     CompilerType id_type(
772b9c1b51eSKate Stone         m_backend.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(
773b9c1b51eSKate Stone             lldb::eBasicTypeObjCID));
774b9c1b51eSKate Stone     return m_backend.GetSyntheticChildAtOffset(
775b9c1b51eSKate Stone         m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true, g_zero);
776936499aeSEnrico Granata   }
777936499aeSEnrico Granata   return lldb::ValueObjectSP();
778936499aeSEnrico Granata }
779936499aeSEnrico Granata 
780b9c1b51eSKate Stone SyntheticChildrenFrontEnd *
781b9c1b51eSKate Stone lldb_private::formatters::NSArraySyntheticFrontEndCreator(
782b9c1b51eSKate Stone     CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) {
783170c395eSEnrico Granata   if (!valobj_sp)
784170c395eSEnrico Granata     return nullptr;
785170c395eSEnrico Granata 
786170c395eSEnrico Granata   lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
787170c395eSEnrico Granata   if (!process_sp)
788bbd16815SEugene Zelenko     return nullptr;
789b9c1b51eSKate Stone   AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
790b9c1b51eSKate Stone       process_sp->GetObjCLanguageRuntime());
791170c395eSEnrico Granata   if (!runtime)
792bbd16815SEugene Zelenko     return nullptr;
793170c395eSEnrico Granata 
794170c395eSEnrico Granata   CompilerType valobj_type(valobj_sp->GetCompilerType());
795170c395eSEnrico Granata   Flags flags(valobj_type.GetTypeInfo());
796170c395eSEnrico Granata 
797b9c1b51eSKate Stone   if (flags.IsClear(eTypeIsPointer)) {
79897206d57SZachary Turner     Status error;
799170c395eSEnrico Granata     valobj_sp = valobj_sp->AddressOf(error);
800170c395eSEnrico Granata     if (error.Fail() || !valobj_sp)
801bbd16815SEugene Zelenko       return nullptr;
802170c395eSEnrico Granata   }
803170c395eSEnrico Granata 
804b9c1b51eSKate Stone   ObjCLanguageRuntime::ClassDescriptorSP descriptor(
805b9c1b51eSKate Stone       runtime->GetClassDescriptor(*valobj_sp));
806170c395eSEnrico Granata 
807bbd16815SEugene Zelenko   if (!descriptor || !descriptor->IsValid())
808bbd16815SEugene Zelenko     return nullptr;
809170c395eSEnrico Granata 
810936499aeSEnrico Granata   ConstString class_name(descriptor->GetClassName());
811170c395eSEnrico Granata 
812936499aeSEnrico Granata   static const ConstString g_NSArrayI("__NSArrayI");
813bb93483cSJason Molenda   static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer");
814bb93483cSJason Molenda   static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM");
815936499aeSEnrico Granata   static const ConstString g_NSArrayM("__NSArrayM");
816936499aeSEnrico Granata   static const ConstString g_NSArray0("__NSArray0");
817936499aeSEnrico Granata   static const ConstString g_NSArray1("__NSSingleObjectArrayI");
818f40da172SSean Callanan   static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
819f40da172SSean Callanan   static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
820936499aeSEnrico Granata 
821936499aeSEnrico Granata   if (class_name.IsEmpty())
822bbd16815SEugene Zelenko     return nullptr;
823170c395eSEnrico Granata 
824b9c1b51eSKate Stone   if (class_name == g_NSArrayI) {
825bb93483cSJason Molenda     if (runtime->GetFoundationVersion() >= 1436)
826bb93483cSJason Molenda       return (new Foundation1436::NSArrayISyntheticFrontEnd(valobj_sp));
827bb93483cSJason Molenda     if (runtime->GetFoundationVersion() >= 1430)
828bb93483cSJason Molenda       return (new Foundation1430::NSArrayISyntheticFrontEnd(valobj_sp));
829f40da172SSean Callanan     else
830bb93483cSJason Molenda       return (new Foundation1300::NSArrayISyntheticFrontEnd(valobj_sp));
831bb93483cSJason Molenda   } else if (class_name == g_NSArrayI_Transfer) {
832bb93483cSJason Molenda       return (new Foundation1436::NSArrayI_TransferSyntheticFrontEnd(valobj_sp));
833bb93483cSJason Molenda   } else if (class_name == g_NSArray0) {
834bb93483cSJason Molenda   } else if (class_name == g_NSFrozenArrayM) {
835bb93483cSJason Molenda     return (new Foundation1436::NSFrozenArrayMSyntheticFrontEnd(valobj_sp));
836b9c1b51eSKate Stone   } else if (class_name == g_NSArray0) {
837bbf1da3cSEnrico Granata     return (new NSArray0SyntheticFrontEnd(valobj_sp));
838b9c1b51eSKate Stone   } else if (class_name == g_NSArray1) {
839936499aeSEnrico Granata     return (new NSArray1SyntheticFrontEnd(valobj_sp));
840b9c1b51eSKate Stone   } else if (class_name == g_NSArrayM) {
841bb93483cSJason Molenda     if (runtime->GetFoundationVersion() >= 1437)
842bb93483cSJason Molenda       return (new Foundation1437::NSArrayMSyntheticFrontEnd(valobj_sp));
843bb93483cSJason Molenda     if (runtime->GetFoundationVersion() >= 1428)
844bb93483cSJason Molenda       return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp));
845170c395eSEnrico Granata     if (runtime->GetFoundationVersion() >= 1100)
846bb93483cSJason Molenda       return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp));
847170c395eSEnrico Granata     else
848bb93483cSJason Molenda       return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp));
849b9c1b51eSKate Stone   } else {
850c28b3e88SEnrico Granata     auto &map(NSArray_Additionals::GetAdditionalSynthetics());
851c28b3e88SEnrico Granata     auto iter = map.find(class_name), end = map.end();
852c28b3e88SEnrico Granata     if (iter != end)
853c28b3e88SEnrico Granata       return iter->second(synth, valobj_sp);
854c28b3e88SEnrico Granata   }
855170c395eSEnrico Granata 
8562543d290SEnrico Granata   return nullptr;
857170c395eSEnrico Granata }
858