xref: /freebsd/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeSynthetic.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- TypeSynthetic.h -----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
10 #define LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
11 
12 #include <cstdint>
13 
14 #include <functional>
15 #include <initializer_list>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 #include "lldb/lldb-enumerations.h"
21 #include "lldb/lldb-public.h"
22 
23 #include "lldb/Core/ValueObject.h"
24 #include "lldb/Utility/StructuredData.h"
25 
26 namespace lldb_private {
27 class SyntheticChildrenFrontEnd {
28 protected:
29   ValueObject &m_backend;
30 
SetValid(bool valid)31   void SetValid(bool valid) { m_valid = valid; }
32 
IsValid()33   bool IsValid() { return m_valid; }
34 
35 public:
SyntheticChildrenFrontEnd(ValueObject & backend)36   SyntheticChildrenFrontEnd(ValueObject &backend)
37       : m_backend(backend), m_valid(true) {}
38 
39   virtual ~SyntheticChildrenFrontEnd() = default;
40 
41   virtual llvm::Expected<uint32_t> CalculateNumChildren() = 0;
42 
CalculateNumChildren(uint32_t max)43   virtual llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) {
44     auto count = CalculateNumChildren();
45     if (!count)
46       return count;
47     return *count <= max ? *count : max;
48   }
49 
50   uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max = UINT32_MAX);
51 
52   virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) = 0;
53 
54   virtual size_t GetIndexOfChildWithName(ConstString name) = 0;
55 
56   /// This function is assumed to always succeed and if it fails, the front-end
57   /// should know to deal with it in the correct way (most probably, by refusing
58   /// to return any children). The return value of \ref Update should actually
59   /// be interpreted as "ValueObjectSyntheticFilter cache is good/bad". If this
60   /// function returns \ref lldb::ChildCacheState::eReuse, \ref
61   /// ValueObjectSyntheticFilter is allowed to use the children it fetched
62   /// previously and cached. Otherwise, \ref ValueObjectSyntheticFilter must
63   /// throw away its cache, and query again for children.
64   virtual lldb::ChildCacheState Update() = 0;
65 
66   // if this function returns false, then CalculateNumChildren() MUST return 0
67   // since UI frontends might validly decide not to inquire for children given
68   // a false return value from this call if it returns true, then
69   // CalculateNumChildren() can return any number >= 0 (0 being valid) it
70   // should if at all possible be more efficient than CalculateNumChildren()
71   virtual bool MightHaveChildren() = 0;
72 
73   // if this function returns a non-null ValueObject, then the returned
74   // ValueObject will stand for this ValueObject whenever a "value" request is
75   // made to this ValueObject
GetSyntheticValue()76   virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
77 
78   // if this function returns a non-empty ConstString, then clients are
79   // expected to use the return as the name of the type of this ValueObject for
80   // display purposes
GetSyntheticTypeName()81   virtual ConstString GetSyntheticTypeName() { return ConstString(); }
82 
83   typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
84   typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
85 
86 protected:
87   lldb::ValueObjectSP
88   CreateValueObjectFromExpression(llvm::StringRef name,
89                                   llvm::StringRef expression,
90                                   const ExecutionContext &exe_ctx);
91 
92   lldb::ValueObjectSP
93   CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
94                                const ExecutionContext &exe_ctx,
95                                CompilerType type);
96 
97   lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name,
98                                                 const DataExtractor &data,
99                                                 const ExecutionContext &exe_ctx,
100                                                 CompilerType type);
101 
102 private:
103   bool m_valid;
104   SyntheticChildrenFrontEnd(const SyntheticChildrenFrontEnd &) = delete;
105   const SyntheticChildrenFrontEnd &
106   operator=(const SyntheticChildrenFrontEnd &) = delete;
107 };
108 
109 class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
110 public:
SyntheticValueProviderFrontEnd(ValueObject & backend)111   SyntheticValueProviderFrontEnd(ValueObject &backend)
112       : SyntheticChildrenFrontEnd(backend) {}
113 
114   ~SyntheticValueProviderFrontEnd() override = default;
115 
CalculateNumChildren()116   llvm::Expected<uint32_t> CalculateNumChildren() override { return 0; }
117 
GetChildAtIndex(uint32_t idx)118   lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override { return nullptr; }
119 
GetIndexOfChildWithName(ConstString name)120   size_t GetIndexOfChildWithName(ConstString name) override {
121     return UINT32_MAX;
122   }
123 
Update()124   lldb::ChildCacheState Update() override {
125     return lldb::ChildCacheState::eRefetch;
126   }
127 
MightHaveChildren()128   bool MightHaveChildren() override { return false; }
129 
130   lldb::ValueObjectSP GetSyntheticValue() override = 0;
131 
132 private:
133   SyntheticValueProviderFrontEnd(const SyntheticValueProviderFrontEnd &) =
134       delete;
135   const SyntheticValueProviderFrontEnd &
136   operator=(const SyntheticValueProviderFrontEnd &) = delete;
137 };
138 
139 class SyntheticChildren {
140 public:
141   class Flags {
142   public:
143     Flags() = default;
144 
Flags(const Flags & other)145     Flags(const Flags &other) : m_flags(other.m_flags) {}
146 
Flags(uint32_t value)147     Flags(uint32_t value) : m_flags(value) {}
148 
149     Flags &operator=(const Flags &rhs) {
150       if (&rhs != this)
151         m_flags = rhs.m_flags;
152 
153       return *this;
154     }
155 
156     Flags &operator=(const uint32_t &rhs) {
157       m_flags = rhs;
158       return *this;
159     }
160 
Clear()161     Flags &Clear() {
162       m_flags = 0;
163       return *this;
164     }
165 
GetCascades()166     bool GetCascades() const {
167       return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
168     }
169 
170     Flags &SetCascades(bool value = true) {
171       if (value)
172         m_flags |= lldb::eTypeOptionCascade;
173       else
174         m_flags &= ~lldb::eTypeOptionCascade;
175       return *this;
176     }
177 
GetSkipPointers()178     bool GetSkipPointers() const {
179       return (m_flags & lldb::eTypeOptionSkipPointers) ==
180              lldb::eTypeOptionSkipPointers;
181     }
182 
183     Flags &SetSkipPointers(bool value = true) {
184       if (value)
185         m_flags |= lldb::eTypeOptionSkipPointers;
186       else
187         m_flags &= ~lldb::eTypeOptionSkipPointers;
188       return *this;
189     }
190 
GetSkipReferences()191     bool GetSkipReferences() const {
192       return (m_flags & lldb::eTypeOptionSkipReferences) ==
193              lldb::eTypeOptionSkipReferences;
194     }
195 
196     Flags &SetSkipReferences(bool value = true) {
197       if (value)
198         m_flags |= lldb::eTypeOptionSkipReferences;
199       else
200         m_flags &= ~lldb::eTypeOptionSkipReferences;
201       return *this;
202     }
203 
GetNonCacheable()204     bool GetNonCacheable() const {
205       return (m_flags & lldb::eTypeOptionNonCacheable) ==
206              lldb::eTypeOptionNonCacheable;
207     }
208 
209     Flags &SetNonCacheable(bool value = true) {
210       if (value)
211         m_flags |= lldb::eTypeOptionNonCacheable;
212       else
213         m_flags &= ~lldb::eTypeOptionNonCacheable;
214       return *this;
215     }
216 
GetFrontEndWantsDereference()217     bool GetFrontEndWantsDereference() const {
218       return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
219              lldb::eTypeOptionFrontEndWantsDereference;
220     }
221 
222     Flags &SetFrontEndWantsDereference(bool value = true) {
223       if (value)
224         m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
225       else
226         m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
227       return *this;
228     }
229 
GetValue()230     uint32_t GetValue() { return m_flags; }
231 
SetValue(uint32_t value)232     void SetValue(uint32_t value) { m_flags = value; }
233 
234   private:
235     uint32_t m_flags = lldb::eTypeOptionCascade;
236   };
237 
238   SyntheticChildren(const Flags &flags);
239 
240   virtual ~SyntheticChildren();
241 
Cascades()242   bool Cascades() const { return m_flags.GetCascades(); }
243 
SkipsPointers()244   bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
245 
SkipsReferences()246   bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
247 
NonCacheable()248   bool NonCacheable() const { return m_flags.GetNonCacheable(); }
249 
WantsDereference()250   bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
251 
SetCascades(bool value)252   void SetCascades(bool value) { m_flags.SetCascades(value); }
253 
SetSkipsPointers(bool value)254   void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
255 
SetSkipsReferences(bool value)256   void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
257 
SetNonCacheable(bool value)258   void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
259 
GetOptions()260   uint32_t GetOptions() { return m_flags.GetValue(); }
261 
SetOptions(uint32_t value)262   void SetOptions(uint32_t value) { m_flags.SetValue(value); }
263 
264   virtual bool IsScripted() = 0;
265 
266   virtual std::string GetDescription() = 0;
267 
268   virtual SyntheticChildrenFrontEnd::AutoPointer
269   GetFrontEnd(ValueObject &backend) = 0;
270 
271   typedef std::shared_ptr<SyntheticChildren> SharedPointer;
272 
GetRevision()273   uint32_t &GetRevision() { return m_my_revision; }
274 
275 protected:
276   uint32_t m_my_revision = 0;
277   Flags m_flags;
278 
279 private:
280   SyntheticChildren(const SyntheticChildren &) = delete;
281   const SyntheticChildren &operator=(const SyntheticChildren &) = delete;
282 };
283 
284 class TypeFilterImpl : public SyntheticChildren {
285   std::vector<std::string> m_expression_paths;
286 
287 public:
TypeFilterImpl(const SyntheticChildren::Flags & flags)288   TypeFilterImpl(const SyntheticChildren::Flags &flags)
289       : SyntheticChildren(flags) {}
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     for (auto path : items)
295       AddExpressionPath(path);
296   }
297 
AddExpressionPath(const char * path)298   void AddExpressionPath(const char *path) {
299     AddExpressionPath(std::string(path));
300   }
301 
Clear()302   void Clear() { m_expression_paths.clear(); }
303 
GetCount()304   size_t GetCount() const { return m_expression_paths.size(); }
305 
GetExpressionPathAtIndex(size_t i)306   const char *GetExpressionPathAtIndex(size_t i) const {
307     return m_expression_paths[i].c_str();
308   }
309 
SetExpressionPathAtIndex(size_t i,const char * path)310   bool SetExpressionPathAtIndex(size_t i, const char *path) {
311     return SetExpressionPathAtIndex(i, std::string(path));
312   }
313 
314   void AddExpressionPath(const std::string &path);
315 
316   bool SetExpressionPathAtIndex(size_t i, const std::string &path);
317 
IsScripted()318   bool IsScripted() override { return false; }
319 
320   std::string GetDescription() override;
321 
322   class FrontEnd : public SyntheticChildrenFrontEnd {
323   public:
FrontEnd(TypeFilterImpl * flt,ValueObject & backend)324     FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
325         : SyntheticChildrenFrontEnd(backend), filter(flt) {}
326 
327     ~FrontEnd() override = default;
328 
CalculateNumChildren()329     llvm::Expected<uint32_t> CalculateNumChildren() override {
330       return filter->GetCount();
331     }
332 
GetChildAtIndex(uint32_t idx)333     lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
334       if (idx >= filter->GetCount())
335         return lldb::ValueObjectSP();
336       return m_backend.GetSyntheticExpressionPathChild(
337           filter->GetExpressionPathAtIndex(idx), true);
338     }
339 
Update()340     lldb::ChildCacheState Update() override {
341       return lldb::ChildCacheState::eRefetch;
342     }
343 
MightHaveChildren()344     bool MightHaveChildren() override { return filter->GetCount() > 0; }
345 
346     size_t GetIndexOfChildWithName(ConstString name) override;
347 
348     typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
349 
350   private:
351     TypeFilterImpl *filter;
352 
353     FrontEnd(const FrontEnd &) = delete;
354     const FrontEnd &operator=(const FrontEnd &) = delete;
355   };
356 
357   SyntheticChildrenFrontEnd::AutoPointer
GetFrontEnd(ValueObject & backend)358   GetFrontEnd(ValueObject &backend) override {
359     return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
360   }
361 
362   typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
363 
364 private:
365   TypeFilterImpl(const TypeFilterImpl &) = delete;
366   const TypeFilterImpl &operator=(const TypeFilterImpl &) = delete;
367 };
368 
369 class CXXSyntheticChildren : public SyntheticChildren {
370 public:
371   typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
372                                                     lldb::ValueObjectSP)>
373       CreateFrontEndCallback;
374   CXXSyntheticChildren(const SyntheticChildren::Flags &flags,
375                        const char *description, CreateFrontEndCallback callback);
376 
377   virtual ~CXXSyntheticChildren();
378 
IsScripted()379   bool IsScripted() override { return false; }
380 
381   std::string GetDescription() override;
382 
383   SyntheticChildrenFrontEnd::AutoPointer
GetFrontEnd(ValueObject & backend)384   GetFrontEnd(ValueObject &backend) override {
385     return SyntheticChildrenFrontEnd::AutoPointer(
386         m_create_callback(this, backend.GetSP()));
387   }
388 
389 protected:
390   CreateFrontEndCallback m_create_callback;
391   std::string m_description;
392 
393 private:
394   CXXSyntheticChildren(const CXXSyntheticChildren &) = delete;
395   const CXXSyntheticChildren &operator=(const CXXSyntheticChildren &) = delete;
396 };
397 
398 class ScriptedSyntheticChildren : public SyntheticChildren {
399   std::string m_python_class;
400   std::string m_python_code;
401 
402 public:
403   ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags,
404                             const char *pclass, const char *pcode = nullptr)
SyntheticChildren(flags)405       : SyntheticChildren(flags) {
406     if (pclass)
407       m_python_class = pclass;
408     if (pcode)
409       m_python_code = pcode;
410   }
411 
GetPythonClassName()412   const char *GetPythonClassName() { return m_python_class.c_str(); }
413 
GetPythonCode()414   const char *GetPythonCode() { return m_python_code.c_str(); }
415 
SetPythonClassName(const char * fname)416   void SetPythonClassName(const char *fname) {
417     m_python_class.assign(fname);
418     m_python_code.clear();
419   }
420 
SetPythonCode(const char * script)421   void SetPythonCode(const char *script) { m_python_code.assign(script); }
422 
423   std::string GetDescription() override;
424 
IsScripted()425   bool IsScripted() override { return true; }
426 
427   class FrontEnd : public SyntheticChildrenFrontEnd {
428   public:
429     FrontEnd(std::string pclass, ValueObject &backend);
430 
431     ~FrontEnd() override;
432 
433     bool IsValid();
434 
435     llvm::Expected<uint32_t> CalculateNumChildren() override;
436 
437     llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
438 
439     lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
440 
441     lldb::ChildCacheState Update() override;
442 
443     bool MightHaveChildren() override;
444 
445     size_t GetIndexOfChildWithName(ConstString name) override;
446 
447     lldb::ValueObjectSP GetSyntheticValue() override;
448 
449     ConstString GetSyntheticTypeName() override;
450 
451     typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
452 
453   private:
454     std::string m_python_class;
455     StructuredData::ObjectSP m_wrapper_sp;
456     ScriptInterpreter *m_interpreter;
457 
458     FrontEnd(const FrontEnd &) = delete;
459     const FrontEnd &operator=(const FrontEnd &) = delete;
460   };
461 
462   SyntheticChildrenFrontEnd::AutoPointer
GetFrontEnd(ValueObject & backend)463   GetFrontEnd(ValueObject &backend) override {
464     auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(
465         new FrontEnd(m_python_class, backend));
466     if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
467       return synth_ptr;
468     return nullptr;
469   }
470 
471 private:
472   ScriptedSyntheticChildren(const ScriptedSyntheticChildren &) = delete;
473   const ScriptedSyntheticChildren &
474   operator=(const ScriptedSyntheticChildren &) = delete;
475 };
476 } // namespace lldb_private
477 
478 #endif // LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
479