Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:47

0001 //===-- TypeSynthetic.h -----------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
0010 #define LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
0011 
0012 #include <cstdint>
0013 
0014 #include <functional>
0015 #include <initializer_list>
0016 #include <memory>
0017 #include <string>
0018 #include <vector>
0019 
0020 #include "lldb/lldb-enumerations.h"
0021 #include "lldb/lldb-public.h"
0022 
0023 #include "lldb/Utility/StructuredData.h"
0024 #include "lldb/ValueObject/ValueObject.h"
0025 
0026 namespace lldb_private {
0027 class SyntheticChildrenFrontEnd {
0028 protected:
0029   ValueObject &m_backend;
0030 
0031   void SetValid(bool valid) { m_valid = valid; }
0032 
0033   bool IsValid() { return m_valid; }
0034 
0035 public:
0036   SyntheticChildrenFrontEnd(ValueObject &backend)
0037       : m_backend(backend), m_valid(true) {}
0038 
0039   virtual ~SyntheticChildrenFrontEnd() = default;
0040 
0041   virtual llvm::Expected<uint32_t> CalculateNumChildren() = 0;
0042 
0043   virtual llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) {
0044     auto count = CalculateNumChildren();
0045     if (!count)
0046       return count;
0047     return *count <= max ? *count : max;
0048   }
0049 
0050   uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max = UINT32_MAX);
0051 
0052   virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) = 0;
0053 
0054   virtual size_t GetIndexOfChildWithName(ConstString name) = 0;
0055 
0056   /// This function is assumed to always succeed and if it fails, the front-end
0057   /// should know to deal with it in the correct way (most probably, by refusing
0058   /// to return any children). The return value of \ref Update should actually
0059   /// be interpreted as "ValueObjectSyntheticFilter cache is good/bad". If this
0060   /// function returns \ref lldb::ChildCacheState::eReuse, \ref
0061   /// ValueObjectSyntheticFilter is allowed to use the children it fetched
0062   /// previously and cached. Otherwise, \ref ValueObjectSyntheticFilter must
0063   /// throw away its cache, and query again for children.
0064   virtual lldb::ChildCacheState Update() = 0;
0065 
0066   // if this function returns false, then CalculateNumChildren() MUST return 0
0067   // since UI frontends might validly decide not to inquire for children given
0068   // a false return value from this call if it returns true, then
0069   // CalculateNumChildren() can return any number >= 0 (0 being valid) it
0070   // should if at all possible be more efficient than CalculateNumChildren()
0071   virtual bool MightHaveChildren() = 0;
0072 
0073   // if this function returns a non-null ValueObject, then the returned
0074   // ValueObject will stand for this ValueObject whenever a "value" request is
0075   // made to this ValueObject
0076   virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
0077 
0078   // if this function returns a non-empty ConstString, then clients are
0079   // expected to use the return as the name of the type of this ValueObject for
0080   // display purposes
0081   virtual ConstString GetSyntheticTypeName() { return ConstString(); }
0082 
0083   typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
0084   typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
0085 
0086 protected:
0087   lldb::ValueObjectSP
0088   CreateValueObjectFromExpression(llvm::StringRef name,
0089                                   llvm::StringRef expression,
0090                                   const ExecutionContext &exe_ctx);
0091 
0092   lldb::ValueObjectSP
0093   CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
0094                                const ExecutionContext &exe_ctx,
0095                                CompilerType type);
0096 
0097   lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name,
0098                                                 const DataExtractor &data,
0099                                                 const ExecutionContext &exe_ctx,
0100                                                 CompilerType type);
0101 
0102 private:
0103   bool m_valid;
0104   SyntheticChildrenFrontEnd(const SyntheticChildrenFrontEnd &) = delete;
0105   const SyntheticChildrenFrontEnd &
0106   operator=(const SyntheticChildrenFrontEnd &) = delete;
0107 };
0108 
0109 class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
0110 public:
0111   SyntheticValueProviderFrontEnd(ValueObject &backend)
0112       : SyntheticChildrenFrontEnd(backend) {}
0113 
0114   ~SyntheticValueProviderFrontEnd() override = default;
0115 
0116   llvm::Expected<uint32_t> CalculateNumChildren() override { return 0; }
0117 
0118   lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override { return nullptr; }
0119 
0120   size_t GetIndexOfChildWithName(ConstString name) override {
0121     return UINT32_MAX;
0122   }
0123 
0124   lldb::ChildCacheState Update() override {
0125     return lldb::ChildCacheState::eRefetch;
0126   }
0127 
0128   bool MightHaveChildren() override { return false; }
0129 
0130   lldb::ValueObjectSP GetSyntheticValue() override = 0;
0131 
0132 private:
0133   SyntheticValueProviderFrontEnd(const SyntheticValueProviderFrontEnd &) =
0134       delete;
0135   const SyntheticValueProviderFrontEnd &
0136   operator=(const SyntheticValueProviderFrontEnd &) = delete;
0137 };
0138 
0139 class SyntheticChildren {
0140 public:
0141   class Flags {
0142   public:
0143     Flags() = default;
0144 
0145     Flags(const Flags &other) : m_flags(other.m_flags) {}
0146 
0147     Flags(uint32_t value) : m_flags(value) {}
0148 
0149     Flags &operator=(const Flags &rhs) {
0150       if (&rhs != this)
0151         m_flags = rhs.m_flags;
0152 
0153       return *this;
0154     }
0155 
0156     Flags &operator=(const uint32_t &rhs) {
0157       m_flags = rhs;
0158       return *this;
0159     }
0160 
0161     Flags &Clear() {
0162       m_flags = 0;
0163       return *this;
0164     }
0165 
0166     bool GetCascades() const {
0167       return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
0168     }
0169 
0170     Flags &SetCascades(bool value = true) {
0171       if (value)
0172         m_flags |= lldb::eTypeOptionCascade;
0173       else
0174         m_flags &= ~lldb::eTypeOptionCascade;
0175       return *this;
0176     }
0177 
0178     bool GetSkipPointers() const {
0179       return (m_flags & lldb::eTypeOptionSkipPointers) ==
0180              lldb::eTypeOptionSkipPointers;
0181     }
0182 
0183     Flags &SetSkipPointers(bool value = true) {
0184       if (value)
0185         m_flags |= lldb::eTypeOptionSkipPointers;
0186       else
0187         m_flags &= ~lldb::eTypeOptionSkipPointers;
0188       return *this;
0189     }
0190 
0191     bool GetSkipReferences() const {
0192       return (m_flags & lldb::eTypeOptionSkipReferences) ==
0193              lldb::eTypeOptionSkipReferences;
0194     }
0195 
0196     Flags &SetSkipReferences(bool value = true) {
0197       if (value)
0198         m_flags |= lldb::eTypeOptionSkipReferences;
0199       else
0200         m_flags &= ~lldb::eTypeOptionSkipReferences;
0201       return *this;
0202     }
0203 
0204     bool GetNonCacheable() const {
0205       return (m_flags & lldb::eTypeOptionNonCacheable) ==
0206              lldb::eTypeOptionNonCacheable;
0207     }
0208 
0209     Flags &SetNonCacheable(bool value = true) {
0210       if (value)
0211         m_flags |= lldb::eTypeOptionNonCacheable;
0212       else
0213         m_flags &= ~lldb::eTypeOptionNonCacheable;
0214       return *this;
0215     }
0216 
0217     bool GetFrontEndWantsDereference() const {
0218       return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
0219              lldb::eTypeOptionFrontEndWantsDereference;
0220     }
0221 
0222     Flags &SetFrontEndWantsDereference(bool value = true) {
0223       if (value)
0224         m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
0225       else
0226         m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
0227       return *this;
0228     }
0229 
0230     uint32_t GetValue() { return m_flags; }
0231 
0232     void SetValue(uint32_t value) { m_flags = value; }
0233 
0234   private:
0235     uint32_t m_flags = lldb::eTypeOptionCascade;
0236   };
0237 
0238   SyntheticChildren(const Flags &flags);
0239 
0240   virtual ~SyntheticChildren();
0241 
0242   bool Cascades() const { return m_flags.GetCascades(); }
0243 
0244   bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
0245 
0246   bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
0247 
0248   bool NonCacheable() const { return m_flags.GetNonCacheable(); }
0249 
0250   bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
0251 
0252   void SetCascades(bool value) { m_flags.SetCascades(value); }
0253 
0254   void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
0255 
0256   void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
0257 
0258   void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
0259 
0260   uint32_t GetOptions() { return m_flags.GetValue(); }
0261 
0262   void SetOptions(uint32_t value) { m_flags.SetValue(value); }
0263 
0264   virtual bool IsScripted() = 0;
0265 
0266   virtual std::string GetDescription() = 0;
0267 
0268   virtual SyntheticChildrenFrontEnd::AutoPointer
0269   GetFrontEnd(ValueObject &backend) = 0;
0270 
0271   typedef std::shared_ptr<SyntheticChildren> SharedPointer;
0272 
0273   uint32_t &GetRevision() { return m_my_revision; }
0274 
0275 protected:
0276   uint32_t m_my_revision = 0;
0277   Flags m_flags;
0278 
0279 private:
0280   SyntheticChildren(const SyntheticChildren &) = delete;
0281   const SyntheticChildren &operator=(const SyntheticChildren &) = delete;
0282 };
0283 
0284 class TypeFilterImpl : public SyntheticChildren {
0285   std::vector<std::string> m_expression_paths;
0286 
0287 public:
0288   TypeFilterImpl(const SyntheticChildren::Flags &flags)
0289       : SyntheticChildren(flags) {}
0290 
0291   TypeFilterImpl(const SyntheticChildren::Flags &flags,
0292                  const std::initializer_list<const char *> items)
0293       : SyntheticChildren(flags) {
0294     for (auto path : items)
0295       AddExpressionPath(path);
0296   }
0297 
0298   void AddExpressionPath(const char *path) {
0299     AddExpressionPath(std::string(path));
0300   }
0301 
0302   void Clear() { m_expression_paths.clear(); }
0303 
0304   size_t GetCount() const { return m_expression_paths.size(); }
0305 
0306   const char *GetExpressionPathAtIndex(size_t i) const {
0307     return m_expression_paths[i].c_str();
0308   }
0309 
0310   bool SetExpressionPathAtIndex(size_t i, const char *path) {
0311     return SetExpressionPathAtIndex(i, std::string(path));
0312   }
0313 
0314   void AddExpressionPath(const std::string &path);
0315 
0316   bool SetExpressionPathAtIndex(size_t i, const std::string &path);
0317 
0318   bool IsScripted() override { return false; }
0319 
0320   std::string GetDescription() override;
0321 
0322   class FrontEnd : public SyntheticChildrenFrontEnd {
0323   public:
0324     FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
0325         : SyntheticChildrenFrontEnd(backend), filter(flt) {}
0326 
0327     ~FrontEnd() override = default;
0328 
0329     llvm::Expected<uint32_t> CalculateNumChildren() override {
0330       return filter->GetCount();
0331     }
0332 
0333     lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
0334       if (idx >= filter->GetCount())
0335         return lldb::ValueObjectSP();
0336       return m_backend.GetSyntheticExpressionPathChild(
0337           filter->GetExpressionPathAtIndex(idx), true);
0338     }
0339 
0340     lldb::ChildCacheState Update() override {
0341       return lldb::ChildCacheState::eRefetch;
0342     }
0343 
0344     bool MightHaveChildren() override { return filter->GetCount() > 0; }
0345 
0346     size_t GetIndexOfChildWithName(ConstString name) override;
0347 
0348     typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
0349 
0350   private:
0351     TypeFilterImpl *filter;
0352 
0353     FrontEnd(const FrontEnd &) = delete;
0354     const FrontEnd &operator=(const FrontEnd &) = delete;
0355   };
0356 
0357   SyntheticChildrenFrontEnd::AutoPointer
0358   GetFrontEnd(ValueObject &backend) override {
0359     return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
0360   }
0361 
0362   typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
0363 
0364 private:
0365   TypeFilterImpl(const TypeFilterImpl &) = delete;
0366   const TypeFilterImpl &operator=(const TypeFilterImpl &) = delete;
0367 };
0368 
0369 class CXXSyntheticChildren : public SyntheticChildren {
0370 public:
0371   typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
0372                                                     lldb::ValueObjectSP)>
0373       CreateFrontEndCallback;
0374   CXXSyntheticChildren(const SyntheticChildren::Flags &flags,
0375                        const char *description, CreateFrontEndCallback callback);
0376 
0377   virtual ~CXXSyntheticChildren();
0378 
0379   bool IsScripted() override { return false; }
0380 
0381   std::string GetDescription() override;
0382 
0383   SyntheticChildrenFrontEnd::AutoPointer
0384   GetFrontEnd(ValueObject &backend) override {
0385     return SyntheticChildrenFrontEnd::AutoPointer(
0386         m_create_callback(this, backend.GetSP()));
0387   }
0388 
0389 protected:
0390   CreateFrontEndCallback m_create_callback;
0391   std::string m_description;
0392 
0393 private:
0394   CXXSyntheticChildren(const CXXSyntheticChildren &) = delete;
0395   const CXXSyntheticChildren &operator=(const CXXSyntheticChildren &) = delete;
0396 };
0397 
0398 class ScriptedSyntheticChildren : public SyntheticChildren {
0399   std::string m_python_class;
0400   std::string m_python_code;
0401 
0402 public:
0403   ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags,
0404                             const char *pclass, const char *pcode = nullptr)
0405       : SyntheticChildren(flags) {
0406     if (pclass)
0407       m_python_class = pclass;
0408     if (pcode)
0409       m_python_code = pcode;
0410   }
0411 
0412   const char *GetPythonClassName() { return m_python_class.c_str(); }
0413 
0414   const char *GetPythonCode() { return m_python_code.c_str(); }
0415 
0416   void SetPythonClassName(const char *fname) {
0417     m_python_class.assign(fname);
0418     m_python_code.clear();
0419   }
0420 
0421   void SetPythonCode(const char *script) { m_python_code.assign(script); }
0422 
0423   std::string GetDescription() override;
0424 
0425   bool IsScripted() override { return true; }
0426 
0427   class FrontEnd : public SyntheticChildrenFrontEnd {
0428   public:
0429     FrontEnd(std::string pclass, ValueObject &backend);
0430 
0431     ~FrontEnd() override;
0432 
0433     bool IsValid();
0434 
0435     llvm::Expected<uint32_t> CalculateNumChildren() override;
0436 
0437     llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
0438 
0439     lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
0440 
0441     lldb::ChildCacheState Update() override;
0442 
0443     bool MightHaveChildren() override;
0444 
0445     size_t GetIndexOfChildWithName(ConstString name) override;
0446 
0447     lldb::ValueObjectSP GetSyntheticValue() override;
0448 
0449     ConstString GetSyntheticTypeName() override;
0450 
0451     typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
0452 
0453   private:
0454     std::string m_python_class;
0455     StructuredData::ObjectSP m_wrapper_sp;
0456     ScriptInterpreter *m_interpreter;
0457 
0458     FrontEnd(const FrontEnd &) = delete;
0459     const FrontEnd &operator=(const FrontEnd &) = delete;
0460   };
0461 
0462   SyntheticChildrenFrontEnd::AutoPointer
0463   GetFrontEnd(ValueObject &backend) override {
0464     auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(
0465         new FrontEnd(m_python_class, backend));
0466     if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
0467       return synth_ptr;
0468     return nullptr;
0469   }
0470 
0471 private:
0472   ScriptedSyntheticChildren(const ScriptedSyntheticChildren &) = delete;
0473   const ScriptedSyntheticChildren &
0474   operator=(const ScriptedSyntheticChildren &) = delete;
0475 };
0476 } // namespace lldb_private
0477 
0478 #endif // LLDB_DATAFORMATTERS_TYPESYNTHETIC_H