LLDB mainline
TypeSynthetic.h
Go to the documentation of this file.
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
21#include "lldb/lldb-public.h"
22
26
27namespace lldb_private {
29protected:
31
32public:
34
35 virtual ~SyntheticChildrenFrontEnd() = default;
36
37 virtual llvm::Expected<uint32_t> CalculateNumChildren() = 0;
38
39 virtual llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) {
40 auto count = CalculateNumChildren();
41 if (!count)
42 return count;
43 return *count <= max ? *count : max;
44 }
45
46 uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max = UINT32_MAX);
47
48 virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) = 0;
49
50 /// Determine the index of a named child. Subscript names ("[N]") are, by
51 /// default, handled automatically. For data types which need custom
52 /// subscripting behavior - for example a sparse array, disable automatic
53 /// subscripting with TypeOptions::eTypeOptionCustomSubscripting.
54 virtual llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) {
55 return llvm::createStringError("Type has no child named '%s'",
56 name.AsCString());
57 }
58
59 /// This function is assumed to always succeed and if it fails, the front-end
60 /// should know to deal with it in the correct way (most probably, by refusing
61 /// to return any children). The return value of \ref Update should actually
62 /// be interpreted as "ValueObjectSynthetic cache is good/bad". If this
63 /// function returns \ref lldb::ChildCacheState::eReuse, \ref
64 /// ValueObjectSynthetic is allowed to use the children it fetched
65 /// previously and cached. Otherwise, \ref ValueObjectSynthetic must
66 /// throw away its cache, and query again for children.
68
69 // if this function returns false, then CalculateNumChildren() MUST return 0
70 // since UI frontends might validly decide not to inquire for children given
71 // a false return value from this call if it returns true, then
72 // CalculateNumChildren() can return any number >= 0 (0 being valid) it
73 // should if at all possible be more efficient than CalculateNumChildren()
74 virtual bool MightHaveChildren() { return true; }
75
76 // if this function returns a non-null ValueObject, then the returned
77 // ValueObject will stand for this ValueObject whenever a "value" request is
78 // made to this ValueObject
79 virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
80
81 // if this function returns a non-empty ConstString, then clients are
82 // expected to use the return as the name of the type of this ValueObject for
83 // display purposes
85
86 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
87 typedef std::unique_ptr<SyntheticChildrenFrontEnd> UniquePointer;
88
89protected:
91 CreateValueObjectFromExpression(llvm::StringRef name,
92 llvm::StringRef expression,
93 const ExecutionContext &exe_ctx);
94
96 CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
97 const ExecutionContext &exe_ctx,
98 CompilerType type, bool do_deref = true);
99
101 const DataExtractor &data,
102 const ExecutionContext &exe_ctx,
103 CompilerType type);
104
105private:
109};
110
112public:
115
117
118 llvm::Expected<uint32_t> CalculateNumChildren() override { return 0; }
119
120 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override { return nullptr; }
121
122 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
123 return llvm::createStringError("Type has no child named '%s'",
124 name.AsCString());
125 }
126
130
131 bool MightHaveChildren() override { return false; }
132
134
135private:
137 delete;
140};
141
143public:
144 class Flags {
145 public:
146 Flags() = default;
147
148 Flags(const Flags &other) : m_flags(other.m_flags) {}
149
150 Flags(uint32_t value) : m_flags(value) {}
151
152 Flags &operator=(const Flags &rhs) {
153 if (&rhs != this)
154 m_flags = rhs.m_flags;
155
156 return *this;
157 }
158
159 Flags &operator=(const uint32_t &rhs) {
160 m_flags = rhs;
161 return *this;
162 }
163
165 m_flags = 0;
166 return *this;
167 }
168
169 bool GetCascades() const {
170 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
171 }
172
173 Flags &SetCascades(bool value = true) {
174 if (value)
175 m_flags |= lldb::eTypeOptionCascade;
176 else
177 m_flags &= ~lldb::eTypeOptionCascade;
178 return *this;
179 }
180
181 bool GetSkipPointers() const {
182 return (m_flags & lldb::eTypeOptionSkipPointers) ==
183 lldb::eTypeOptionSkipPointers;
184 }
185
186 Flags &SetSkipPointers(bool value = true) {
187 if (value)
188 m_flags |= lldb::eTypeOptionSkipPointers;
189 else
190 m_flags &= ~lldb::eTypeOptionSkipPointers;
191 return *this;
192 }
193
194 bool GetSkipReferences() const {
195 return (m_flags & lldb::eTypeOptionSkipReferences) ==
196 lldb::eTypeOptionSkipReferences;
197 }
198
199 Flags &SetSkipReferences(bool value = true) {
200 if (value)
201 m_flags |= lldb::eTypeOptionSkipReferences;
202 else
203 m_flags &= ~lldb::eTypeOptionSkipReferences;
204 return *this;
205 }
206
207 bool GetNonCacheable() const {
208 return (m_flags & lldb::eTypeOptionNonCacheable) ==
209 lldb::eTypeOptionNonCacheable;
210 }
211
212 Flags &SetNonCacheable(bool value = true) {
213 if (value)
214 m_flags |= lldb::eTypeOptionNonCacheable;
215 else
216 m_flags &= ~lldb::eTypeOptionNonCacheable;
217 return *this;
218 }
219
221 return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
222 lldb::eTypeOptionFrontEndWantsDereference;
223 }
224
225 Flags &SetFrontEndWantsDereference(bool value = true) {
226 if (value)
227 m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
228 else
229 m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
230 return *this;
231 }
232
234 return m_flags & lldb::eTypeOptionCustomSubscripting;
235 }
236
237 Flags &SetCustomSubscripting(bool value = true) {
238 if (value)
239 m_flags |= lldb::eTypeOptionCustomSubscripting;
240 else
241 m_flags &= ~lldb::eTypeOptionCustomSubscripting;
242 return *this;
243 }
244
245 uint32_t GetValue() { return m_flags; }
246
247 void SetValue(uint32_t value) { m_flags = value; }
248
249 private:
250 uint32_t m_flags = lldb::eTypeOptionCascade;
251 };
252
253 SyntheticChildren(const Flags &flags);
254
256
257 bool Cascades() const { return m_flags.GetCascades(); }
258
259 bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
260
261 bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
262
263 bool NonCacheable() const { return m_flags.GetNonCacheable(); }
264
265 bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
266
267 bool CustomSubscripting() const { return m_flags.GetCustomSubscripting(); }
268
269 void SetCascades(bool value) { m_flags.SetCascades(value); }
270
271 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
272
273 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
274
275 void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
276
277 uint32_t GetOptions() { return m_flags.GetValue(); }
278
279 void SetOptions(uint32_t value) { m_flags.SetValue(value); }
280
281 virtual bool IsScripted() = 0;
282
283 virtual std::string GetDescription() = 0;
284
286 GetFrontEnd(ValueObject &backend) = 0;
287
288 typedef std::shared_ptr<SyntheticChildren> SharedPointer;
289
290 uint32_t &GetRevision() { return m_my_revision; }
291
292 uint32_t GetPtrMatchDepth() { return m_ptr_match_depth; }
293
294 void SetPtrMatchDepth(uint32_t value) { m_ptr_match_depth = value; }
295
296protected:
297 uint32_t m_my_revision = 0;
299 uint32_t m_ptr_match_depth = 1;
300
301private:
304};
305
307 std::vector<std::string> m_expression_paths;
308
309public:
312
314 const std::initializer_list<const char *> items)
315 : SyntheticChildren(flags) {
316 for (auto path : items)
317 AddExpressionPath(path);
318 }
319
320 void AddExpressionPath(const char *path) {
321 AddExpressionPath(std::string(path));
322 }
323
324 void Clear() { m_expression_paths.clear(); }
325
326 size_t GetCount() const { return m_expression_paths.size(); }
327
328 const char *GetExpressionPathAtIndex(size_t i) const {
329 return m_expression_paths[i].c_str();
330 }
331
332 bool SetExpressionPathAtIndex(size_t i, const char *path) {
333 return SetExpressionPathAtIndex(i, std::string(path));
334 }
335
336 void AddExpressionPath(const std::string &path);
337
338 bool SetExpressionPathAtIndex(size_t i, const std::string &path);
339
340 bool IsScripted() override { return false; }
341
342 std::string GetDescription() override;
343
345 public:
347 : SyntheticChildrenFrontEnd(backend), filter(flt) {}
348
349 ~FrontEnd() override = default;
350
351 llvm::Expected<uint32_t> CalculateNumChildren() override {
352 return filter->GetCount();
353 }
354
355 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
356 if (idx >= filter->GetCount())
357 return lldb::ValueObjectSP();
358 return m_backend.GetSyntheticExpressionPathChild(
359 filter->GetExpressionPathAtIndex(idx), true);
360 }
361
365
366 bool MightHaveChildren() override { return filter->GetCount() > 0; }
367
368 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
369
370 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
371
372 private:
374
375 FrontEnd(const FrontEnd &) = delete;
376 const FrontEnd &operator=(const FrontEnd &) = delete;
377 };
378
380 GetFrontEnd(ValueObject &backend) override {
382 new FrontEnd(this, backend));
383 }
384
385 typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
386
387private:
389 const TypeFilterImpl &operator=(const TypeFilterImpl &) = delete;
390};
391
393public:
394 typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
398 const char *description, CreateFrontEndCallback callback);
399
401
402 bool IsScripted() override { return false; }
403
404 std::string GetDescription() override;
405
407 GetFrontEnd(ValueObject &backend) override {
409 m_create_callback(this, backend.GetSP()));
410 }
411
412protected:
414 std::string m_description;
415
416private:
419};
420
422 std::string m_python_class;
423 std::string m_python_code;
424
425public:
427 const char *pclass, const char *pcode = nullptr)
428 : SyntheticChildren(flags) {
429 if (pclass)
430 m_python_class = pclass;
431 if (pcode)
432 m_python_code = pcode;
433 }
434
435 const char *GetPythonClassName() { return m_python_class.c_str(); }
436
437 const char *GetPythonCode() { return m_python_code.c_str(); }
438
439 void SetPythonClassName(const char *fname) {
440 m_python_class.assign(fname);
441 m_python_code.clear();
442 }
443
444 void SetPythonCode(const char *script) { m_python_code.assign(script); }
445
446 std::string GetDescription() override;
447
448 bool IsScripted() override { return true; }
449
451 public:
452 FrontEnd(std::string pclass, ValueObject &backend);
453
454 ~FrontEnd() override;
455
456 bool IsValid();
457
458 llvm::Expected<uint32_t> CalculateNumChildren() override;
459
460 llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
461
462 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
463
464 lldb::ChildCacheState Update() override;
465
466 bool MightHaveChildren() override;
467
468 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
469
471
473
474 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
475
476 private:
477 std::string m_python_class;
480
481 FrontEnd(const FrontEnd &) = delete;
482 const FrontEnd &operator=(const FrontEnd &) = delete;
483 };
484
486 GetFrontEnd(ValueObject &backend) override {
488 new FrontEnd(m_python_class, backend));
489 if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
490 return synth_ptr;
491 return nullptr;
492 }
493
494private:
498};
499
500/// A synthetic formatter that is defined in LLDB formmater bytecode.
501///
502/// See `BytecodeSummaryFormat` for the corresponding summary formatter.
503///
504/// Formatter bytecode documentation can be found in
505/// lldb/docs/resources/formatterbytecode.rst
507public:
509 std::unique_ptr<llvm::MemoryBuffer> init;
510 std::unique_ptr<llvm::MemoryBuffer> update;
511 std::unique_ptr<llvm::MemoryBuffer> num_children;
512 std::unique_ptr<llvm::MemoryBuffer> get_child_at_index;
513 std::unique_ptr<llvm::MemoryBuffer> get_child_index;
514 };
515
516private:
518 public:
520
521 lldb::ChildCacheState Update() override;
522 llvm::Expected<uint32_t> CalculateNumChildren() override;
523 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
524 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
525
526 private:
529 };
530
531public:
534
535 bool IsScripted() override { return false; }
536
537 std::string GetDescription() override;
538
540 GetFrontEnd(ValueObject &backend) override {
542 new FrontEnd(backend, m_impl));
543 }
544
545private:
547};
548
549} // namespace lldb_private
550
551#endif // LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
FrontEnd(ValueObject &backend, SyntheticBytecodeImplementation &impl)
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Determine the index of a named child.
llvm::Expected< uint32_t > CalculateNumChildren() override
const SyntheticBytecodeImplementation & m_impl
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
SyntheticChildrenFrontEnd::UniquePointer GetFrontEnd(ValueObject &backend) override
BytecodeSyntheticChildren(SyntheticBytecodeImplementation &&impl)
SyntheticBytecodeImplementation m_impl
CXXSyntheticChildren(const CXXSyntheticChildren &)=delete
const CXXSyntheticChildren & operator=(const CXXSyntheticChildren &)=delete
CreateFrontEndCallback m_create_callback
std::string GetDescription() override
SyntheticChildrenFrontEnd::UniquePointer GetFrontEnd(ValueObject &backend) override
CXXSyntheticChildren(const SyntheticChildren::Flags &flags, const char *description, CreateFrontEndCallback callback)
std::function< SyntheticChildrenFrontEnd *(CXXSyntheticChildren *, lldb::ValueObjectSP)> CreateFrontEndCallback
Generic representation of a type in a programming language.
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
An data extractor class.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Determine the index of a named child.
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
std::shared_ptr< SyntheticChildrenFrontEnd > SharedPointer
FrontEnd(std::string pclass, ValueObject &backend)
llvm::Expected< uint32_t > CalculateNumChildren() override
const FrontEnd & operator=(const FrontEnd &)=delete
SyntheticChildrenFrontEnd::UniquePointer GetFrontEnd(ValueObject &backend) override
void SetPythonClassName(const char *fname)
ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags, const char *pclass, const char *pcode=nullptr)
const ScriptedSyntheticChildren & operator=(const ScriptedSyntheticChildren &)=delete
void SetPythonCode(const char *script)
ScriptedSyntheticChildren(const ScriptedSyntheticChildren &)=delete
std::shared_ptr< Object > ObjectSP
uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max=UINT32_MAX)
virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx)=0
virtual lldb::ChildCacheState Update()=0
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
lldb::ValueObjectSP CreateValueObjectFromExpression(llvm::StringRef name, llvm::StringRef expression, const ExecutionContext &exe_ctx)
std::unique_ptr< SyntheticChildrenFrontEnd > UniquePointer
virtual lldb::ValueObjectSP GetSyntheticValue()
virtual llvm::Expected< uint32_t > CalculateNumChildren(uint32_t max)
lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data, const ExecutionContext &exe_ctx, CompilerType type)
std::shared_ptr< SyntheticChildrenFrontEnd > SharedPointer
virtual llvm::Expected< uint32_t > CalculateNumChildren()=0
virtual ConstString GetSyntheticTypeName()
SyntheticChildrenFrontEnd(const SyntheticChildrenFrontEnd &)=delete
SyntheticChildrenFrontEnd(ValueObject &backend)
virtual llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name)
Determine the index of a named child.
const SyntheticChildrenFrontEnd & operator=(const SyntheticChildrenFrontEnd &)=delete
lldb::ValueObjectSP CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
Flags & SetSkipReferences(bool value=true)
Flags & SetFrontEndWantsDereference(bool value=true)
Flags & operator=(const uint32_t &rhs)
Flags & SetSkipPointers(bool value=true)
Flags & SetCascades(bool value=true)
Flags & SetCustomSubscripting(bool value=true)
Flags & SetNonCacheable(bool value=true)
Flags & operator=(const Flags &rhs)
const SyntheticChildren & operator=(const SyntheticChildren &)=delete
virtual std::string GetDescription()=0
virtual SyntheticChildrenFrontEnd::UniquePointer GetFrontEnd(ValueObject &backend)=0
void SetPtrMatchDepth(uint32_t value)
SyntheticChildren(const Flags &flags)
void SetOptions(uint32_t value)
SyntheticChildren(const SyntheticChildren &)=delete
std::shared_ptr< SyntheticChildren > SharedPointer
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Determine the index of a named child.
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
llvm::Expected< uint32_t > CalculateNumChildren() override
SyntheticValueProviderFrontEnd(const SyntheticValueProviderFrontEnd &)=delete
lldb::ValueObjectSP GetSyntheticValue() override=0
const SyntheticValueProviderFrontEnd & operator=(const SyntheticValueProviderFrontEnd &)=delete
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
FrontEnd(const FrontEnd &)=delete
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Determine the index of a named child.
llvm::Expected< uint32_t > CalculateNumChildren() override
FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
const FrontEnd & operator=(const FrontEnd &)=delete
std::shared_ptr< SyntheticChildrenFrontEnd > SharedPointer
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
std::shared_ptr< TypeFilterImpl > SharedPointer
bool SetExpressionPathAtIndex(size_t i, const char *path)
const char * GetExpressionPathAtIndex(size_t i) const
TypeFilterImpl(const SyntheticChildren::Flags &flags, const std::initializer_list< const char * > items)
void AddExpressionPath(const char *path)
std::string GetDescription() override
TypeFilterImpl(const SyntheticChildren::Flags &flags)
SyntheticChildrenFrontEnd::UniquePointer GetFrontEnd(ValueObject &backend) override
std::vector< std::string > m_expression_paths
const TypeFilterImpl & operator=(const TypeFilterImpl &)=delete
TypeFilterImpl(const TypeFilterImpl &)=delete
lldb::ValueObjectSP GetSP()
#define UINT32_MAX
A class that represents a running process on the host machine.
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP