Skip to content

Commit 5510a57

Browse files
author
Enrico Granata
committed
Add synthetic children support for NSIndexPath
llvm-svn: 219852
1 parent bbdd6c1 commit 5510a57

File tree

5 files changed

+315
-0
lines changed

5 files changed

+315
-0
lines changed

lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ namespace lldb_private {
474474

475475
SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
476476

477+
SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
478+
477479
class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd
478480
{
479481
public:

lldb/lldb.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@
648648
941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568814E355F2003A195C /* SBTypeSummary.h */; settings = {ATTRIBUTES = (Public, ); }; };
649649
941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568914E355F2003A195C /* SBTypeSynthetic.h */; settings = {ATTRIBUTES = (Public, ); }; };
650650
94380B8219940B0A00BFE4A8 /* StringLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */; };
651+
9439FB1A19EF140C006FD6A4 /* NSIndexPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */; };
651652
944372DC171F6B4300E57C32 /* RegisterContextDummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */; };
652653
944372DD171F6B4300E57C32 /* RegisterContextDummy.h in Headers */ = {isa = PBXBuildFile; fileRef = 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */; };
653654
9443B122140C18C40013457C /* SBData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9443B121140C18C10013457C /* SBData.cpp */; };
@@ -1985,6 +1986,7 @@
19851986
94145430175D7FDE00284436 /* lldb-versioning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-versioning.h"; path = "include/lldb/lldb-versioning.h"; sourceTree = "<group>"; };
19861987
94380B8019940B0300BFE4A8 /* StringLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringLexer.h; path = include/lldb/Utility/StringLexer.h; sourceTree = "<group>"; };
19871988
94380B8119940B0A00BFE4A8 /* StringLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringLexer.cpp; path = source/Utility/StringLexer.cpp; sourceTree = "<group>"; };
1989+
9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSIndexPath.cpp; path = source/DataFormatters/NSIndexPath.cpp; sourceTree = "<group>"; };
19881990
944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDummy.cpp; path = Utility/RegisterContextDummy.cpp; sourceTree = "<group>"; };
19891991
944372DB171F6B4300E57C32 /* RegisterContextDummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDummy.h; path = Utility/RegisterContextDummy.h; sourceTree = "<group>"; };
19901992
9443B120140C18A90013457C /* SBData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBData.h; path = include/lldb/API/SBData.h; sourceTree = "<group>"; };
@@ -4327,6 +4329,7 @@
43274329
94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */,
43284330
94D6A0A716CEB55F00833B6E /* NSArray.cpp */,
43294331
94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */,
4332+
9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */,
43304333
94D6A0A916CEB55F00833B6E /* NSSet.cpp */,
43314334
94CB256816B096F90059775D /* TypeCategory.h */,
43324335
94CB256416B096F10059775D /* TypeCategory.cpp */,
@@ -5079,6 +5082,7 @@
50795082
94D0B10D16D5535900EA9C70 /* LibStdcpp.cpp in Sources */,
50805083
AF0E22F018A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp in Sources */,
50815084
2689004E13353E0400698AC0 /* Stream.cpp in Sources */,
5085+
9439FB1A19EF140C006FD6A4 /* NSIndexPath.cpp in Sources */,
50825086
2689004F13353E0400698AC0 /* StreamFile.cpp in Sources */,
50835087
2689005013353E0400698AC0 /* StreamString.cpp in Sources */,
50845088
2689005113353E0400698AC0 /* StringList.cpp in Sources */,

lldb/source/Core/ValueObjectConstResult.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope
230230
{
231231
m_value = value;
232232
m_value.GetData(m_data);
233+
m_name = name;
233234
}
234235

235236
ValueObjectConstResult::~ValueObjectConstResult()

lldb/source/DataFormatters/FormatManager.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,8 @@ FormatManager::LoadObjCFormatters()
13941394
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags());
13951395
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags());
13961396
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags());
1397+
1398+
AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags());
13971399

