xref: /freebsd/contrib/llvm-project/lldb/include/lldb/DataFormatters/TypeSummary.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- TypeSummary.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_TYPESUMMARY_H
10 #define LLDB_DATAFORMATTERS_TYPESUMMARY_H
11 
12 #include <cstdint>
13 
14 #include <functional>
15 #include <memory>
16 #include <string>
17 
18 #include "lldb/lldb-enumerations.h"
19 #include "lldb/lldb-public.h"
20 
21 #include "lldb/Core/FormatEntity.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/Utility/StructuredData.h"
24 
25 namespace llvm {
26 class MemoryBuffer;
27 }
28 
29 namespace lldb_private {
30 class TypeSummaryOptions {
31 public:
32   TypeSummaryOptions();
33 
34   ~TypeSummaryOptions() = default;
35 
36   lldb::LanguageType GetLanguage() const;
37 
38   lldb::TypeSummaryCapping GetCapping() const;
39 
40   TypeSummaryOptions &SetLanguage(lldb::LanguageType);
41 
42   TypeSummaryOptions &SetCapping(lldb::TypeSummaryCapping);
43 
44 private:
45   lldb::LanguageType m_lang = lldb::eLanguageTypeUnknown;
46   lldb::TypeSummaryCapping m_capping = lldb::eTypeSummaryCapped;
47 };
48 
49 class TypeSummaryImpl {
50 public:
51   enum class Kind { eSummaryString, eScript, eBytecode, eCallback, eInternal };
52 
53   virtual ~TypeSummaryImpl() = default;
54 
GetKind()55   Kind GetKind() const { return m_kind; }
56 
57   class Flags {
58   public:
59     Flags() = default;
60 
Flags(const Flags & other)61     Flags(const Flags &other) : m_flags(other.m_flags) {}
62 
Flags(uint32_t value)63     Flags(uint32_t value) : m_flags(value) {}
64 
65     Flags &operator=(const Flags &rhs) {
66       if (&rhs != this)
67         m_flags = rhs.m_flags;
68 
69       return *this;
70     }
71 
72     Flags &operator=(const uint32_t &rhs) {
73       m_flags = rhs;
74       return *this;
75     }
76 
Clear()77     Flags &Clear() {
78       m_flags = 0;
79       return *this;
80     }
81 
GetCascades()82     bool GetCascades() const {
83       return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
84     }
85 
86     Flags &SetCascades(bool value = true) {
87       if (value)
88         m_flags |= lldb::eTypeOptionCascade;
89       else
90         m_flags &= ~lldb::eTypeOptionCascade;
91       return *this;
92     }
93 
GetSkipPointers()94     bool GetSkipPointers() const {
95       return (m_flags & lldb::eTypeOptionSkipPointers) ==
96              lldb::eTypeOptionSkipPointers;
97     }
98 
99     Flags &SetSkipPointers(bool value = true) {
100       if (value)
101         m_flags |= lldb::eTypeOptionSkipPointers;
102       else
103         m_flags &= ~lldb::eTypeOptionSkipPointers;
104       return *this;
105     }
106 
GetSkipReferences()107     bool GetSkipReferences() const {
108       return (m_flags & lldb::eTypeOptionSkipReferences) ==
109              lldb::eTypeOptionSkipReferences;
110     }
111 
112     Flags &SetSkipReferences(bool value = true) {
113       if (value)
114         m_flags |= lldb::eTypeOptionSkipReferences;
115       else
116         m_flags &= ~lldb::eTypeOptionSkipReferences;
117       return *this;
118     }
119 
GetDontShowChildren()120     bool GetDontShowChildren() const {
121       return (m_flags & lldb::eTypeOptionHideChildren) ==
122              lldb::eTypeOptionHideChildren;
123     }
124 
125     Flags &SetDontShowChildren(bool value = true) {
126       if (value)
127         m_flags |= lldb::eTypeOptionHideChildren;
128       else
129         m_flags &= ~lldb::eTypeOptionHideChildren;
130       return *this;
131     }
132 
GetHideEmptyAggregates()133     bool GetHideEmptyAggregates() const {
134       return (m_flags & lldb::eTypeOptionHideEmptyAggregates) ==
135              lldb::eTypeOptionHideEmptyAggregates;
136     }
137 
138     Flags &SetHideEmptyAggregates(bool value = true) {
139       if (value)
140         m_flags |= lldb::eTypeOptionHideEmptyAggregates;
141       else
142         m_flags &= ~lldb::eTypeOptionHideEmptyAggregates;
143       return *this;
144     }
145 
GetDontShowValue()146     bool GetDontShowValue() const {
147       return (m_flags & lldb::eTypeOptionHideValue) ==
148              lldb::eTypeOptionHideValue;
149     }
150 
151     Flags &SetDontShowValue(bool value = true) {
152       if (value)
153         m_flags |= lldb::eTypeOptionHideValue;
154       else
155         m_flags &= ~lldb::eTypeOptionHideValue;
156       return *this;
157     }
158 
GetShowMembersOneLiner()159     bool GetShowMembersOneLiner() const {
160       return (m_flags & lldb::eTypeOptionShowOneLiner) ==
161              lldb::eTypeOptionShowOneLiner;
162     }
163 
164     Flags &SetShowMembersOneLiner(bool value = true) {
165       if (value)
166         m_flags |= lldb::eTypeOptionShowOneLiner;
167       else
168         m_flags &= ~lldb::eTypeOptionShowOneLiner;
169       return *this;
170     }
171 
GetHideItemNames()172     bool GetHideItemNames() const {
173       return (m_flags & lldb::eTypeOptionHideNames) ==
174              lldb::eTypeOptionHideNames;
175     }
176 
177     Flags &SetHideItemNames(bool value = true) {
178       if (value)
179         m_flags |= lldb::eTypeOptionHideNames;
180       else
181         m_flags &= ~lldb::eTypeOptionHideNames;
182       return *this;
183     }
184 
GetNonCacheable()185     bool GetNonCacheable() const {
186       return (m_flags & lldb::eTypeOptionNonCacheable) ==
187              lldb::eTypeOptionNonCacheable;
188     }
189 
190     Flags &SetNonCacheable(bool value = true) {
191       if (value)
192         m_flags |= lldb::eTypeOptionNonCacheable;
193       else
194         m_flags &= ~lldb::eTypeOptionNonCacheable;
195       return *this;
196     }
197 
GetValue()198     uint32_t GetValue() { return m_flags; }
199 
SetValue(uint32_t value)200     void SetValue(uint32_t value) { m_flags = value; }
201 
202   private:
203     uint32_t m_flags = lldb::eTypeOptionCascade;
204   };
205 
Cascades()206   bool Cascades() const { return m_flags.GetCascades(); }
207 
SkipsPointers()208   bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
209 
SkipsReferences()210   bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
211 
NonCacheable()212   bool NonCacheable() const { return m_flags.GetNonCacheable(); }
213 
DoesPrintChildren(ValueObject * valobj)214   virtual bool DoesPrintChildren(ValueObject *valobj) const {
215     return !m_flags.GetDontShowChildren();
216   }
217 
DoesPrintEmptyAggregates()218   virtual bool DoesPrintEmptyAggregates() const {
219     return !m_flags.GetHideEmptyAggregates();
220   }
221 
DoesPrintValue(ValueObject * valobj)222   virtual bool DoesPrintValue(ValueObject *valobj) const {
223     return !m_flags.GetDontShowValue();
224   }
225 
IsOneLiner()226   bool IsOneLiner() const { return m_flags.GetShowMembersOneLiner(); }
227 
HideNames(ValueObject * valobj)228   virtual bool HideNames(ValueObject *valobj) const {
229     return m_flags.GetHideItemNames();
230   }
231 
SetCascades(bool value)232   void SetCascades(bool value) { m_flags.SetCascades(value); }
233 
SetSkipsPointers(bool value)234   void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
235 
SetSkipsReferences(bool value)236   void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
237 
SetDoesPrintChildren(bool value)238   virtual void SetDoesPrintChildren(bool value) {
239     m_flags.SetDontShowChildren(!value);
240   }
241 
SetDoesPrintValue(bool value)242   virtual void SetDoesPrintValue(bool value) {
243     m_flags.SetDontShowValue(!value);
244   }
245 
SetIsOneLiner(bool value)246   void SetIsOneLiner(bool value) { m_flags.SetShowMembersOneLiner(value); }
247 
SetHideNames(bool value)248   virtual void SetHideNames(bool value) { m_flags.SetHideItemNames(value); }
249 
SetNonCacheable(bool value)250   virtual void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
251 
GetOptions()252   uint32_t GetOptions() { return m_flags.GetValue(); }
253 
SetOptions(uint32_t value)254   void SetOptions(uint32_t value) { m_flags.SetValue(value); }
255 
GetPtrMatchDepth()256   uint32_t GetPtrMatchDepth() { return m_ptr_match_depth; }
257 
SetPtrMatchDepth(uint32_t value)258   void SetPtrMatchDepth(uint32_t value) { m_ptr_match_depth = value; }
259 
260   // we are using a ValueObject* instead of a ValueObjectSP because we do not
261   // need to hold on to this for extended periods of time and we trust the
262   // ValueObject to stay around for as long as it is required for us to
263   // generate its summary
264   virtual bool FormatObject(ValueObject *valobj, std::string &dest,
265                             const TypeSummaryOptions &options) = 0;
266 
267   virtual std::string GetDescription() = 0;
268 
269   /// Get the name of the Type Summary Provider, either a C++ class, a summary
270   /// string, or a script function name.
271   virtual std::string GetName() = 0;
272 
273   /// Get the name of the kind of Summary Provider, either c++, summary string,
274   /// script or python.
275   virtual std::string GetSummaryKindName();
276 
GetRevision()277   uint32_t &GetRevision() { return m_my_revision; }
278 
279   typedef std::shared_ptr<TypeSummaryImpl> SharedPointer;
280 
281 protected:
282   uint32_t m_my_revision = 0;
283   Flags m_flags;
284 
285   TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags,
286                   uint32_t ptr_match_depth = 1);
287 
288 private:
289   Kind m_kind;
290   uint32_t m_ptr_match_depth = 1;
291   TypeSummaryImpl(const TypeSummaryImpl &) = delete;
292   const TypeSummaryImpl &operator=(const TypeSummaryImpl &) = delete;
293 };
294 
295 // simple string-based summaries, using ${var to show data
296 struct StringSummaryFormat : public TypeSummaryImpl {
297   std::string m_format_str;
298   FormatEntity::Entry m_format;
299   Status m_error;
300 
301   StringSummaryFormat(const TypeSummaryImpl::Flags &flags, const char *f,
302                       uint32_t ptr_match_depth = 1);
303 
304   ~StringSummaryFormat() override = default;
305 
GetSummaryStringStringSummaryFormat306   const char *GetSummaryString() const { return m_format_str.c_str(); }
307 
308   void SetSummaryString(const char *f);
309 
310   bool FormatObject(ValueObject *valobj, std::string &dest,
311                     const TypeSummaryOptions &options) override;
312 
313   std::string GetDescription() override;
314 
315   std::string GetName() override;
316 
classofStringSummaryFormat317   static bool classof(const TypeSummaryImpl *S) {
318     return S->GetKind() == Kind::eSummaryString;
319   }
320 
321 private:
322   StringSummaryFormat(const StringSummaryFormat &) = delete;
323   const StringSummaryFormat &operator=(const StringSummaryFormat &) = delete;
324 };
325 
326 // summaries implemented via a C++ function
327 struct CXXFunctionSummaryFormat : public TypeSummaryImpl {
328   // we should convert these to SBValue and SBStream if we ever cross the
329   // boundary towards the external world
330   typedef std::function<bool(ValueObject &, Stream &,
331                              const TypeSummaryOptions &)>
332       Callback;
333 
334   Callback m_impl;
335   std::string m_description;
336 
337   CXXFunctionSummaryFormat(const TypeSummaryImpl::Flags &flags, Callback impl,
338                            const char *description,
339                            uint32_t ptr_match_depth = 1);
340 
341   ~CXXFunctionSummaryFormat() override = default;
342 
GetBackendFunctionCXXFunctionSummaryFormat343   Callback GetBackendFunction() const { return m_impl; }
344 
GetTextualInfoCXXFunctionSummaryFormat345   const char *GetTextualInfo() const { return m_description.c_str(); }
346 
SetBackendFunctionCXXFunctionSummaryFormat347   void SetBackendFunction(Callback cb_func) { m_impl = std::move(cb_func); }
348 
SetTextualInfoCXXFunctionSummaryFormat349   void SetTextualInfo(const char *descr) {
350     if (descr)
351       m_description.assign(descr);
352     else
353       m_description.clear();
354   }
355 
356   bool FormatObject(ValueObject *valobj, std::string &dest,
357                     const TypeSummaryOptions &options) override;
358 
359   std::string GetDescription() override;
360 
classofCXXFunctionSummaryFormat361   static bool classof(const TypeSummaryImpl *S) {
362     return S->GetKind() == Kind::eCallback;
363   }
364 
365   std::string GetName() override;
366 
367   typedef std::shared_ptr<CXXFunctionSummaryFormat> SharedPointer;
368 
369 private:
370   CXXFunctionSummaryFormat(const CXXFunctionSummaryFormat &) = delete;
371   const CXXFunctionSummaryFormat &
372   operator=(const CXXFunctionSummaryFormat &) = delete;
373 };
374 
375 // Python-based summaries, running script code to show data
376 struct ScriptSummaryFormat : public TypeSummaryImpl {
377   std::string m_function_name;
378   std::string m_python_script;
379   std::string m_script_formatter_name;
380   StructuredData::ObjectSP m_script_function_sp;
381 
382   ScriptSummaryFormat(const TypeSummaryImpl::Flags &flags,
383                       const char *function_name,
384                       const char *python_script = nullptr,
385                       uint32_t ptr_match_depth = 1);
386 
387   ~ScriptSummaryFormat() override = default;
388 
GetFunctionNameScriptSummaryFormat389   const char *GetFunctionName() const { return m_function_name.c_str(); }
390 
GetPythonScriptScriptSummaryFormat391   const char *GetPythonScript() const { return m_python_script.c_str(); }
392 
SetFunctionNameScriptSummaryFormat393   void SetFunctionName(const char *function_name) {
394     if (function_name)
395       m_function_name.assign(function_name);
396     else
397       m_function_name.clear();
398     m_python_script.clear();
399   }
400 
SetPythonScriptScriptSummaryFormat401   void SetPythonScript(const char *script) {
402     if (script)
403       m_python_script.assign(script);
404     else
405       m_python_script.clear();
406   }
407 
408   bool FormatObject(ValueObject *valobj, std::string &dest,
409                     const TypeSummaryOptions &options) override;
410 
411   std::string GetDescription() override;
412 
413   std::string GetName() override;
414 
classofScriptSummaryFormat415   static bool classof(const TypeSummaryImpl *S) {
416     return S->GetKind() == Kind::eScript;
417   }
418 
419   typedef std::shared_ptr<ScriptSummaryFormat> SharedPointer;
420 
421 private:
422   ScriptSummaryFormat(const ScriptSummaryFormat &) = delete;
423   const ScriptSummaryFormat &operator=(const ScriptSummaryFormat &) = delete;
424 };
425 
426 /// A summary formatter that is defined in LLDB formmater bytecode.
427 class BytecodeSummaryFormat : public TypeSummaryImpl {
428   std::unique_ptr<llvm::MemoryBuffer> m_bytecode;
429 
430 public:
431   BytecodeSummaryFormat(const TypeSummaryImpl::Flags &flags,
432                         std::unique_ptr<llvm::MemoryBuffer> bytecode);
433   bool FormatObject(ValueObject *valobj, std::string &dest,
434                     const TypeSummaryOptions &options) override;
435   std::string GetDescription() override;
436   std::string GetName() override;
classof(const TypeSummaryImpl * S)437   static bool classof(const TypeSummaryImpl *S) {
438     return S->GetKind() == Kind::eBytecode;
439   }
440 };
441 
442 } // namespace lldb_private
443 
444 #endif // LLDB_DATAFORMATTERS_TYPESUMMARY_H
445