• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- TypeSynthetic.h -------------------------------------------*- 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 #ifndef lldb_TypeSynthetic_h_
11 #define lldb_TypeSynthetic_h_
12 
13 // C Includes
14 #include <stdint.h>
15 #include <unistd.h>
16 
17 // C++ Includes
18 #include <string>
19 #include <vector>
20 
21 // Other libraries and framework includes
22 
23 // Project includes
24 #include "lldb/lldb-public.h"
25 #include "lldb/lldb-enumerations.h"
26 
27 #include "lldb/Core/ValueObject.h"
28 #include "lldb/Interpreter/ScriptInterpreterPython.h"
29 #include "lldb/Symbol/Type.h"
30 
31 namespace lldb_private {
32     class SyntheticChildrenFrontEnd
33     {
34     protected:
35         ValueObject &m_backend;
36     public:
37 
SyntheticChildrenFrontEnd(ValueObject & backend)38         SyntheticChildrenFrontEnd (ValueObject &backend) :
39         m_backend(backend)
40         {}
41 
42         virtual
~SyntheticChildrenFrontEnd()43         ~SyntheticChildrenFrontEnd ()
44         {
45         }
46 
47         virtual size_t
48         CalculateNumChildren () = 0;
49 
50         virtual lldb::ValueObjectSP
51         GetChildAtIndex (size_t idx) = 0;
52 
53         virtual size_t
54         GetIndexOfChildWithName (const ConstString &name) = 0;
55 
56         // this function is assumed to always succeed and it if fails, the front-end should know to deal
57         // with it in the correct way (most probably, by refusing to return any children)
58         // the return value of Update() should actually be interpreted as "ValueObjectSyntheticFilter cache is good/bad"
59         // if =true, ValueObjectSyntheticFilter is allowed to use the children it fetched previously and cached
60         // if =false, ValueObjectSyntheticFilter must throw away its cache, and query again for children
61         virtual bool
62         Update () = 0;
63 
64         // if this function returns false, then CalculateNumChildren() MUST return 0 since UI frontends
65         // might validly decide not to inquire for children given a false return value from this call
66         // if it returns true, then CalculateNumChildren() can return any number >= 0 (0 being valid)
67         // it should if at all possible be more efficient than CalculateNumChildren()
68         virtual bool
69         MightHaveChildren () = 0;
70 
71         typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
72         typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
73 
74     private:
75         DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd);
76     };
77 
78     class SyntheticChildren
79     {
80     public:
81 
82         class Flags
83         {
84         public:
85 
Flags()86             Flags () :
87             m_flags (lldb::eTypeOptionCascade)
88             {}
89 
Flags(const Flags & other)90             Flags (const Flags& other) :
91             m_flags (other.m_flags)
92             {}
93 
Flags(uint32_t value)94             Flags (uint32_t value) :
95             m_flags (value)
96             {}
97 
98             Flags&
99             operator = (const Flags& rhs)
100             {
101                 if (&rhs != this)
102                     m_flags = rhs.m_flags;
103 
104                 return *this;
105             }
106 
107             Flags&
108             operator = (const uint32_t& rhs)
109             {
110                 m_flags = rhs;
111                 return *this;
112             }
113 
114             Flags&
Clear()115             Clear()
116             {
117                 m_flags = 0;
118                 return *this;
119             }
120 
121             bool
GetCascades()122             GetCascades () const
123             {
124                 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
125             }
126 
127             Flags&
128             SetCascades (bool value = true)
129             {
130                 if (value)
131                     m_flags |= lldb::eTypeOptionCascade;
132                 else
133                     m_flags &= ~lldb::eTypeOptionCascade;
134                 return *this;
135             }
136 
137             bool
GetSkipPointers()138             GetSkipPointers () const
139             {
140                 return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers;
141             }
142 
143             Flags&
144             SetSkipPointers (bool value = true)
145             {
146                 if (value)
147                     m_flags |= lldb::eTypeOptionSkipPointers;
148                 else
149                     m_flags &= ~lldb::eTypeOptionSkipPointers;
150                 return *this;
151             }
152 
153             bool
GetSkipReferences()154             GetSkipReferences () const
155             {
156                 return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences;
157             }
158 
159             Flags&
160             SetSkipReferences (bool value = true)
161             {
162                 if (value)
163                     m_flags |= lldb::eTypeOptionSkipReferences;
164                 else
165                     m_flags &= ~lldb::eTypeOptionSkipReferences;
166                 return *this;
167             }
168 
169             uint32_t
GetValue()170             GetValue ()
171             {
172                 return m_flags;
173             }
174 
175             void
SetValue(uint32_t value)176             SetValue (uint32_t value)
177             {
178                 m_flags = value;
179             }
180 
181         private:
182             uint32_t m_flags;
183         };
184 
SyntheticChildren(const Flags & flags)185         SyntheticChildren (const Flags& flags) :
186         m_flags(flags)
187         {
188         }
189 
190         virtual
~SyntheticChildren()191         ~SyntheticChildren ()
192         {
193         }
194 
195         bool
Cascades()196         Cascades () const
197         {
198             return m_flags.GetCascades();
199         }
200         bool
SkipsPointers()201         SkipsPointers () const
202         {
203             return m_flags.GetSkipPointers();
204         }
205         bool
SkipsReferences()206         SkipsReferences () const
207         {
208             return m_flags.GetSkipReferences();
209         }
210 
211         void
SetCascades(bool value)212         SetCascades (bool value)
213         {
214             m_flags.SetCascades(value);
215         }
216 
217         void
SetSkipsPointers(bool value)218         SetSkipsPointers (bool value)
219         {
220             m_flags.SetSkipPointers(value);
221         }
222 
223         void
SetSkipsReferences(bool value)224         SetSkipsReferences (bool value)
225         {
226             m_flags.SetSkipReferences(value);
227         }
228 
229         uint32_t
GetOptions()230         GetOptions ()
231         {
232             return m_flags.GetValue();
233         }
234 
235         void
SetOptions(uint32_t value)236         SetOptions (uint32_t value)
237         {
238             m_flags.SetValue(value);
239         }
240 
241         virtual bool
242         IsScripted () = 0;
243 
244         virtual std::string
245         GetDescription () = 0;
246 
247         virtual SyntheticChildrenFrontEnd::AutoPointer
248         GetFrontEnd (ValueObject &backend) = 0;
249 
250         typedef std::shared_ptr<SyntheticChildren> SharedPointer;
251         typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&);
252 
253         uint32_t&
GetRevision()254         GetRevision ()
255         {
256             return m_my_revision;
257         }
258 
259     protected:
260         uint32_t m_my_revision;
261         Flags m_flags;
262 
263     private:
264         DISALLOW_COPY_AND_ASSIGN(SyntheticChildren);
265     };
266 
267     class TypeFilterImpl : public SyntheticChildren
268     {
269         std::vector<std::string> m_expression_paths;
270     public:
TypeFilterImpl(const SyntheticChildren::Flags & flags)271         TypeFilterImpl(const SyntheticChildren::Flags& flags) :
272         SyntheticChildren(flags),
273         m_expression_paths()
274         {
275         }
276 
TypeFilterImpl(const SyntheticChildren::Flags & flags,const std::initializer_list<const char * > items)277         TypeFilterImpl(const SyntheticChildren::Flags& flags,
278                        const std::initializer_list<const char*> items) :
279         SyntheticChildren(flags),
280         m_expression_paths()
281         {
282             for (auto path : items)
283                 AddExpressionPath (path);
284         }
285 
286         void
AddExpressionPath(const char * path)287         AddExpressionPath (const char* path)
288         {
289             AddExpressionPath(std::string(path));
290         }
291 
292         void
Clear()293         Clear()
294         {
295             m_expression_paths.clear();
296         }
297 
298         size_t
GetCount()299         GetCount() const
300         {
301             return m_expression_paths.size();
302         }
303 
304         const char*
GetExpressionPathAtIndex(size_t i)305         GetExpressionPathAtIndex(size_t i) const
306         {
307             return m_expression_paths[i].c_str();
308         }
309 
310         bool
SetExpressionPathAtIndex(size_t i,const char * path)311         SetExpressionPathAtIndex (size_t i, const char* path)
312         {
313             return SetExpressionPathAtIndex(i, std::string(path));
314         }
315 
316         void
AddExpressionPath(const std::string & path)317         AddExpressionPath (const std::string& path)
318         {
319             bool need_add_dot = true;
320             if (path[0] == '.' ||
321                 (path[0] == '-' && path[1] == '>') ||
322                 path[0] == '[')
323                 need_add_dot = false;
324             // add a '.' symbol to help forgetful users
325             if(!need_add_dot)
326                 m_expression_paths.push_back(path);
327             else
328                 m_expression_paths.push_back(std::string(".") + path);
329         }
330 
331         bool
SetExpressionPathAtIndex(size_t i,const std::string & path)332         SetExpressionPathAtIndex (size_t i, const std::string& path)
333         {
334             if (i >= GetCount())
335                 return false;
336             bool need_add_dot = true;
337             if (path[0] == '.' ||
338                 (path[0] == '-' && path[1] == '>') ||
339                 path[0] == '[')
340                 need_add_dot = false;
341             // add a '.' symbol to help forgetful users
342             if(!need_add_dot)
343                 m_expression_paths[i] = path;
344             else
345                 m_expression_paths[i] = std::string(".") + path;
346             return true;
347         }
348 
349         bool
IsScripted()350         IsScripted ()
351         {
352             return false;
353         }
354 
355         std::string
356         GetDescription ();
357 
358         class FrontEnd : public SyntheticChildrenFrontEnd
359         {
360         private:
361             TypeFilterImpl* filter;
362         public:
363 
FrontEnd(TypeFilterImpl * flt,ValueObject & backend)364             FrontEnd(TypeFilterImpl* flt,
365                      ValueObject &backend) :
366             SyntheticChildrenFrontEnd(backend),
367             filter(flt)
368             {}
369 
370             virtual
~FrontEnd()371             ~FrontEnd ()
372             {
373             }
374 
375             virtual size_t
CalculateNumChildren()376             CalculateNumChildren ()
377             {
378                 return filter->GetCount();
379             }
380 
381             virtual lldb::ValueObjectSP
GetChildAtIndex(size_t idx)382             GetChildAtIndex (size_t idx)
383             {
384                 if (idx >= filter->GetCount())
385                     return lldb::ValueObjectSP();
386                 return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), true);
387             }
388 
389             virtual bool
Update()390             Update() { return false; }
391 
392             virtual bool
MightHaveChildren()393             MightHaveChildren ()
394             {
395                 return filter->GetCount() > 0;
396             }
397 
398             virtual size_t
GetIndexOfChildWithName(const ConstString & name)399             GetIndexOfChildWithName (const ConstString &name)
400             {
401                 const char* name_cstr = name.GetCString();
402                 for (size_t i = 0; i < filter->GetCount(); i++)
403                 {
404                     const char* expr_cstr = filter->GetExpressionPathAtIndex(i);
405                     if (expr_cstr)
406                     {
407                         if (*expr_cstr == '.')
408                             expr_cstr++;
409                         else if (*expr_cstr == '-' && *(expr_cstr+1) == '>')
410                             expr_cstr += 2;
411                     }
412                     if (!::strcmp(name_cstr, expr_cstr))
413                         return i;
414                 }
415                 return UINT32_MAX;
416             }
417 
418             typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
419 
420         private:
421             DISALLOW_COPY_AND_ASSIGN(FrontEnd);
422         };
423 
424         virtual SyntheticChildrenFrontEnd::AutoPointer
GetFrontEnd(ValueObject & backend)425         GetFrontEnd(ValueObject &backend)
426         {
427             return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
428         }
429 
430     private:
431         DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl);
432     };
433 
434     class CXXSyntheticChildren : public SyntheticChildren
435     {
436     public:
437         typedef SyntheticChildrenFrontEnd* (*CreateFrontEndCallback) (CXXSyntheticChildren*, lldb::ValueObjectSP);
438     protected:
439         CreateFrontEndCallback m_create_callback;
440         std::string m_description;
441     public:
CXXSyntheticChildren(const SyntheticChildren::Flags & flags,const char * description,CreateFrontEndCallback callback)442         CXXSyntheticChildren (const SyntheticChildren::Flags& flags,
443                               const char* description,
444                               CreateFrontEndCallback callback) :
445         SyntheticChildren(flags),
446         m_create_callback(callback),
447         m_description(description ? description : "")
448         {
449         }
450 
451         bool
IsScripted()452         IsScripted ()
453         {
454             return false;
455         }
456 
457         std::string
458         GetDescription ();
459 
460         virtual SyntheticChildrenFrontEnd::AutoPointer
GetFrontEnd(ValueObject & backend)461         GetFrontEnd (ValueObject &backend)
462         {
463             return SyntheticChildrenFrontEnd::AutoPointer(m_create_callback(this, backend.GetSP()));
464         }
465 
466     private:
467         DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren);
468     };
469 
470 #ifndef LLDB_DISABLE_PYTHON
471 
472     class ScriptedSyntheticChildren : public SyntheticChildren
473     {
474         std::string m_python_class;
475         std::string m_python_code;
476     public:
477 
478         ScriptedSyntheticChildren (const SyntheticChildren::Flags& flags,
479                                    const char* pclass,
480                                    const char* pcode = NULL) :
SyntheticChildren(flags)481         SyntheticChildren(flags),
482         m_python_class(),
483         m_python_code()
484         {
485             if (pclass)
486                 m_python_class = pclass;
487             if (pcode)
488                 m_python_code = pcode;
489         }
490 
491         const char*
GetPythonClassName()492         GetPythonClassName ()
493         {
494             return m_python_class.c_str();
495         }
496 
497         const char*
GetPythonCode()498         GetPythonCode ()
499         {
500             return m_python_code.c_str();
501         }
502 
503         void
SetPythonClassName(const char * fname)504         SetPythonClassName (const char* fname)
505         {
506             m_python_class.assign(fname);
507             m_python_code.clear();
508         }
509 
510         void
SetPythonCode(const char * script)511         SetPythonCode (const char* script)
512         {
513             m_python_code.assign(script);
514         }
515 
516         std::string
517         GetDescription ();
518 
519         bool
IsScripted()520         IsScripted ()
521         {
522             return true;
523         }
524 
525         class FrontEnd : public SyntheticChildrenFrontEnd
526         {
527         private:
528             std::string m_python_class;
529             lldb::ScriptInterpreterObjectSP m_wrapper_sp;
530             ScriptInterpreter *m_interpreter;
531         public:
532 
533             FrontEnd (std::string pclass,
534                       ValueObject &backend);
535 
536             virtual
537             ~FrontEnd ();
538 
539             virtual size_t
CalculateNumChildren()540             CalculateNumChildren ()
541             {
542                 if (!m_wrapper_sp || m_interpreter == NULL)
543                     return 0;
544                 return m_interpreter->CalculateNumChildren(m_wrapper_sp);
545             }
546 
547             virtual lldb::ValueObjectSP
548             GetChildAtIndex (size_t idx);
549 
550             virtual bool
Update()551             Update ()
552             {
553                 if (!m_wrapper_sp || m_interpreter == NULL)
554                     return false;
555 
556                 return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp);
557             }
558 
559             virtual bool
MightHaveChildren()560             MightHaveChildren ()
561             {
562                 if (!m_wrapper_sp || m_interpreter == NULL)
563                     return false;
564 
565                 return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp);
566             }
567 
568             virtual size_t
GetIndexOfChildWithName(const ConstString & name)569             GetIndexOfChildWithName (const ConstString &name)
570             {
571                 if (!m_wrapper_sp || m_interpreter == NULL)
572                     return UINT32_MAX;
573                 return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString());
574             }
575 
576             typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
577 
578         private:
579             DISALLOW_COPY_AND_ASSIGN(FrontEnd);
580         };
581 
582         virtual SyntheticChildrenFrontEnd::AutoPointer
GetFrontEnd(ValueObject & backend)583         GetFrontEnd(ValueObject &backend)
584         {
585             return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend));
586         }
587 
588     private:
589         DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren);
590     };
591 #endif
592 } // namespace lldb_private
593 
594 #endif	// lldb_TypeSynthetic_h_
595