]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/DataFormatters/NSIndexPath.cpp
Update libc++ to 3.7.0 release.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / DataFormatters / NSIndexPath.cpp
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.Clear();
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_inlined.SetIndexes(payload, *process_sp);
80             m_impl.m_mode = Mode::Inlined;
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 (size_t 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         struct InlinedIndexes {
194         public:
195           void SetIndexes(uint64_t value, Process& p)
196           {
197               m_indexes = value;
198               _lengthForInlinePayload(p.GetAddressByteSize());
199               m_process = &p;
200           }
201               
202           size_t
203           GetNumIndexes ()
204           {
205               return m_count;
206           }
207
208           lldb::ValueObjectSP
209           GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
210           {
211               std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
212               if (!value.second)
213                   return nullptr;
214               
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
227               v.SetClangType(desired_type);
228
229               StreamString idx_name;
230               idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
231
232               return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
233           }
234             
235             void
236             Clear ()
237             {
238                 m_indexes = 0;
239                 m_count = 0;
240                 m_ptr_size = 0;
241                 m_process = nullptr;
242             }
243                     
244           private:
245           uint64_t m_indexes;
246           size_t m_count;
247           uint32_t m_ptr_size;
248           Process *m_process;
249                     
250           // cfr. Foundation for the details of this code
251           size_t _lengthForInlinePayload(uint32_t ptr_size) {
252               m_ptr_size = ptr_size;
253               if (m_ptr_size == 8)
254               m_count = ((m_indexes >> 3) & 0x7);
255               else
256               m_count = ((m_indexes >> 3) & 0x3);
257               return m_count;
258           }
259                     
260           std::pair<uint64_t, bool>
261           _indexAtPositionForInlinePayload(size_t pos)
262           {
263               if (m_ptr_size == 8)
264               {
265                 switch (pos) {
266                     case 5: return {((m_indexes >> 51) & 0x1ff),true};
267                     case 4: return {((m_indexes >> 42) & 0x1ff),true};
268                     case 3: return {((m_indexes >> 33) & 0x1ff),true};
269                     case 2: return {((m_indexes >> 24) & 0x1ff),true};
270                     case 1: return {((m_indexes >> 15) & 0x1ff),true};
271                     case 0: return {((m_indexes >>  6) & 0x1ff),true};
272                 }
273               }
274               else
275                   {
276                   switch (pos) {
277                       case 2: return {((m_indexes >> 23) & 0x1ff),true};
278                       case 1: return {((m_indexes >> 14) & 0x1ff),true};
279                       case 0: return {((m_indexes >>  5) & 0x1ff),true};
280                   }
281               }
282               return {0,false};
283           }
284
285         };
286         struct OutsourcedIndexes {
287             ValueObject *m_indexes;
288             size_t m_count;
289                     
290             lldb::ValueObjectSP
291             GetIndexAtIndex (size_t idx)
292             {
293                 if (m_indexes)
294                 {
295                     ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true));
296                     return index_sp;
297                 }
298                 return nullptr;
299             }
300             
301             void
302             Clear ()
303             {
304                 m_indexes = nullptr;
305                 m_count = 0;
306             }
307         };
308
309         union {
310             struct InlinedIndexes m_inlined;
311             struct OutsourcedIndexes m_outsourced;
312         };
313         
314         void
315         Clear ()
316         {
317             m_mode = Mode::Invalid;
318             m_inlined.Clear();
319             m_outsourced.Clear();
320         }
321     } m_impl;
322     
323     uint32_t m_ptr_size;
324     ClangASTContext* m_ast_ctx;
325     ClangASTType m_uint_star_type;
326 };
327
328 namespace lldb_private {
329     namespace formatters {
330         
331         SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
332         {
333             if (valobj_sp)
334                 return new NSIndexPathSyntheticFrontEnd(valobj_sp);
335             return nullptr;
336         }
337     }
338 }