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#include "llvm/Support/ErrorExtras.h"
27
28namespace lldb_private {
30protected:
32
33public:
35
36 virtual ~SyntheticChildrenFrontEnd() = default;
37
38 virtual llvm::Expected<uint32_t> CalculateNumChildren() = 0;
39
40 virtual llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) {
41 auto count = CalculateNumChildren();
42 if (!count)
43 return count;
44 return *count <= max ? *count : max;
45 }
46
47 uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max = UINT32_MAX);
48
49 virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) = 0;
50
51 /// Determine the index of a named child. Subscript names ("[N]") are, by
52 /// default, handled automatically. For data types which need custom
53 /// subscripting behavior - for example a sparse array, disable automatic
54 /// subscripting with TypeOptions::eTypeOptionCustomSubscripting.
55 virtual llvm::Expected<size_t> GetIndexOfChildWithName(llvm::StringRef name) {
56 return llvm::createStringErrorV("type has no child named '{0}'", name);
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 virtual void *GetImplementation() { return nullptr; }
87
88 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
89 typedef std::unique_ptr<SyntheticChildrenFrontEnd> UniquePointer;
90
91protected:
93 CreateChildValueObjectFromExpression(llvm::StringRef name,
94 llvm::StringRef expression,
95 const ExecutionContext &exe_ctx);
96
98 CreateChildValueObjectFromAddress(llvm::StringRef name, uint64_t address,
99 const ExecutionContext &exe_ctx,
100 CompilerType type, bool do_deref = true);
101
103 llvm::StringRef name, const DataExtractor &data,
104 const ExecutionContext &exe_ctx, CompilerType type);
105
106private:
110};
111
113public:
116
118
119 llvm::Expected<uint32_t> CalculateNumChildren() override { return 0; }
120
121 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override { return nullptr; }
122
123 llvm::Expected<size_t>
124 GetIndexOfChildWithName(llvm::StringRef name) override {
125 return llvm::createStringErrorV("type has no child named '{0}'", name);
126 }
127
131
132 bool MightHaveChildren() override { return false; }
133
135
136private:
138 delete;
141};
142
144public:
145 class Flags {
146 public:
147 Flags() = default;
148
149 Flags(const Flags &other) : m_flags(other.m_flags) {}
150
151 Flags(uint32_t value) : m_flags(value) {}
152
153 Flags &operator=(const Flags &rhs) {
154 if (&rhs != this)
155 m_flags = rhs.m_flags;
156
157 return *this;
158 }
159
160 Flags &operator=(const uint32_t &rhs) {
161 m_flags = rhs;
162 return *this;
163 }
164
166 m_flags = 0;
167 return *this;
168 }
169
170 bool GetCascades() const {
171 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
172 }
173
174 Flags &SetCascades(bool value = true) {
175 if (value)
176 m_flags |= lldb::eTypeOptionCascade;
177 else
178 m_flags &= ~lldb::eTypeOptionCascade;
179 return *this;
180 }
181
182 bool GetSkipPointers() const {
183 return (m_flags & lldb::eTypeOptionSkipPointers) ==
184 lldb::eTypeOptionSkipPointers;
185 }
186
187 Flags &SetSkipPointers(bool value = true) {
188 if (value)
189 m_flags |= lldb::eTypeOptionSkipPointers;
190 else
191 m_flags &= ~lldb::eTypeOptionSkipPointers;
192 return *this;
193 }
194
195 bool GetSkipReferences() const {
196 return (m_flags & lldb::eTypeOptionSkipReferences) ==
197 lldb::eTypeOptionSkipReferences;
198 }
199
200 Flags &SetSkipReferences(bool value = true) {
201 if (value)
202 m_flags |= lldb::eTypeOptionSkipReferences;
203 else
204 m_flags &= ~lldb::eTypeOptionSkipReferences;
205 return *this;
206 }
207
208 bool GetNonCacheable() const {
209 return (m_flags & lldb::eTypeOptionNonCacheable) ==
210 lldb::eTypeOptionNonCacheable;
211 }
212
213 Flags &SetNonCacheable(bool value = true) {
214 if (value)
215 m_flags |= lldb::eTypeOptionNonCacheable;
216 else
217 m_flags &= ~lldb::eTypeOptionNonCacheable;
218 return *this;
219 }
220
222 return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
223 lldb::eTypeOptionFrontEndWantsDereference;
224 }
225
226 Flags &SetFrontEndWantsDereference(bool value = true) {
227 if (value)
228 m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
229 else
230 m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
231 return *this;
232 }
233
235 return m_flags & lldb::eTypeOptionCustomSubscripting;
236 }
237
238 Flags &SetCustomSubscripting(bool value = true) {
239 if (value)
240 m_flags |= lldb::eTypeOptionCustomSubscripting;
241 else
242 m_flags &= ~lldb::eTypeOptionCustomSubscripting;
243 return *this;
244 }
245
246 uint32_t GetValue() { return m_flags; }
247
248 void SetValue(uint32_t value) { m_flags = value; }
249
250 private:
251 uint32_t m_flags = lldb::eTypeOptionCascade;
252 };
253
254 SyntheticChildren(const Flags &flags);
255
257
258 bool Cascades() const { return m_flags.GetCascades(); }
259
260 bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
261
262 bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
263
264 bool NonCacheable() const { return m_flags.GetNonCacheable(); }
265
266 bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
267
268 bool CustomSubscripting() const { return m_flags.GetCustomSubscripting(); }
269
270 void SetCascades(bool value) { m_flags.SetCascades(value); }
271
272 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
273
274 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
275
276 void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
277
278 uint32_t GetOptions() { return m_flags.GetValue(); }
279
280 void SetOptions(uint32_t value) { m_flags.SetValue(value); }
281
282 virtual bool IsScripted() = 0;
283
284 virtual std::string GetDescription() = 0;
285
287 GetFrontEnd(ValueObject &backend) = 0;
288
289 typedef std::shared_ptr<SyntheticChildren> SharedPointer;
290
291 uint32_t &GetRevision() { return m_my_revision; }
292
293 uint32_t GetPtrMatchDepth() { return m_ptr_match_depth; }
294
295 void SetPtrMatchDepth(uint32_t value) { m_ptr_match_depth = value; }
296
297protected:
298 uint32_t m_my_revision = 0;
300 uint32_t m_ptr_match_depth = 1;
301
302private:
305};
306
308 std::vector<std::string> m_expression_paths;
309
310public:
313
315 const std::initializer_list<const char *> items)
316 : SyntheticChildren(flags) {
317 for (auto path : items)
318 AddExpressionPath(path);
319 }
320
321 void Clear() { m_expression_paths.clear(); }
322
323 size_t GetCount() const { return m_expression_paths.size(); }
324
325 llvm::StringRef GetExpressionPathAtIndex(size_t i) const;
326
327 void AddExpressionPath(llvm::StringRef path);
328
329 bool SetExpressionPathAtIndex(size_t i, llvm::StringRef path);
330
331 bool IsScripted() override { return false; }
332
333 std::string GetDescription() override;
334
336 public:
338 : SyntheticChildrenFrontEnd(backend), filter(flt) {}
339
340 ~FrontEnd() override = default;
341
342 llvm::Expected<uint32_t> CalculateNumChildren() override {
343 return filter->GetCount();
344 }
345
346 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
347 if (idx >= filter->GetCount())
348 return lldb::ValueObjectSP();
349 return m_backend.GetSyntheticExpressionPathChild(
350 filter->GetExpressionPathAtIndex(idx), true);
351 }
352
356
357 bool MightHaveChildren() override { return filter->GetCount() > 0; }
358
359 llvm::Expected<size_t>
360 GetIndexOfChildWithName(llvm::StringRef name) override;
361
362 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
363
364 private:
366
367 FrontEnd(const FrontEnd &) = delete;
368 const FrontEnd &operator=(const FrontEnd &) = delete;
369 };
370
372 GetFrontEnd(ValueObject &backend) override {
374 new FrontEnd(this, backend));
375 }
376
377 typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
378
379private:
381 const TypeFilterImpl &operator=(const TypeFilterImpl &) = delete;
382};
383
385public:
386 typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
390 const char *description, CreateFrontEndCallback callback);
391
393
394 bool IsScripted() override { return false; }
395
396 std::string GetDescription() override;
397
399 GetFrontEnd(ValueObject &backend) override {
401 m_create_callback(this, backend.GetSP()));
402 }
403
404protected:
406 std::string m_description;
407
408private:
411};
412
414 std::string m_python_class;
415 std::string m_python_code;
416
417public:
419 const char *pclass, const char *pcode = nullptr)
420 : SyntheticChildren(flags) {
421 if (pclass)
422 m_python_class = pclass;
423 if (pcode)
424 m_python_code = pcode;
425 }
426
427 const char *GetPythonClassName() { return m_python_class.c_str(); }
428
429 const char *GetPythonCode() { return m_python_code.c_str(); }
430
431 void SetPythonClassName(const char *fname) {
432 m_python_class.assign(fname);
433 m_python_code.clear();
434 }
435
436 void SetPythonCode(const char *script) { m_python_code.assign(script); }
437
438 std::string GetDescription() override;
439
440 bool IsScripted() override { return true; }
441
443 public:
444 FrontEnd(std::string pclass, ValueObject &backend);
445
446 ~FrontEnd() override;
447
448 bool IsValid();
449
450 llvm::Expected<uint32_t> CalculateNumChildren() override;
451
452 llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
453
454 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
455
456 lldb::ChildCacheState Update() override;
457
458 bool MightHaveChildren() override;
459
460 llvm::Expected<size_t>
461 GetIndexOfChildWithName(llvm::StringRef name) override;
462
464
466
467 void *GetImplementation() override;
468
469 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
470
471 private:
472 std::string m_python_class;
474
475 FrontEnd(const FrontEnd &) = delete;
476 const FrontEnd &operator=(const FrontEnd &) = delete;
477 };
478
480 GetFrontEnd(ValueObject &backend) override {
482 new FrontEnd(m_python_class, backend));
483 if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
484 return synth_ptr;
485 return nullptr;
486 }
487
488private:
492};
493
494/// A synthetic formatter that is defined in LLDB formmater bytecode.
495///
496/// See `BytecodeSummaryFormat` for the corresponding summary formatter.
497///
498/// Formatter bytecode documentation can be found in
499/// lldb/docs/resources/formatterbytecode.rst
501public:
503 /// The version of this record. Specs are found in formatterbytecode.md.
504 uint32_t version = 1;
505 std::unique_ptr<llvm::MemoryBuffer> init;
506 std::unique_ptr<llvm::MemoryBuffer> update;
507 std::unique_ptr<llvm::MemoryBuffer> num_children;
508 std::unique_ptr<llvm::MemoryBuffer> get_child_at_index;
509 std::unique_ptr<llvm::MemoryBuffer> get_child_index;
510 };
511
512private:
514 public:
516
517 lldb::ChildCacheState Update() override;
518 llvm::Expected<uint32_t> CalculateNumChildren() override;
519 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
520 llvm::Expected<size_t>
521 GetIndexOfChildWithName(llvm::StringRef name) override;
522
523 private:
527 };
528
529public:
532
533 bool IsScripted() override { return false; }
534
535 std::string GetDescription() override;
536
538 GetFrontEnd(ValueObject &backend) override {
540 new FrontEnd(backend, m_impl));
541 }
542
543private:
545};
546
547} // namespace lldb_private
548
549#endif // LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
FrontEnd(ValueObject &backend, SyntheticBytecodeImplementation &impl)
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
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...
llvm::Expected< size_t > GetIndexOfChildWithName(llvm::StringRef name) override
Determine the index of a named child.
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
An data extractor class.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
llvm::Expected< size_t > GetIndexOfChildWithName(llvm::StringRef name) override
Determine the index of a named child.
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
lldb::ScriptedSyntheticChildrenInterfaceSP m_interface_sp
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
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 CreateChildValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
std::unique_ptr< SyntheticChildrenFrontEnd > UniquePointer
virtual lldb::ValueObjectSP GetSyntheticValue()
virtual llvm::Expected< uint32_t > CalculateNumChildren(uint32_t max)
virtual llvm::Expected< size_t > GetIndexOfChildWithName(llvm::StringRef name)
Determine the index of a named child.
std::shared_ptr< SyntheticChildrenFrontEnd > SharedPointer
lldb::ValueObjectSP CreateChildValueObjectFromExpression(llvm::StringRef name, llvm::StringRef expression, const ExecutionContext &exe_ctx)
virtual llvm::Expected< uint32_t > CalculateNumChildren()=0
virtual ConstString GetSyntheticTypeName()
SyntheticChildrenFrontEnd(const SyntheticChildrenFrontEnd &)=delete
SyntheticChildrenFrontEnd(ValueObject &backend)
const SyntheticChildrenFrontEnd & operator=(const SyntheticChildrenFrontEnd &)=delete
lldb::ValueObjectSP CreateChildValueObjectFromData(llvm::StringRef name, const DataExtractor &data, const ExecutionContext &exe_ctx, CompilerType type)
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
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< size_t > GetIndexOfChildWithName(llvm::StringRef name) override
Determine the index of a named child.
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< uint32_t > CalculateNumChildren() override
llvm::Expected< size_t > GetIndexOfChildWithName(llvm::StringRef name) override
Determine the index of a named child.
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, llvm::StringRef path)
void AddExpressionPath(llvm::StringRef path)
TypeFilterImpl(const SyntheticChildren::Flags &flags, const std::initializer_list< const char * > items)
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
llvm::StringRef GetExpressionPathAtIndex(size_t i) const
TypeFilterImpl(const TypeFilterImpl &)=delete
lldb::ValueObjectSP GetSP()
#define UINT32_MAX
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::ScriptedSyntheticChildrenInterface > ScriptedSyntheticChildrenInterfaceSP
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
uint32_t version
The version of this record. Specs are found in formatterbytecode.md.