1cfca06d7SDimitry Andric //===-- NSArray.cpp -------------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9e81d9d49SDimitry Andric #include "clang/AST/ASTContext.h"
10cfca06d7SDimitry Andric #include "clang/Basic/TargetInfo.h"
11e81d9d49SDimitry Andric
12e81d9d49SDimitry Andric #include "Cocoa.h"
13f034231aSEd Maste
1414f1b3e8SDimitry Andric #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
15cfca06d7SDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
165f29bb8aSDimitry Andric
17f034231aSEd Maste #include "lldb/Core/ValueObject.h"
18f034231aSEd Maste #include "lldb/Core/ValueObjectConstResult.h"
19e81d9d49SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
20e81d9d49SDimitry Andric #include "lldb/Expression/FunctionCaller.h"
21e81d9d49SDimitry Andric #include "lldb/Target/Language.h"
22f034231aSEd Maste #include "lldb/Target/Target.h"
2374a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
2474a628f7SDimitry Andric #include "lldb/Utility/Endian.h"
25b76161e4SDimitry Andric #include "lldb/Utility/Status.h"
2674a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
27f034231aSEd Maste
28f034231aSEd Maste using namespace lldb;
29f034231aSEd Maste using namespace lldb_private;
30f034231aSEd Maste using namespace lldb_private::formatters;
31f034231aSEd Maste
320cac4ca3SEd Maste namespace lldb_private {
330cac4ca3SEd Maste namespace formatters {
34f3fbd1c0SDimitry Andric std::map<ConstString, CXXFunctionSummaryFormat::Callback> &
GetAdditionalSummaries()3514f1b3e8SDimitry Andric NSArray_Additionals::GetAdditionalSummaries() {
36f3fbd1c0SDimitry Andric static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
37f3fbd1c0SDimitry Andric return g_map;
38f3fbd1c0SDimitry Andric }
39f3fbd1c0SDimitry Andric
40f3fbd1c0SDimitry Andric std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> &
GetAdditionalSynthetics()4114f1b3e8SDimitry Andric NSArray_Additionals::GetAdditionalSynthetics() {
4214f1b3e8SDimitry Andric static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>
4314f1b3e8SDimitry Andric g_map;
44f3fbd1c0SDimitry Andric return g_map;
45f3fbd1c0SDimitry Andric }
46f3fbd1c0SDimitry Andric
47ef5d0b5eSDimitry Andric class NSArrayMSyntheticFrontEndBase : public SyntheticChildrenFrontEnd {
480cac4ca3SEd Maste public:
49ef5d0b5eSDimitry Andric NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp);
500cac4ca3SEd Maste
51ef5d0b5eSDimitry Andric ~NSArrayMSyntheticFrontEndBase() override = default;
520cac4ca3SEd Maste
53ac9a064cSDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override;
540cac4ca3SEd Maste
55ac9a064cSDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
560cac4ca3SEd Maste
57ac9a064cSDimitry Andric lldb::ChildCacheState Update() override = 0;
580cac4ca3SEd Maste
5914f1b3e8SDimitry Andric bool MightHaveChildren() override;
600cac4ca3SEd Maste
615f29bb8aSDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override;
620cac4ca3SEd Maste
630cac4ca3SEd Maste protected:
6414f1b3e8SDimitry Andric virtual lldb::addr_t GetDataAddress() = 0;
650cac4ca3SEd Maste
6614f1b3e8SDimitry Andric virtual uint64_t GetUsedCount() = 0;
670cac4ca3SEd Maste
6814f1b3e8SDimitry Andric virtual uint64_t GetOffset() = 0;
690cac4ca3SEd Maste
7014f1b3e8SDimitry Andric virtual uint64_t GetSize() = 0;
710cac4ca3SEd Maste
720cac4ca3SEd Maste ExecutionContextRef m_exe_ctx_ref;
73145449b1SDimitry Andric uint8_t m_ptr_size = 8;
74e81d9d49SDimitry Andric CompilerType m_id_type;
750cac4ca3SEd Maste };
760cac4ca3SEd Maste
77ef5d0b5eSDimitry Andric template <typename D32, typename D64>
78ef5d0b5eSDimitry Andric class GenericNSArrayMSyntheticFrontEnd : public NSArrayMSyntheticFrontEndBase {
79e81d9d49SDimitry Andric public:
80ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
81e81d9d49SDimitry Andric
82ef5d0b5eSDimitry Andric ~GenericNSArrayMSyntheticFrontEnd() override;
83e81d9d49SDimitry Andric
84ac9a064cSDimitry Andric lldb::ChildCacheState Update() override;
85e81d9d49SDimitry Andric
86e81d9d49SDimitry Andric protected:
8714f1b3e8SDimitry Andric lldb::addr_t GetDataAddress() override;
88e81d9d49SDimitry Andric
8914f1b3e8SDimitry Andric uint64_t GetUsedCount() override;
90e81d9d49SDimitry Andric
9114f1b3e8SDimitry Andric uint64_t GetOffset() override;
92e81d9d49SDimitry Andric
9314f1b3e8SDimitry Andric uint64_t GetSize() override;
94e81d9d49SDimitry Andric
950cac4ca3SEd Maste private:
96ef5d0b5eSDimitry Andric D32 *m_data_32;
97ef5d0b5eSDimitry Andric D64 *m_data_64;
98ef5d0b5eSDimitry Andric };
99ef5d0b5eSDimitry Andric
100ef5d0b5eSDimitry Andric namespace Foundation1010 {
101cfca06d7SDimitry Andric namespace {
10214f1b3e8SDimitry Andric struct DataDescriptor_32 {
1030cac4ca3SEd Maste uint32_t _used;
1040cac4ca3SEd Maste uint32_t _offset;
1050cac4ca3SEd Maste uint32_t _size : 28;
1060cac4ca3SEd Maste uint64_t _priv1 : 4;
1070cac4ca3SEd Maste uint32_t _priv2;
1080cac4ca3SEd Maste uint32_t _data;
1090cac4ca3SEd Maste };
110e81d9d49SDimitry Andric
11114f1b3e8SDimitry Andric struct DataDescriptor_64 {
1120cac4ca3SEd Maste uint64_t _used;
1130cac4ca3SEd Maste uint64_t _offset;
1140cac4ca3SEd Maste uint64_t _size : 60;
1150cac4ca3SEd Maste uint64_t _priv1 : 4;
1160cac4ca3SEd Maste uint32_t _priv2;
1170cac4ca3SEd Maste uint64_t _data;
1180cac4ca3SEd Maste };
119cfca06d7SDimitry Andric }
1200cac4ca3SEd Maste
121ef5d0b5eSDimitry Andric using NSArrayMSyntheticFrontEnd =
122ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
123ef5d0b5eSDimitry Andric }
1240cac4ca3SEd Maste
125ef5d0b5eSDimitry Andric namespace Foundation1428 {
126cfca06d7SDimitry Andric namespace {
127fdea456aSDimitry Andric struct DataDescriptor_32 {
128ef5d0b5eSDimitry Andric uint32_t _used;
129ef5d0b5eSDimitry Andric uint32_t _offset;
130ef5d0b5eSDimitry Andric uint32_t _size;
131ef5d0b5eSDimitry Andric uint32_t _data;
132fdea456aSDimitry Andric };
133fdea456aSDimitry Andric
134fdea456aSDimitry Andric struct DataDescriptor_64 {
135ef5d0b5eSDimitry Andric uint64_t _used;
136ef5d0b5eSDimitry Andric uint64_t _offset;
137ef5d0b5eSDimitry Andric uint64_t _size;
138ef5d0b5eSDimitry Andric uint64_t _data;
139fdea456aSDimitry Andric };
140cfca06d7SDimitry Andric }
141fdea456aSDimitry Andric
142ef5d0b5eSDimitry Andric using NSArrayMSyntheticFrontEnd =
143ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
144ef5d0b5eSDimitry Andric }
145ef5d0b5eSDimitry Andric
146ef5d0b5eSDimitry Andric namespace Foundation1437 {
147ef5d0b5eSDimitry Andric template <typename PtrType>
148ef5d0b5eSDimitry Andric struct DataDescriptor {
149ef5d0b5eSDimitry Andric PtrType _cow;
150ef5d0b5eSDimitry Andric // __deque
151ef5d0b5eSDimitry Andric PtrType _data;
152ef5d0b5eSDimitry Andric uint32_t _offset;
153ef5d0b5eSDimitry Andric uint32_t _size;
154ef5d0b5eSDimitry Andric uint32_t _muts;
155ef5d0b5eSDimitry Andric uint32_t _used;
156ef5d0b5eSDimitry Andric };
157fdea456aSDimitry Andric
158ef5d0b5eSDimitry Andric using NSArrayMSyntheticFrontEnd =
159ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd<
160ef5d0b5eSDimitry Andric DataDescriptor<uint32_t>, DataDescriptor<uint64_t>>;
161ef5d0b5eSDimitry Andric
162ef5d0b5eSDimitry Andric template <typename DD>
163ef5d0b5eSDimitry Andric uint64_t
__NSArrayMSize_Impl(lldb_private::Process & process,lldb::addr_t valobj_addr,Status & error)164ef5d0b5eSDimitry Andric __NSArrayMSize_Impl(lldb_private::Process &process,
165ef5d0b5eSDimitry Andric lldb::addr_t valobj_addr, Status &error) {
166ef5d0b5eSDimitry Andric const lldb::addr_t start_of_descriptor =
167ef5d0b5eSDimitry Andric valobj_addr + process.GetAddressByteSize();
168ef5d0b5eSDimitry Andric DD descriptor = DD();
169ef5d0b5eSDimitry Andric process.ReadMemory(start_of_descriptor, &descriptor,
170ef5d0b5eSDimitry Andric sizeof(descriptor), error);
171ef5d0b5eSDimitry Andric if (error.Fail()) {
172ef5d0b5eSDimitry Andric return 0;
173ef5d0b5eSDimitry Andric }
174ef5d0b5eSDimitry Andric return descriptor._used;
175ef5d0b5eSDimitry Andric }
176ef5d0b5eSDimitry Andric
177ef5d0b5eSDimitry Andric uint64_t
__NSArrayMSize(lldb_private::Process & process,lldb::addr_t valobj_addr,Status & error)178ef5d0b5eSDimitry Andric __NSArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr,
179ef5d0b5eSDimitry Andric Status &error) {
180ef5d0b5eSDimitry Andric if (process.GetAddressByteSize() == 4) {
181ef5d0b5eSDimitry Andric return __NSArrayMSize_Impl<DataDescriptor<uint32_t>>(process, valobj_addr,
182ef5d0b5eSDimitry Andric error);
183ef5d0b5eSDimitry Andric } else {
184ef5d0b5eSDimitry Andric return __NSArrayMSize_Impl<DataDescriptor<uint64_t>>(process, valobj_addr,
185ef5d0b5eSDimitry Andric error);
186ef5d0b5eSDimitry Andric }
187ef5d0b5eSDimitry Andric }
188ef5d0b5eSDimitry Andric
189ef5d0b5eSDimitry Andric }
190ef5d0b5eSDimitry Andric
19194994d37SDimitry Andric namespace CallStackArray {
19294994d37SDimitry Andric struct DataDescriptor_32 {
19394994d37SDimitry Andric uint32_t _data;
19494994d37SDimitry Andric uint32_t _used;
19594994d37SDimitry Andric uint32_t _offset;
19694994d37SDimitry Andric const uint32_t _size = 0;
19794994d37SDimitry Andric };
19894994d37SDimitry Andric
19994994d37SDimitry Andric struct DataDescriptor_64 {
20094994d37SDimitry Andric uint64_t _data;
20194994d37SDimitry Andric uint64_t _used;
20294994d37SDimitry Andric uint64_t _offset;
20394994d37SDimitry Andric const uint64_t _size = 0;
20494994d37SDimitry Andric };
20594994d37SDimitry Andric
20694994d37SDimitry Andric using NSCallStackArraySyntheticFrontEnd =
20794994d37SDimitry Andric GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
20894994d37SDimitry Andric } // namespace CallStackArray
20994994d37SDimitry Andric
210ef5d0b5eSDimitry Andric template <typename D32, typename D64, bool Inline>
211ef5d0b5eSDimitry Andric class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
212fdea456aSDimitry Andric public:
213ef5d0b5eSDimitry Andric GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
214fdea456aSDimitry Andric
215ef5d0b5eSDimitry Andric ~GenericNSArrayISyntheticFrontEnd() override;
216fdea456aSDimitry Andric
217ac9a064cSDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override;
218fdea456aSDimitry Andric
219ac9a064cSDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
220fdea456aSDimitry Andric
221ac9a064cSDimitry Andric lldb::ChildCacheState Update() override;
222fdea456aSDimitry Andric
223fdea456aSDimitry Andric bool MightHaveChildren() override;
224fdea456aSDimitry Andric
2255f29bb8aSDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override;
226fdea456aSDimitry Andric
227fdea456aSDimitry Andric private:
228fdea456aSDimitry Andric ExecutionContextRef m_exe_ctx_ref;
229145449b1SDimitry Andric uint8_t m_ptr_size = 8;
230fdea456aSDimitry Andric
231ef5d0b5eSDimitry Andric D32 *m_data_32;
232ef5d0b5eSDimitry Andric D64 *m_data_64;
233ef5d0b5eSDimitry Andric CompilerType m_id_type;
234ef5d0b5eSDimitry Andric };
235ef5d0b5eSDimitry Andric
236ef5d0b5eSDimitry Andric namespace Foundation1300 {
237ef5d0b5eSDimitry Andric struct IDD32 {
238fdea456aSDimitry Andric uint32_t used;
239fdea456aSDimitry Andric uint32_t list;
240fdea456aSDimitry Andric };
241fdea456aSDimitry Andric
242ef5d0b5eSDimitry Andric struct IDD64 {
243fdea456aSDimitry Andric uint64_t used;
244fdea456aSDimitry Andric uint64_t list;
245fdea456aSDimitry Andric };
246fdea456aSDimitry Andric
247ef5d0b5eSDimitry Andric using NSArrayISyntheticFrontEnd =
248ef5d0b5eSDimitry Andric GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>;
249ef5d0b5eSDimitry Andric }
250ef5d0b5eSDimitry Andric
251ef5d0b5eSDimitry Andric namespace Foundation1430 {
252ef5d0b5eSDimitry Andric using NSArrayISyntheticFrontEnd =
253ef5d0b5eSDimitry Andric Foundation1428::NSArrayMSyntheticFrontEnd;
254ef5d0b5eSDimitry Andric }
255ef5d0b5eSDimitry Andric
256ef5d0b5eSDimitry Andric namespace Foundation1436 {
257ef5d0b5eSDimitry Andric struct IDD32 {
258ef5d0b5eSDimitry Andric uint32_t used;
259ef5d0b5eSDimitry Andric uint32_t list; // in Inline cases, this is the first element
260fdea456aSDimitry Andric };
261fdea456aSDimitry Andric
262ef5d0b5eSDimitry Andric struct IDD64 {
263ef5d0b5eSDimitry Andric uint64_t used;
264ef5d0b5eSDimitry Andric uint64_t list; // in Inline cases, this is the first element
265ef5d0b5eSDimitry Andric };
266ef5d0b5eSDimitry Andric
267ef5d0b5eSDimitry Andric using NSArrayI_TransferSyntheticFrontEnd =
268ef5d0b5eSDimitry Andric GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, false>;
269ef5d0b5eSDimitry Andric
270ef5d0b5eSDimitry Andric using NSArrayISyntheticFrontEnd =
271ef5d0b5eSDimitry Andric GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>;
272ef5d0b5eSDimitry Andric
273ef5d0b5eSDimitry Andric using NSFrozenArrayMSyntheticFrontEnd =
274ef5d0b5eSDimitry Andric Foundation1437::NSArrayMSyntheticFrontEnd;
275ef5d0b5eSDimitry Andric
276ef5d0b5eSDimitry Andric uint64_t
__NSFrozenArrayMSize(lldb_private::Process & process,lldb::addr_t valobj_addr,Status & error)277ef5d0b5eSDimitry Andric __NSFrozenArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr,
278ef5d0b5eSDimitry Andric Status &error) {
279ef5d0b5eSDimitry Andric return Foundation1437::__NSArrayMSize(process, valobj_addr, error);
280ef5d0b5eSDimitry Andric }
281ef5d0b5eSDimitry Andric }
282ef5d0b5eSDimitry Andric
283c0981da4SDimitry Andric namespace ConstantArray {
284c0981da4SDimitry Andric
285c0981da4SDimitry Andric struct ConstantArray32 {
286c0981da4SDimitry Andric uint64_t used;
287c0981da4SDimitry Andric uint32_t list;
288c0981da4SDimitry Andric };
289c0981da4SDimitry Andric
290c0981da4SDimitry Andric struct ConstantArray64 {
291c0981da4SDimitry Andric uint64_t used;
292c0981da4SDimitry Andric uint64_t list;
293c0981da4SDimitry Andric };
294c0981da4SDimitry Andric
295c0981da4SDimitry Andric using NSConstantArraySyntheticFrontEnd =
296c0981da4SDimitry Andric GenericNSArrayISyntheticFrontEnd<ConstantArray32, ConstantArray64, false>;
297c0981da4SDimitry Andric } // namespace ConstantArray
298c0981da4SDimitry Andric
29914f1b3e8SDimitry Andric class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
300e81d9d49SDimitry Andric public:
301e81d9d49SDimitry Andric NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
302e81d9d49SDimitry Andric
303e81d9d49SDimitry Andric ~NSArray0SyntheticFrontEnd() override = default;
304e81d9d49SDimitry Andric
305ac9a064cSDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override;
306e81d9d49SDimitry Andric
307ac9a064cSDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
308e81d9d49SDimitry Andric
309ac9a064cSDimitry Andric lldb::ChildCacheState Update() override;
310e81d9d49SDimitry Andric
31114f1b3e8SDimitry Andric bool MightHaveChildren() override;
312e81d9d49SDimitry Andric
3135f29bb8aSDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override;
314e81d9d49SDimitry Andric };
315e81d9d49SDimitry Andric
31614f1b3e8SDimitry Andric class NSArray1SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
3170cac4ca3SEd Maste public:
318f3fbd1c0SDimitry Andric NSArray1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
3190cac4ca3SEd Maste
320f3fbd1c0SDimitry Andric ~NSArray1SyntheticFrontEnd() override = default;
3210cac4ca3SEd Maste
322ac9a064cSDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override;
3230cac4ca3SEd Maste
324ac9a064cSDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
3250cac4ca3SEd Maste
326ac9a064cSDimitry Andric lldb::ChildCacheState Update() override;
3270cac4ca3SEd Maste
32814f1b3e8SDimitry Andric bool MightHaveChildren() override;
3290cac4ca3SEd Maste
3305f29bb8aSDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override;
3310cac4ca3SEd Maste };
332e81d9d49SDimitry Andric } // namespace formatters
333e81d9d49SDimitry Andric } // namespace lldb_private
3340cac4ca3SEd Maste
NSArraySummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)33514f1b3e8SDimitry Andric bool lldb_private::formatters::NSArraySummaryProvider(
33614f1b3e8SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
3377fa27ce4SDimitry Andric static constexpr llvm::StringLiteral g_TypeHint("NSArray");
338e81d9d49SDimitry Andric
339f034231aSEd Maste ProcessSP process_sp = valobj.GetProcessSP();
340f034231aSEd Maste if (!process_sp)
341f034231aSEd Maste return false;
342f034231aSEd Maste
3435f29bb8aSDimitry Andric ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
344f034231aSEd Maste
345f034231aSEd Maste if (!runtime)
346f034231aSEd Maste return false;
347f034231aSEd Maste
34814f1b3e8SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP descriptor(
34914f1b3e8SDimitry Andric runtime->GetClassDescriptor(valobj));
350f034231aSEd Maste
351f3fbd1c0SDimitry Andric if (!descriptor || !descriptor->IsValid())
352f034231aSEd Maste return false;
353f034231aSEd Maste
354f034231aSEd Maste uint32_t ptr_size = process_sp->GetAddressByteSize();
355f034231aSEd Maste
356f034231aSEd Maste lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
357f034231aSEd Maste
358f034231aSEd Maste if (!valobj_addr)
359f034231aSEd Maste return false;
360f034231aSEd Maste
361f034231aSEd Maste uint64_t value = 0;
362f034231aSEd Maste
363f3fbd1c0SDimitry Andric ConstString class_name(descriptor->GetClassName());
364f034231aSEd Maste
365f3fbd1c0SDimitry Andric static const ConstString g_NSArrayI("__NSArrayI");
366f3fbd1c0SDimitry Andric static const ConstString g_NSArrayM("__NSArrayM");
367ef5d0b5eSDimitry Andric static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer");
368ef5d0b5eSDimitry Andric static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM");
369f3fbd1c0SDimitry Andric static const ConstString g_NSArray0("__NSArray0");
370f3fbd1c0SDimitry Andric static const ConstString g_NSArray1("__NSSingleObjectArrayI");
371f3fbd1c0SDimitry Andric static const ConstString g_NSArrayCF("__NSCFArray");
372fdea456aSDimitry Andric static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
373fdea456aSDimitry Andric static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
37494994d37SDimitry Andric static const ConstString g_NSCallStackArray("_NSCallStackArray");
375c0981da4SDimitry Andric static const ConstString g_NSConstantArray("NSConstantArray");
376f3fbd1c0SDimitry Andric
377f3fbd1c0SDimitry Andric if (class_name.IsEmpty())
378f034231aSEd Maste return false;
379f034231aSEd Maste
38014f1b3e8SDimitry Andric if (class_name == g_NSArrayI) {
381b76161e4SDimitry Andric Status error;
38214f1b3e8SDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
38314f1b3e8SDimitry Andric ptr_size, 0, error);
384f034231aSEd Maste if (error.Fail())
385f034231aSEd Maste return false;
386c0981da4SDimitry Andric } else if (class_name == g_NSConstantArray) {
387c0981da4SDimitry Andric Status error;
388c0981da4SDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 8,
389c0981da4SDimitry Andric 0, error);
390c0981da4SDimitry Andric if (error.Fail())
391c0981da4SDimitry Andric return false;
39214f1b3e8SDimitry Andric } else if (class_name == g_NSArrayM) {
393ef5d0b5eSDimitry Andric AppleObjCRuntime *apple_runtime =
394ef5d0b5eSDimitry Andric llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
395ef5d0b5eSDimitry Andric Status error;
396ef5d0b5eSDimitry Andric if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {
397ef5d0b5eSDimitry Andric value = Foundation1437::__NSArrayMSize(*process_sp, valobj_addr, error);
398ef5d0b5eSDimitry Andric } else {
399ef5d0b5eSDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
400ef5d0b5eSDimitry Andric ptr_size, 0, error);
401ef5d0b5eSDimitry Andric }
402ef5d0b5eSDimitry Andric if (error.Fail())
403ef5d0b5eSDimitry Andric return false;
404ef5d0b5eSDimitry Andric } else if (class_name == g_NSArrayI_Transfer) {
405b76161e4SDimitry Andric Status error;
40614f1b3e8SDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
40714f1b3e8SDimitry Andric ptr_size, 0, error);
408f034231aSEd Maste if (error.Fail())
409f034231aSEd Maste return false;
410ef5d0b5eSDimitry Andric } else if (class_name == g_NSFrozenArrayM) {
411ef5d0b5eSDimitry Andric Status error;
412ef5d0b5eSDimitry Andric value = Foundation1436::__NSFrozenArrayMSize(*process_sp, valobj_addr, error);
413ef5d0b5eSDimitry Andric if (error.Fail())
414ef5d0b5eSDimitry Andric return false;
415fdea456aSDimitry Andric } else if (class_name == g_NSArrayMLegacy) {
416fdea456aSDimitry Andric Status error;
417fdea456aSDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
418fdea456aSDimitry Andric ptr_size, 0, error);
419fdea456aSDimitry Andric if (error.Fail())
420fdea456aSDimitry Andric return false;
421fdea456aSDimitry Andric } else if (class_name == g_NSArrayMImmutable) {
422fdea456aSDimitry Andric Status error;
423fdea456aSDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
424fdea456aSDimitry Andric ptr_size, 0, error);
425fdea456aSDimitry Andric if (error.Fail())
426fdea456aSDimitry Andric return false;
42714f1b3e8SDimitry Andric } else if (class_name == g_NSArray0) {
428e81d9d49SDimitry Andric value = 0;
42914f1b3e8SDimitry Andric } else if (class_name == g_NSArray1) {
430f3fbd1c0SDimitry Andric value = 1;
43194994d37SDimitry Andric } else if (class_name == g_NSArrayCF || class_name == g_NSCallStackArray) {
43294994d37SDimitry Andric // __NSCFArray and _NSCallStackArray store the number of elements as a
43394994d37SDimitry Andric // pointer-sized value at offset `2 * ptr_size`.
434b76161e4SDimitry Andric Status error;
43514f1b3e8SDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(
43614f1b3e8SDimitry Andric valobj_addr + 2 * ptr_size, ptr_size, 0, error);
437f034231aSEd Maste if (error.Fail())
438f034231aSEd Maste return false;
43914f1b3e8SDimitry Andric } else {
440f3fbd1c0SDimitry Andric auto &map(NSArray_Additionals::GetAdditionalSummaries());
441f3fbd1c0SDimitry Andric auto iter = map.find(class_name), end = map.end();
442f3fbd1c0SDimitry Andric if (iter != end)
443f3fbd1c0SDimitry Andric return iter->second(valobj, stream, options);
444f3fbd1c0SDimitry Andric else
445f034231aSEd Maste return false;
446f034231aSEd Maste }
447f034231aSEd Maste
4487fa27ce4SDimitry Andric llvm::StringRef prefix, suffix;
4497fa27ce4SDimitry Andric if (Language *language = Language::FindPlugin(options.GetLanguage()))
4507fa27ce4SDimitry Andric std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
451e81d9d49SDimitry Andric
4527fa27ce4SDimitry Andric stream << prefix;
4537fa27ce4SDimitry Andric stream.Printf("%" PRIu64 " %s%s", value, "element", value == 1 ? "" : "s");
4547fa27ce4SDimitry Andric stream << suffix;
455f034231aSEd Maste return true;
456f034231aSEd Maste }
457f034231aSEd Maste
458145449b1SDimitry Andric lldb_private::formatters::NSArrayMSyntheticFrontEndBase::
NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp)459145449b1SDimitry Andric NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp)
460145449b1SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_id_type() {
46114f1b3e8SDimitry Andric if (valobj_sp) {
462e3b55780SDimitry Andric TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(
463706b4fc4SDimitry Andric *valobj_sp->GetExecutionContextRef().GetTargetSP());
464e3b55780SDimitry Andric if (scratch_ts_sp)
465ead24645SDimitry Andric m_id_type = CompilerType(
466e3b55780SDimitry Andric scratch_ts_sp->weak_from_this(),
467e3b55780SDimitry Andric scratch_ts_sp->getASTContext().ObjCBuiltinIdTy.getAsOpaquePtr());
4680cac4ca3SEd Maste if (valobj_sp->GetProcessSP())
4690cac4ca3SEd Maste m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
470f034231aSEd Maste }
471f034231aSEd Maste }
472f034231aSEd Maste
473ef5d0b5eSDimitry Andric template <typename D32, typename D64>
474ef5d0b5eSDimitry Andric lldb_private::formatters::
475ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd<D32, D64>::
GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)476ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
477ef5d0b5eSDimitry Andric : NSArrayMSyntheticFrontEndBase(valobj_sp), m_data_32(nullptr),
478fdea456aSDimitry Andric m_data_64(nullptr) {}
479fdea456aSDimitry Andric
480ac9a064cSDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters::
CalculateNumChildren()481ac9a064cSDimitry Andric NSArrayMSyntheticFrontEndBase::CalculateNumChildren() {
4820cac4ca3SEd Maste return GetUsedCount();
483f034231aSEd Maste }
484f034231aSEd Maste
485f034231aSEd Maste lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx)486ef5d0b5eSDimitry Andric lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetChildAtIndex(
487ac9a064cSDimitry Andric uint32_t idx) {
488ac9a064cSDimitry Andric if (idx >= CalculateNumChildrenIgnoringErrors())
489f034231aSEd Maste return lldb::ValueObjectSP();
4900cac4ca3SEd Maste lldb::addr_t object_at_idx = GetDataAddress();
491f034231aSEd Maste size_t pyhs_idx = idx;
4920cac4ca3SEd Maste pyhs_idx += GetOffset();
4930cac4ca3SEd Maste if (GetSize() <= pyhs_idx)
4940cac4ca3SEd Maste pyhs_idx -= GetSize();
495f034231aSEd Maste object_at_idx += (pyhs_idx * m_ptr_size);
496f034231aSEd Maste StreamString idx_name;
4970cac4ca3SEd Maste idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
49814f1b3e8SDimitry Andric return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx,
49914f1b3e8SDimitry Andric m_exe_ctx_ref, m_id_type);
500f034231aSEd Maste }
501f034231aSEd Maste
502ef5d0b5eSDimitry Andric template <typename D32, typename D64>
503ac9a064cSDimitry Andric lldb::ChildCacheState
Update()504ac9a064cSDimitry Andric lldb_private::formatters::GenericNSArrayMSyntheticFrontEnd<D32, D64>::Update() {
5050cac4ca3SEd Maste ValueObjectSP valobj_sp = m_backend.GetSP();
5060cac4ca3SEd Maste m_ptr_size = 0;
5070cac4ca3SEd Maste delete m_data_32;
508f3fbd1c0SDimitry Andric m_data_32 = nullptr;
5090cac4ca3SEd Maste delete m_data_64;
510f3fbd1c0SDimitry Andric m_data_64 = nullptr;
5110cac4ca3SEd Maste if (!valobj_sp)
512ac9a064cSDimitry Andric return lldb::ChildCacheState::eRefetch;
5130cac4ca3SEd Maste m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
514b76161e4SDimitry Andric Status error;
5150cac4ca3SEd Maste error.Clear();
5160cac4ca3SEd Maste lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
5170cac4ca3SEd Maste if (!process_sp)
518ac9a064cSDimitry Andric return lldb::ChildCacheState::eRefetch;
5190cac4ca3SEd Maste m_ptr_size = process_sp->GetAddressByteSize();
5200cac4ca3SEd Maste uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
52114f1b3e8SDimitry Andric if (m_ptr_size == 4) {
522ef5d0b5eSDimitry Andric m_data_32 = new D32();
523ef5d0b5eSDimitry Andric process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
52414f1b3e8SDimitry Andric error);
52514f1b3e8SDimitry Andric } else {
526ef5d0b5eSDimitry Andric m_data_64 = new D64();
527ef5d0b5eSDimitry Andric process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
52814f1b3e8SDimitry Andric error);
5290cac4ca3SEd Maste }
530e3b55780SDimitry Andric
531ac9a064cSDimitry Andric return error.Success() ? lldb::ChildCacheState::eReuse
532ac9a064cSDimitry Andric : lldb::ChildCacheState::eRefetch;
5330cac4ca3SEd Maste }
5340cac4ca3SEd Maste
535ef5d0b5eSDimitry Andric bool
MightHaveChildren()536ef5d0b5eSDimitry Andric lldb_private::formatters::NSArrayMSyntheticFrontEndBase::MightHaveChildren() {
537f034231aSEd Maste return true;
538f034231aSEd Maste }
539f034231aSEd Maste
540f034231aSEd Maste size_t
GetIndexOfChildWithName(ConstString name)541ef5d0b5eSDimitry Andric lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetIndexOfChildWithName(
5425f29bb8aSDimitry Andric ConstString name) {
543f034231aSEd Maste const char *item_name = name.GetCString();
544f034231aSEd Maste uint32_t idx = ExtractIndexFromString(item_name);
545ac9a064cSDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())
546f034231aSEd Maste return UINT32_MAX;
547f034231aSEd Maste return idx;
548f034231aSEd Maste }
549f034231aSEd Maste
550ef5d0b5eSDimitry Andric template <typename D32, typename D64>
551ac9a064cSDimitry Andric lldb_private::formatters::GenericNSArrayMSyntheticFrontEnd<D32, D64>::
~GenericNSArrayMSyntheticFrontEnd()552ac9a064cSDimitry Andric GenericNSArrayMSyntheticFrontEnd::~GenericNSArrayMSyntheticFrontEnd() {
553e81d9d49SDimitry Andric delete m_data_32;
554f3fbd1c0SDimitry Andric m_data_32 = nullptr;
555e81d9d49SDimitry Andric delete m_data_64;
556f3fbd1c0SDimitry Andric m_data_64 = nullptr;
557e81d9d49SDimitry Andric }
558e81d9d49SDimitry Andric
559ef5d0b5eSDimitry Andric template <typename D32, typename D64>
5600cac4ca3SEd Maste lldb::addr_t
561ef5d0b5eSDimitry Andric lldb_private::formatters::
562ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd<D32, D64>::
GetDataAddress()563ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd::GetDataAddress() {
5640cac4ca3SEd Maste if (!m_data_32 && !m_data_64)
5650cac4ca3SEd Maste return LLDB_INVALID_ADDRESS;
56614f1b3e8SDimitry Andric return m_data_32 ? m_data_32->_data : m_data_64->_data;
5670cac4ca3SEd Maste }
5680cac4ca3SEd Maste
569ef5d0b5eSDimitry Andric template <typename D32, typename D64>
5700cac4ca3SEd Maste uint64_t
571ef5d0b5eSDimitry Andric lldb_private::formatters::
572ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd<D32, D64>::
GetUsedCount()573ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd::GetUsedCount() {
5740cac4ca3SEd Maste if (!m_data_32 && !m_data_64)
5750cac4ca3SEd Maste return 0;
57614f1b3e8SDimitry Andric return m_data_32 ? m_data_32->_used : m_data_64->_used;
5770cac4ca3SEd Maste }
5780cac4ca3SEd Maste
579ef5d0b5eSDimitry Andric template <typename D32, typename D64>
580ef5d0b5eSDimitry Andric uint64_t
581ef5d0b5eSDimitry Andric lldb_private::formatters::
582ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd<D32, D64>::
GetOffset()583ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd::GetOffset() {
5840cac4ca3SEd Maste if (!m_data_32 && !m_data_64)
5850cac4ca3SEd Maste return 0;
58614f1b3e8SDimitry Andric return m_data_32 ? m_data_32->_offset : m_data_64->_offset;
5870cac4ca3SEd Maste }
5880cac4ca3SEd Maste
589ef5d0b5eSDimitry Andric template <typename D32, typename D64>
590ef5d0b5eSDimitry Andric uint64_t
591ef5d0b5eSDimitry Andric lldb_private::formatters::
592ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd<D32, D64>::
GetSize()593ef5d0b5eSDimitry Andric GenericNSArrayMSyntheticFrontEnd::GetSize() {
5940cac4ca3SEd Maste if (!m_data_32 && !m_data_64)
5950cac4ca3SEd Maste return 0;
59614f1b3e8SDimitry Andric return m_data_32 ? m_data_32->_size : m_data_64->_size;
5970cac4ca3SEd Maste }
5980cac4ca3SEd Maste
599ef5d0b5eSDimitry Andric template <typename D32, typename D64, bool Inline>
600ef5d0b5eSDimitry Andric lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)601145449b1SDimitry Andric GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
602145449b1SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),
603fdea456aSDimitry Andric m_data_32(nullptr), m_data_64(nullptr) {
604fdea456aSDimitry Andric if (valobj_sp) {
605fdea456aSDimitry Andric CompilerType type = valobj_sp->GetCompilerType();
606fdea456aSDimitry Andric if (type) {
607e3b55780SDimitry Andric TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(
608706b4fc4SDimitry Andric *valobj_sp->GetExecutionContextRef().GetTargetSP());
609e3b55780SDimitry Andric if (scratch_ts_sp)
610e3b55780SDimitry Andric m_id_type = scratch_ts_sp->GetType(
611e3b55780SDimitry Andric scratch_ts_sp->getASTContext().ObjCBuiltinIdTy);
612fdea456aSDimitry Andric }
613fdea456aSDimitry Andric }
614fdea456aSDimitry Andric }
615fdea456aSDimitry Andric
616ef5d0b5eSDimitry Andric template <typename D32, typename D64, bool Inline>
617ef5d0b5eSDimitry Andric lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
~GenericNSArrayISyntheticFrontEnd()618ac9a064cSDimitry Andric GenericNSArrayISyntheticFrontEnd::~GenericNSArrayISyntheticFrontEnd() {
619fdea456aSDimitry Andric delete m_data_32;
620fdea456aSDimitry Andric m_data_32 = nullptr;
621fdea456aSDimitry Andric delete m_data_64;
622fdea456aSDimitry Andric m_data_64 = nullptr;
623fdea456aSDimitry Andric }
624fdea456aSDimitry Andric
625ef5d0b5eSDimitry Andric template <typename D32, typename D64, bool Inline>
626fdea456aSDimitry Andric size_t
627ef5d0b5eSDimitry Andric lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
GetIndexOfChildWithName(ConstString name)6285f29bb8aSDimitry Andric GetIndexOfChildWithName(ConstString name) {
629fdea456aSDimitry Andric const char *item_name = name.GetCString();
630fdea456aSDimitry Andric uint32_t idx = ExtractIndexFromString(item_name);
631ac9a064cSDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())
632fdea456aSDimitry Andric return UINT32_MAX;
633fdea456aSDimitry Andric return idx;
634fdea456aSDimitry Andric }
635fdea456aSDimitry Andric
636ef5d0b5eSDimitry Andric template <typename D32, typename D64, bool Inline>
637ac9a064cSDimitry Andric llvm::Expected<uint32_t>
638ac9a064cSDimitry Andric lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<
CalculateNumChildren()639ac9a064cSDimitry Andric D32, D64, Inline>::CalculateNumChildren() {
640fdea456aSDimitry Andric return m_data_32 ? m_data_32->used : m_data_64->used;
641fdea456aSDimitry Andric }
642fdea456aSDimitry Andric
643ef5d0b5eSDimitry Andric template <typename D32, typename D64, bool Inline>
644ac9a064cSDimitry Andric lldb::ChildCacheState
645ac9a064cSDimitry Andric lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64,
Update()646ac9a064cSDimitry Andric Inline>::Update() {
647fdea456aSDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP();
648fdea456aSDimitry Andric m_ptr_size = 0;
649fdea456aSDimitry Andric delete m_data_32;
650fdea456aSDimitry Andric m_data_32 = nullptr;
651fdea456aSDimitry Andric delete m_data_64;
652fdea456aSDimitry Andric m_data_64 = nullptr;
653fdea456aSDimitry Andric if (!valobj_sp)
654ac9a064cSDimitry Andric return lldb::ChildCacheState::eRefetch;
655fdea456aSDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
656fdea456aSDimitry Andric Status error;
657fdea456aSDimitry Andric error.Clear();
658fdea456aSDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
659fdea456aSDimitry Andric if (!process_sp)
660ac9a064cSDimitry Andric return lldb::ChildCacheState::eRefetch;
661fdea456aSDimitry Andric m_ptr_size = process_sp->GetAddressByteSize();
662fdea456aSDimitry Andric uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
663fdea456aSDimitry Andric if (m_ptr_size == 4) {
664ef5d0b5eSDimitry Andric m_data_32 = new D32();
665ef5d0b5eSDimitry Andric process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
666fdea456aSDimitry Andric error);
667fdea456aSDimitry Andric } else {
668ef5d0b5eSDimitry Andric m_data_64 = new D64();
669ef5d0b5eSDimitry Andric process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
670fdea456aSDimitry Andric error);
671fdea456aSDimitry Andric }
672e3b55780SDimitry Andric
673ac9a064cSDimitry Andric return error.Success() ? lldb::ChildCacheState::eReuse
674ac9a064cSDimitry Andric : lldb::ChildCacheState::eRefetch;
675fdea456aSDimitry Andric }
676fdea456aSDimitry Andric
677ef5d0b5eSDimitry Andric template <typename D32, typename D64, bool Inline>
678ef5d0b5eSDimitry Andric bool
679ef5d0b5eSDimitry Andric lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
MightHaveChildren()680ef5d0b5eSDimitry Andric MightHaveChildren() {
681fdea456aSDimitry Andric return true;
682fdea456aSDimitry Andric }
683fdea456aSDimitry Andric
684ef5d0b5eSDimitry Andric template <typename D32, typename D64, bool Inline>
685fdea456aSDimitry Andric lldb::ValueObjectSP
686ef5d0b5eSDimitry Andric lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
GetChildAtIndex(uint32_t idx)687ac9a064cSDimitry Andric GetChildAtIndex(uint32_t idx) {
688ac9a064cSDimitry Andric if (idx >= CalculateNumChildrenIgnoringErrors())
689fdea456aSDimitry Andric return lldb::ValueObjectSP();
690ef5d0b5eSDimitry Andric lldb::addr_t object_at_idx;
691ef5d0b5eSDimitry Andric if (Inline) {
692ef5d0b5eSDimitry Andric object_at_idx = m_backend.GetSP()->GetValueAsUnsigned(0) + m_ptr_size;
693ef5d0b5eSDimitry Andric object_at_idx += m_ptr_size == 4 ? sizeof(D32) : sizeof(D64); // skip the data header
694ef5d0b5eSDimitry Andric object_at_idx -= m_ptr_size; // we treat the last entry in the data header as the first pointer
695ef5d0b5eSDimitry Andric } else {
696ef5d0b5eSDimitry Andric object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list;
697ef5d0b5eSDimitry Andric }
698fdea456aSDimitry Andric object_at_idx += (idx * m_ptr_size);
699ef5d0b5eSDimitry Andric
700fdea456aSDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
701fdea456aSDimitry Andric if (!process_sp)
702fdea456aSDimitry Andric return lldb::ValueObjectSP();
703fdea456aSDimitry Andric Status error;
704fdea456aSDimitry Andric if (error.Fail())
705fdea456aSDimitry Andric return lldb::ValueObjectSP();
706fdea456aSDimitry Andric StreamString idx_name;
707fdea456aSDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
708fdea456aSDimitry Andric return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx,
709fdea456aSDimitry Andric m_exe_ctx_ref, m_id_type);
710fdea456aSDimitry Andric }
711fdea456aSDimitry Andric
NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)71214f1b3e8SDimitry Andric lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd(
71314f1b3e8SDimitry Andric lldb::ValueObjectSP valobj_sp)
71414f1b3e8SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp) {}
715e81d9d49SDimitry Andric
716e81d9d49SDimitry Andric size_t
GetIndexOfChildWithName(ConstString name)71714f1b3e8SDimitry Andric lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName(
7185f29bb8aSDimitry Andric ConstString name) {
719e81d9d49SDimitry Andric return UINT32_MAX;
720e81d9d49SDimitry Andric }
721e81d9d49SDimitry Andric
722ac9a064cSDimitry Andric llvm::Expected<uint32_t>
CalculateNumChildren()72314f1b3e8SDimitry Andric lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren() {
724e81d9d49SDimitry Andric return 0;
725e81d9d49SDimitry Andric }
726e81d9d49SDimitry Andric
727ac9a064cSDimitry Andric lldb::ChildCacheState
Update()728ac9a064cSDimitry Andric lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() {
729ac9a064cSDimitry Andric return lldb::ChildCacheState::eRefetch;
730e81d9d49SDimitry Andric }
731e81d9d49SDimitry Andric
MightHaveChildren()73214f1b3e8SDimitry Andric bool lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren() {
733e81d9d49SDimitry Andric return false;
734e81d9d49SDimitry Andric }
735e81d9d49SDimitry Andric
736e81d9d49SDimitry Andric lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx)73714f1b3e8SDimitry Andric lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex(
738ac9a064cSDimitry Andric uint32_t idx) {
739e81d9d49SDimitry Andric return lldb::ValueObjectSP();
740e81d9d49SDimitry Andric }
741e81d9d49SDimitry Andric
NSArray1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)74214f1b3e8SDimitry Andric lldb_private::formatters::NSArray1SyntheticFrontEnd::NSArray1SyntheticFrontEnd(
74314f1b3e8SDimitry Andric lldb::ValueObjectSP valobj_sp)
74414f1b3e8SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp.get()) {}
745f3fbd1c0SDimitry Andric
746f3fbd1c0SDimitry Andric size_t
GetIndexOfChildWithName(ConstString name)74714f1b3e8SDimitry Andric lldb_private::formatters::NSArray1SyntheticFrontEnd::GetIndexOfChildWithName(
7485f29bb8aSDimitry Andric ConstString name) {
749f3fbd1c0SDimitry Andric static const ConstString g_zero("[0]");
750f3fbd1c0SDimitry Andric
751f3fbd1c0SDimitry Andric if (name == g_zero)
752f3fbd1c0SDimitry Andric return 0;
753f3fbd1c0SDimitry Andric
754f3fbd1c0SDimitry Andric return UINT32_MAX;
755f3fbd1c0SDimitry Andric }
756f3fbd1c0SDimitry Andric
757ac9a064cSDimitry Andric llvm::Expected<uint32_t>
CalculateNumChildren()75814f1b3e8SDimitry Andric lldb_private::formatters::NSArray1SyntheticFrontEnd::CalculateNumChildren() {
759f3fbd1c0SDimitry Andric return 1;
760f3fbd1c0SDimitry Andric }
761f3fbd1c0SDimitry Andric
762ac9a064cSDimitry Andric lldb::ChildCacheState
Update()763ac9a064cSDimitry Andric lldb_private::formatters::NSArray1SyntheticFrontEnd::Update() {
764ac9a064cSDimitry Andric return lldb::ChildCacheState::eRefetch;
765f3fbd1c0SDimitry Andric }
766f3fbd1c0SDimitry Andric
MightHaveChildren()76714f1b3e8SDimitry Andric bool lldb_private::formatters::NSArray1SyntheticFrontEnd::MightHaveChildren() {
768f3fbd1c0SDimitry Andric return true;
769f3fbd1c0SDimitry Andric }
770f3fbd1c0SDimitry Andric
771f3fbd1c0SDimitry Andric lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx)77214f1b3e8SDimitry Andric lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex(
773ac9a064cSDimitry Andric uint32_t idx) {
774f3fbd1c0SDimitry Andric static const ConstString g_zero("[0]");
775f3fbd1c0SDimitry Andric
77614f1b3e8SDimitry Andric if (idx == 0) {
777e3b55780SDimitry Andric TypeSystemClangSP scratch_ts_sp =
778b60736ecSDimitry Andric ScratchTypeSystemClang::GetForTarget(*m_backend.GetTargetSP());
779e3b55780SDimitry Andric if (scratch_ts_sp) {
780e3b55780SDimitry Andric CompilerType id_type(scratch_ts_sp->GetBasicType(lldb::eBasicTypeObjCID));
78114f1b3e8SDimitry Andric return m_backend.GetSyntheticChildAtOffset(
782706b4fc4SDimitry Andric m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true,
783706b4fc4SDimitry Andric g_zero);
784706b4fc4SDimitry Andric }
785f3fbd1c0SDimitry Andric }
786f3fbd1c0SDimitry Andric return lldb::ValueObjectSP();
787f3fbd1c0SDimitry Andric }
788f3fbd1c0SDimitry Andric
78914f1b3e8SDimitry Andric SyntheticChildrenFrontEnd *
NSArraySyntheticFrontEndCreator(CXXSyntheticChildren * synth,lldb::ValueObjectSP valobj_sp)79014f1b3e8SDimitry Andric lldb_private::formatters::NSArraySyntheticFrontEndCreator(
79114f1b3e8SDimitry Andric CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) {
7920cac4ca3SEd Maste if (!valobj_sp)
7930cac4ca3SEd Maste return nullptr;
7940cac4ca3SEd Maste
795f034231aSEd Maste lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
796f034231aSEd Maste if (!process_sp)
797f3fbd1c0SDimitry Andric return nullptr;
79814f1b3e8SDimitry Andric AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
7995f29bb8aSDimitry Andric ObjCLanguageRuntime::Get(*process_sp));
800f034231aSEd Maste if (!runtime)
801f3fbd1c0SDimitry Andric return nullptr;
802f034231aSEd Maste
803e81d9d49SDimitry Andric CompilerType valobj_type(valobj_sp->GetCompilerType());
8040cac4ca3SEd Maste Flags flags(valobj_type.GetTypeInfo());
8050cac4ca3SEd Maste
80614f1b3e8SDimitry Andric if (flags.IsClear(eTypeIsPointer)) {
807b76161e4SDimitry Andric Status error;
808f034231aSEd Maste valobj_sp = valobj_sp->AddressOf(error);
809f034231aSEd Maste if (error.Fail() || !valobj_sp)
810f3fbd1c0SDimitry Andric return nullptr;
811f034231aSEd Maste }
812f034231aSEd Maste
81314f1b3e8SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP descriptor(
81414f1b3e8SDimitry Andric runtime->GetClassDescriptor(*valobj_sp));
815f034231aSEd Maste
816f3fbd1c0SDimitry Andric if (!descriptor || !descriptor->IsValid())
817f3fbd1c0SDimitry Andric return nullptr;
818f034231aSEd Maste
819f3fbd1c0SDimitry Andric ConstString class_name(descriptor->GetClassName());
820f034231aSEd Maste
821f3fbd1c0SDimitry Andric static const ConstString g_NSArrayI("__NSArrayI");
822c0981da4SDimitry Andric static const ConstString g_NSConstantArray("NSConstantArray");
823ef5d0b5eSDimitry Andric static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer");
824ef5d0b5eSDimitry Andric static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM");
825f3fbd1c0SDimitry Andric static const ConstString g_NSArrayM("__NSArrayM");
826f3fbd1c0SDimitry Andric static const ConstString g_NSArray0("__NSArray0");
827f3fbd1c0SDimitry Andric static const ConstString g_NSArray1("__NSSingleObjectArrayI");
828fdea456aSDimitry Andric static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
829fdea456aSDimitry Andric static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
83094994d37SDimitry Andric static const ConstString g_NSCallStackArray("_NSCallStackArray");
831f034231aSEd Maste
832f3fbd1c0SDimitry Andric if (class_name.IsEmpty())
833f3fbd1c0SDimitry Andric return nullptr;
834f3fbd1c0SDimitry Andric
83514f1b3e8SDimitry Andric if (class_name == g_NSArrayI) {
836ef5d0b5eSDimitry Andric if (runtime->GetFoundationVersion() >= 1436)
837ef5d0b5eSDimitry Andric return (new Foundation1436::NSArrayISyntheticFrontEnd(valobj_sp));
838ef5d0b5eSDimitry Andric if (runtime->GetFoundationVersion() >= 1430)
839ef5d0b5eSDimitry Andric return (new Foundation1430::NSArrayISyntheticFrontEnd(valobj_sp));
840ef5d0b5eSDimitry Andric return (new Foundation1300::NSArrayISyntheticFrontEnd(valobj_sp));
841ef5d0b5eSDimitry Andric } else if (class_name == g_NSArrayI_Transfer) {
842ef5d0b5eSDimitry Andric return (new Foundation1436::NSArrayI_TransferSyntheticFrontEnd(valobj_sp));
843c0981da4SDimitry Andric } else if (class_name == g_NSConstantArray) {
844c0981da4SDimitry Andric return new ConstantArray::NSConstantArraySyntheticFrontEnd(valobj_sp);
845ef5d0b5eSDimitry Andric } else if (class_name == g_NSFrozenArrayM) {
846ef5d0b5eSDimitry Andric return (new Foundation1436::NSFrozenArrayMSyntheticFrontEnd(valobj_sp));
84714f1b3e8SDimitry Andric } else if (class_name == g_NSArray0) {
848e81d9d49SDimitry Andric return (new NSArray0SyntheticFrontEnd(valobj_sp));
84914f1b3e8SDimitry Andric } else if (class_name == g_NSArray1) {
850f3fbd1c0SDimitry Andric return (new NSArray1SyntheticFrontEnd(valobj_sp));
85114f1b3e8SDimitry Andric } else if (class_name == g_NSArrayM) {
852ef5d0b5eSDimitry Andric if (runtime->GetFoundationVersion() >= 1437)
853ef5d0b5eSDimitry Andric return (new Foundation1437::NSArrayMSyntheticFrontEnd(valobj_sp));
854ef5d0b5eSDimitry Andric if (runtime->GetFoundationVersion() >= 1428)
855ef5d0b5eSDimitry Andric return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp));
8560cac4ca3SEd Maste if (runtime->GetFoundationVersion() >= 1100)
857ef5d0b5eSDimitry Andric return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp));
85894994d37SDimitry Andric } else if (class_name == g_NSCallStackArray) {
85994994d37SDimitry Andric return (new CallStackArray::NSCallStackArraySyntheticFrontEnd(valobj_sp));
86014f1b3e8SDimitry Andric } else {
861f3fbd1c0SDimitry Andric auto &map(NSArray_Additionals::GetAdditionalSynthetics());
862f3fbd1c0SDimitry Andric auto iter = map.find(class_name), end = map.end();
863f3fbd1c0SDimitry Andric if (iter != end)
864f3fbd1c0SDimitry Andric return iter->second(synth, valobj_sp);
865f034231aSEd Maste }
866f034231aSEd Maste
867f3fbd1c0SDimitry Andric return nullptr;
868f034231aSEd Maste }
869