13981400
AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
13991401
AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
//===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
11+
12+
#include "lldb/Core/ValueObject.h"
13+
#include "lldb/Core/ValueObjectConstResult.h"
14+
#include "lldb/DataFormatters/TypeSynthetic.h"
15+
#include "lldb/Target/ObjCLanguageRuntime.h"
16+
#include "lldb/Target/Process.h"
17+
#include "lldb/Symbol/ClangASTContext.h"
18+
19+
using namespace lldb;
20+
using namespace lldb_private;
21+
using namespace lldb_private::formatters;
22+
23+
class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd
24+
{
25+
public:
26+
NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
27+
SyntheticChildrenFrontEnd (*valobj_sp.get()),
28+
m_ptr_size(0),
29+
m_ast_ctx(nullptr),
30+
m_uint_star_type()
31+
{
32+
m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
33+
}
34+
35+
virtual size_t
36+
CalculateNumChildren ()
37+
{
38+
return m_impl.GetNumIndexes();
39+
}
40+
41+
virtual lldb::ValueObjectSP
42+
GetChildAtIndex (size_t idx)
43+
{
44+
return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
45+
}
46+
47+
virtual bool
48+
Update()
49+
{
50+
m_impl.m_mode = Mode::Invalid;
51+
52+
m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext());
53+
if (!m_ast_ctx)
54+
return false;
55+
56+
m_uint_star_type = m_ast_ctx->GetPointerSizedIntType(false);
57+
58+
static ConstString g__indexes("_indexes");
59+
static ConstString g__length("_length");
60+
61+
ProcessSP process_sp = m_backend.GetProcessSP();
62+
if (!process_sp)
63+
return false;
64+
65+
ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
66+
67+
if (!runtime)
68+
return false;
69+
70+
ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend));
71+
72+
if (!descriptor.get() || !descriptor->IsValid())
73+
return false;
74+
75+
uint64_t info_bits(0),value_bits(0),payload(0);
76+
77+
if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
78+
{
79+
m_impl.m_mode = Mode::Inlined;
80+
m_impl.m_inlined.SetIndexes(payload, *process_sp);
81+
}
82+
else
83+
{
84+
ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id;
85+
ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id;
86+
87+
bool has_indexes(false),has_length(false);
88+
89+
for (auto x = 0;
90+
x < descriptor->GetNumIVars();
91+
x++)
92+
{
93+
const auto& ivar = descriptor->GetIVarAtIndex(x);
94+
if (ivar.m_name == g__indexes)
95+
{
96+
_indexes_id = ivar;
97+
has_indexes = true;
98+
}
99+
else if (ivar.m_name == g__length)
100+
{
101+
_length_id = ivar;
102+
has_length = true;
103+
}
104+
105+
if (has_length && has_indexes)
106+
break;
107+
}
108+
109+
if (has_length && has_indexes)
110+
{
111+
m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset,
112+
m_uint_star_type.GetPointerType(),
113+
true).get();
114+
ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset,
115+
m_uint_star_type,
116+
true));
117+
if (length_sp)
118+
{
119+
m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
120+
if (m_impl.m_outsourced.m_indexes)
121+
m_impl.m_mode = Mode::Outsourced;
122+
}
123+
}
124+
}
125+
return false;
126+
}
127+
128+
virtual bool
129+
MightHaveChildren ()
130+
{
131+
if (m_impl.m_mode == Mode::Invalid)
132+
return false;
133+
return true;
134+
}
135+
136+
virtual size_t
137+
GetIndexOfChildWithName (const ConstString &name)
138+
{
139+
const char* item_name = name.GetCString();
140+
uint32_t idx = ExtractIndexFromString(item_name);
141+
if (idx < UINT32_MAX && idx >= CalculateNumChildren())
142+
return UINT32_MAX;
143+
return idx;
144+
}
145+
146+
virtual lldb::ValueObjectSP
147+
GetSyntheticValue () { return nullptr; }
148+
149+
virtual
150+
~NSIndexPathSyntheticFrontEnd () {}
151+
152+
protected:
153+
ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
154+
155+
enum class Mode {
156+
Inlined,
157+
Outsourced,
158+
Invalid
159+
};
160+
161+
struct Impl {
162+
Mode m_mode;
163+
164+
size_t
165+
GetNumIndexes ()
166+
{
167+
switch (m_mode)
168+
{
169+
case Mode::Inlined:
170+
return m_inlined.GetNumIndexes();
171+
case Mode::Outsourced:
172+
return m_outsourced.m_count;
173+
default:
174+
return 0;
175+
}
176+
}
177+
178+
lldb::ValueObjectSP
179+
GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
180+
{
181+
if (idx >= GetNumIndexes())
182+
return nullptr;
183+
switch (m_mode)
184+
{
185+
default: return nullptr;
186+
case Mode::Inlined:
187+
return m_inlined.GetIndexAtIndex (idx, desired_type);
188+
case Mode::Outsourced:
189+
return m_outsourced.GetIndexAtIndex (idx);
190+
}
191+
}
192+
193+
union {
194+
struct {
195+
public:
196+
void SetIndexes(uint64_t value, Process& p)
197+
{
198+
m_indexes = value;
199+
_lengthForInlinePayload(p.GetAddressByteSize());
200+
m_process = &p;
201+
}
202+
203+
size_t
204+
GetNumIndexes ()
205+
{
206+
return m_count;
207+
}
208+
209+
lldb::ValueObjectSP
210+
GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
211+
{
212+
std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
213+
if (!value.second)
214+
return nullptr;
215+
Value v;
216+
if (m_ptr_size == 8)
217+
{
218+
Scalar scalar( (unsigned long long)value.first );
219+
v = Value(scalar);
220+
}
221+
else
222+
{
223+
Scalar scalar( (unsigned int)value.first );
224+
v = Value(scalar);
225+
}
226+
v.SetClangType(desired_type);
227+
StreamString idx_name;
228+
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
229+
return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
230+
}
231+
232+
private:
233+
uint64_t m_indexes;
234+
size_t m_count;
235+
uint32_t m_ptr_size;
236+
Process *m_process;
237+
238+
// cfr. Foundation for the details of this code
239+
size_t _lengthForInlinePayload(uint32_t ptr_size) {
240+
m_ptr_size = ptr_size;
241+
if (m_ptr_size == 8)
242+
m_count = ((m_indexes >> 3) & 0x7);
243+
else
244+
m_count = ((m_indexes >> 3) & 0x3);
245+
return m_count;
246+
}
247+
248+
std::pair<uint64_t, bool>
249+
_indexAtPositionForInlinePayload(size_t pos) {
250+
if (m_ptr_size == 8)
251+
{
252+
switch (pos) {
253+
case 5: return {((m_indexes >> 51) & 0x1ff),true};
254+
case 4: return {((m_indexes >> 42) & 0x1ff),true};
255+
case 3: return {((m_indexes >> 33) & 0x1ff),true};
256+
case 2: return {((m_indexes >> 24) & 0x1ff),true};
257+
case 1: return {((m_indexes >> 15) & 0x1ff),true};
258+
case 0: return {((m_indexes >> 6) & 0x1ff),true};
259+
}
260+
}
261+
else
262+
{
263+
switch (pos) {
264+
case 2: return {((m_indexes >> 23) & 0x1ff),true};
265+
case 1: return {((m_indexes >> 14) & 0x1ff),true};
266+
case 0: return {((m_indexes >> 5) & 0x1ff),true};
267+
}
268+
}
269+
return {0,false};
270+
}
271+
272+
} m_inlined;
273+
struct {
274+
ValueObject *m_indexes;
275+
size_t m_count;
276+
277+
lldb::ValueObjectSP
278+
GetIndexAtIndex (size_t idx)
279+
{
280+
if (m_indexes)
281+
{
282+
ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMemberFromPointer(idx, true));
283+
return index_sp;
284+
}
285+
return nullptr;
286+
}
287+
} m_outsourced;
288+
};
289+
} m_impl;
290+
291+
uint32_t m_ptr_size;
292+
ClangASTContext* m_ast_ctx;
293+
ClangASTType m_uint_star_type;
294+
};
295+
296+
namespace lldb_private {
297+
namespace formatters {
298+
299+
SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
300+
{
301+
if (valobj_sp)
302+
return new NSIndexPathSyntheticFrontEnd(valobj_sp);
303+
return nullptr;
304+
}
305+
}
306+
}

0 commit comments

Comments
 (0)