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