1 //===-- TypeSynthetic.h -----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef lldb_TypeSynthetic_h_
10 #define lldb_TypeSynthetic_h_
15 #include <initializer_list>
20 #include "lldb/lldb-enumerations.h"
21 #include "lldb/lldb-public.h"
23 #include "lldb/Core/ValueObject.h"
24 #include "lldb/Utility/StructuredData.h"
26 namespace lldb_private {
27 class SyntheticChildrenFrontEnd {
29 ValueObject &m_backend;
31 void SetValid(bool valid) { m_valid = valid; }
33 bool IsValid() { return m_valid; }
36 SyntheticChildrenFrontEnd(ValueObject &backend)
37 : m_backend(backend), m_valid(true) {}
39 virtual ~SyntheticChildrenFrontEnd() = default;
41 virtual size_t CalculateNumChildren() = 0;
43 virtual size_t CalculateNumChildren(uint32_t max) {
44 auto count = CalculateNumChildren();
45 return count <= max ? count : max;
48 virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx) = 0;
50 virtual size_t GetIndexOfChildWithName(ConstString name) = 0;
52 // this function is assumed to always succeed and it if fails, the front-end
53 // should know to deal with it in the correct way (most probably, by refusing
54 // to return any children) the return value of Update() should actually be
55 // interpreted as "ValueObjectSyntheticFilter cache is good/bad" if =true,
56 // ValueObjectSyntheticFilter is allowed to use the children it fetched
57 // previously and cached if =false, ValueObjectSyntheticFilter must throw
58 // away its cache, and query again for children
59 virtual bool Update() = 0;
61 // if this function returns false, then CalculateNumChildren() MUST return 0
62 // since UI frontends might validly decide not to inquire for children given
63 // a false return value from this call if it returns true, then
64 // CalculateNumChildren() can return any number >= 0 (0 being valid) it
65 // should if at all possible be more efficient than CalculateNumChildren()
66 virtual bool MightHaveChildren() = 0;
68 // if this function returns a non-null ValueObject, then the returned
69 // ValueObject will stand for this ValueObject whenever a "value" request is
70 // made to this ValueObject
71 virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
73 // if this function returns a non-empty ConstString, then clients are
74 // expected to use the return as the name of the type of this ValueObject for
76 virtual ConstString GetSyntheticTypeName() { return ConstString(); }
78 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
79 typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
83 CreateValueObjectFromExpression(llvm::StringRef name,
84 llvm::StringRef expression,
85 const ExecutionContext &exe_ctx);
88 CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
89 const ExecutionContext &exe_ctx,
92 lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name,
93 const DataExtractor &data,
94 const ExecutionContext &exe_ctx,
99 DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd);
102 class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
104 SyntheticValueProviderFrontEnd(ValueObject &backend)
105 : SyntheticChildrenFrontEnd(backend) {}
107 ~SyntheticValueProviderFrontEnd() override = default;
109 size_t CalculateNumChildren() override { return 0; }
111 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { return nullptr; }
113 size_t GetIndexOfChildWithName(ConstString name) override {
117 bool Update() override { return false; }
119 bool MightHaveChildren() override { return false; }
121 lldb::ValueObjectSP GetSyntheticValue() override = 0;
124 DISALLOW_COPY_AND_ASSIGN(SyntheticValueProviderFrontEnd);
127 class SyntheticChildren {
131 Flags() : m_flags(lldb::eTypeOptionCascade) {}
133 Flags(const Flags &other) : m_flags(other.m_flags) {}
135 Flags(uint32_t value) : m_flags(value) {}
137 Flags &operator=(const Flags &rhs) {
139 m_flags = rhs.m_flags;
144 Flags &operator=(const uint32_t &rhs) {
154 bool GetCascades() const {
155 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
158 Flags &SetCascades(bool value = true) {
160 m_flags |= lldb::eTypeOptionCascade;
162 m_flags &= ~lldb::eTypeOptionCascade;
166 bool GetSkipPointers() const {
167 return (m_flags & lldb::eTypeOptionSkipPointers) ==
168 lldb::eTypeOptionSkipPointers;
171 Flags &SetSkipPointers(bool value = true) {
173 m_flags |= lldb::eTypeOptionSkipPointers;
175 m_flags &= ~lldb::eTypeOptionSkipPointers;
179 bool GetSkipReferences() const {
180 return (m_flags & lldb::eTypeOptionSkipReferences) ==
181 lldb::eTypeOptionSkipReferences;
184 Flags &SetSkipReferences(bool value = true) {
186 m_flags |= lldb::eTypeOptionSkipReferences;
188 m_flags &= ~lldb::eTypeOptionSkipReferences;
192 bool GetNonCacheable() const {
193 return (m_flags & lldb::eTypeOptionNonCacheable) ==
194 lldb::eTypeOptionNonCacheable;
197 Flags &SetNonCacheable(bool value = true) {
199 m_flags |= lldb::eTypeOptionNonCacheable;
201 m_flags &= ~lldb::eTypeOptionNonCacheable;
205 bool GetFrontEndWantsDereference() const {
206 return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
207 lldb::eTypeOptionFrontEndWantsDereference;
210 Flags &SetFrontEndWantsDereference(bool value = true) {
212 m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
214 m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
218 uint32_t GetValue() { return m_flags; }
220 void SetValue(uint32_t value) { m_flags = value; }
226 SyntheticChildren(const Flags &flags) : m_flags(flags) {}
228 virtual ~SyntheticChildren() = default;
230 bool Cascades() const { return m_flags.GetCascades(); }
232 bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
234 bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
236 bool NonCacheable() const { return m_flags.GetNonCacheable(); }
238 bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
240 void SetCascades(bool value) { m_flags.SetCascades(value); }
242 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
244 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
246 void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
248 uint32_t GetOptions() { return m_flags.GetValue(); }
250 void SetOptions(uint32_t value) { m_flags.SetValue(value); }
252 virtual bool IsScripted() = 0;
254 virtual std::string GetDescription() = 0;
256 virtual SyntheticChildrenFrontEnd::AutoPointer
257 GetFrontEnd(ValueObject &backend) = 0;
259 typedef std::shared_ptr<SyntheticChildren> SharedPointer;
261 uint32_t &GetRevision() { return m_my_revision; }
264 uint32_t m_my_revision;
268 DISALLOW_COPY_AND_ASSIGN(SyntheticChildren);
271 class TypeFilterImpl : public SyntheticChildren {
272 std::vector<std::string> m_expression_paths;
275 TypeFilterImpl(const SyntheticChildren::Flags &flags)
276 : SyntheticChildren(flags), m_expression_paths() {}
278 TypeFilterImpl(const SyntheticChildren::Flags &flags,
279 const std::initializer_list<const char *> items)
280 : SyntheticChildren(flags), m_expression_paths() {
281 for (auto path : items)
282 AddExpressionPath(path);
285 void AddExpressionPath(const char *path) {
286 AddExpressionPath(std::string(path));
289 void Clear() { m_expression_paths.clear(); }
291 size_t GetCount() const { return m_expression_paths.size(); }
293 const char *GetExpressionPathAtIndex(size_t i) const {
294 return m_expression_paths[i].c_str();
297 bool SetExpressionPathAtIndex(size_t i, const char *path) {
298 return SetExpressionPathAtIndex(i, std::string(path));
301 void AddExpressionPath(const std::string &path);
303 bool SetExpressionPathAtIndex(size_t i, const std::string &path);
305 bool IsScripted() override { return false; }
307 std::string GetDescription() override;
309 class FrontEnd : public SyntheticChildrenFrontEnd {
311 FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
312 : SyntheticChildrenFrontEnd(backend), filter(flt) {}
314 ~FrontEnd() override = default;
316 size_t CalculateNumChildren() override { return filter->GetCount(); }
318 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
319 if (idx >= filter->GetCount())
320 return lldb::ValueObjectSP();
321 return m_backend.GetSyntheticExpressionPathChild(
322 filter->GetExpressionPathAtIndex(idx), true);
325 bool Update() override { return false; }
327 bool MightHaveChildren() override { return filter->GetCount() > 0; }
329 size_t GetIndexOfChildWithName(ConstString name) override;
331 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
334 TypeFilterImpl *filter;
336 DISALLOW_COPY_AND_ASSIGN(FrontEnd);
339 SyntheticChildrenFrontEnd::AutoPointer
340 GetFrontEnd(ValueObject &backend) override {
341 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
344 typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
347 DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl);
350 class CXXSyntheticChildren : public SyntheticChildren {
352 typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
353 lldb::ValueObjectSP)>
354 CreateFrontEndCallback;
355 CXXSyntheticChildren(const SyntheticChildren::Flags &flags,
356 const char *description, CreateFrontEndCallback callback)
357 : SyntheticChildren(flags), m_create_callback(callback),
358 m_description(description ? description : "") {}
360 bool IsScripted() override { return false; }
362 std::string GetDescription() override;
364 SyntheticChildrenFrontEnd::AutoPointer
365 GetFrontEnd(ValueObject &backend) override {
366 return SyntheticChildrenFrontEnd::AutoPointer(
367 m_create_callback(this, backend.GetSP()));
371 CreateFrontEndCallback m_create_callback;
372 std::string m_description;
375 DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren);
378 class ScriptedSyntheticChildren : public SyntheticChildren {
379 std::string m_python_class;
380 std::string m_python_code;
383 ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags,
384 const char *pclass, const char *pcode = nullptr)
385 : SyntheticChildren(flags), m_python_class(), m_python_code() {
387 m_python_class = pclass;
389 m_python_code = pcode;
392 const char *GetPythonClassName() { return m_python_class.c_str(); }
394 const char *GetPythonCode() { return m_python_code.c_str(); }
396 void SetPythonClassName(const char *fname) {
397 m_python_class.assign(fname);
398 m_python_code.clear();
401 void SetPythonCode(const char *script) { m_python_code.assign(script); }
403 std::string GetDescription() override;
405 bool IsScripted() override { return true; }
407 class FrontEnd : public SyntheticChildrenFrontEnd {
409 FrontEnd(std::string pclass, ValueObject &backend);
411 ~FrontEnd() override;
415 size_t CalculateNumChildren() override;
417 size_t CalculateNumChildren(uint32_t max) override;
419 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
421 bool Update() override;
423 bool MightHaveChildren() override;
425 size_t GetIndexOfChildWithName(ConstString name) override;
427 lldb::ValueObjectSP GetSyntheticValue() override;
429 ConstString GetSyntheticTypeName() override;
431 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
434 std::string m_python_class;
435 StructuredData::ObjectSP m_wrapper_sp;
436 ScriptInterpreter *m_interpreter;
438 DISALLOW_COPY_AND_ASSIGN(FrontEnd);
441 SyntheticChildrenFrontEnd::AutoPointer
442 GetFrontEnd(ValueObject &backend) override {
443 auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(
444 new FrontEnd(m_python_class, backend));
445 if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
451 DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren);
453 } // namespace lldb_private
455 #endif // lldb_TypeSynthetic_h_