diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp index fa603642363b8..9b41b5801e46c 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "ReflectionContextInterface.h" #include "SwiftLanguageRuntimeImpl.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" @@ -25,7 +26,7 @@ namespace { /// 32-bit or 64-bit pointers, with and without ObjC interoperability. template class TargetReflectionContext - : public SwiftLanguageRuntimeImpl::ReflectionContextInterface { + : public ReflectionContextInterface { ReflectionContext m_reflection_ctx; swift::reflection::TypeConverter m_type_converter; @@ -142,10 +143,9 @@ class TargetReflectionContext return m_reflection_ctx.getBuilder().lookupSuperclass(tr); } - bool ForEachSuperClassType( - swift::remote::TypeInfoProvider *tip, lldb::addr_t pointer, - std::function fn) - override { + bool ForEachSuperClassType(swift::remote::TypeInfoProvider *tip, + lldb::addr_t pointer, + std::function fn) override { // Guard against faulty self-referential metadata. unsigned limit = 256; auto md_ptr = m_reflection_ctx.readMetadataFromInstance(pointer); @@ -239,8 +239,8 @@ class TargetReflectionContext } // namespace namespace lldb_private { -std::unique_ptr -SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext( +std::unique_ptr +ReflectionContextInterface::CreateReflectionContext( uint8_t ptr_size, std::shared_ptr reader, bool ObjCInterop, SwiftMetadataCache *swift_metadata_cache) { using ReflectionContext32ObjCInterop = diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContextInterface.h b/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContextInterface.h new file mode 100644 index 0000000000000..6b774ffefb96f --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContextInterface.h @@ -0,0 +1,142 @@ +#ifndef liblldb_SwiftReflectionContextInterface_h_ +#define liblldb_SwiftReflectionContextInterface_h_ + +#include + +#include "lldb/lldb-types.h" +#include "swift/ABI/ObjectFile.h" +#include "swift/Remote/RemoteAddress.h" +#include "swift/RemoteInspection/TypeRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Memory.h" + +namespace swift { +namespace Demangle { +class Demangler; +} // namespace Demangle +namespace reflection { +class RecordTypeInfo; +class TypeInfo; +} // namespace reflection +namespace remote { +class MemoryReader; +struct TypeInfoProvider; +} // namespace remote +} // namespace swift + +namespace lldb_private { +struct SwiftMetadataCache; + +/// Returned by \ref ForEachSuperClassType. Not every user of \p +/// ForEachSuperClassType needs all of these. By returning this +/// object we call into the runtime only when needed. +/// Using function objects to avoid instantiating ReflectionContext in this +/// header. +struct SuperClassType { + std::function + get_record_type_info; + std::function get_typeref; +}; + +/// An abstract interface to swift::reflection::ReflectionContext +/// objects of varying pointer sizes. This class encapsulates all +/// traffic to ReflectionContext and abstracts the detail that +/// ReflectionContext is a template that needs to be specialized for +/// a specific pointer width. +class ReflectionContextInterface { +public: + /// Return a reflection context. + static std::unique_ptr CreateReflectionContext( + uint8_t pointer_size, std::shared_ptr reader, + bool objc_interop, SwiftMetadataCache *swift_metadata_cache); + + virtual ~ReflectionContextInterface() = default; + + virtual llvm::Optional AddImage( + llvm::function_ref, uint64_t>( + swift::ReflectionSectionKind)> + find_section, + llvm::SmallVector likely_module_names = {}) = 0; + virtual llvm::Optional + AddImage(swift::remote::RemoteAddress image_start, + llvm::SmallVector likely_module_names = {}) = 0; + virtual llvm::Optional + ReadELF(swift::remote::RemoteAddress ImageStart, + llvm::Optional FileBuffer, + llvm::SmallVector likely_module_names = {}) = 0; + virtual const swift::reflection::TypeRef * + GetTypeRefOrNull(llvm::StringRef mangled_type_name) = 0; + virtual const swift::reflection::TypeRef * + GetTypeRefOrNull(swift::Demangle::Demangler &dem, + swift::Demangle::NodePointer node) = 0; + virtual const swift::reflection::TypeInfo * + GetClassInstanceTypeInfo(const swift::reflection::TypeRef *type_ref, + swift::remote::TypeInfoProvider *provider) = 0; + virtual const swift::reflection::TypeInfo * + GetTypeInfo(const swift::reflection::TypeRef *type_ref, + swift::remote::TypeInfoProvider *provider) = 0; + virtual const swift::reflection::TypeInfo * + GetTypeInfoFromInstance(lldb::addr_t instance, + swift::remote::TypeInfoProvider *provider) = 0; + virtual swift::remote::MemoryReader &GetReader() = 0; + virtual const swift::reflection::TypeRef * + LookupSuperclass(const swift::reflection::TypeRef *tr) = 0; + virtual bool + ForEachSuperClassType(swift::remote::TypeInfoProvider *tip, + lldb::addr_t pointer, + std::function fn) = 0; + virtual llvm::Optional> + ProjectExistentialAndUnwrapClass( + swift::remote::RemoteAddress existential_addess, + const swift::reflection::TypeRef &existential_tr) = 0; + virtual llvm::Optional + ProjectEnumValue(swift::remote::RemoteAddress enum_addr, + const swift::reflection::TypeRef *enum_type_ref, + swift::remote::TypeInfoProvider *provider) = 0; + virtual const swift::reflection::TypeRef * + ReadTypeFromMetadata(lldb::addr_t metadata_address, + bool skip_artificial_subclasses = false) = 0; + virtual const swift::reflection::TypeRef * + ReadTypeFromInstance(lldb::addr_t instance_address, + bool skip_artificial_subclasses = false) = 0; + virtual llvm::Optional IsValueInlinedInExistentialContainer( + swift::remote::RemoteAddress existential_address) = 0; + virtual const swift::reflection::TypeRef * + ApplySubstitutions(const swift::reflection::TypeRef *type_ref, + swift::reflection::GenericArgumentMap substitutions) = 0; + virtual swift::remote::RemoteAbsolutePointer + StripSignedPointer(swift::remote::RemoteAbsolutePointer pointer) = 0; +}; + +/// A wrapper around TargetReflectionContext, which holds a lock to ensure +/// exclusive access. +struct ThreadSafeReflectionContext { + ThreadSafeReflectionContext(ReflectionContextInterface *reflection_ctx, + std::recursive_mutex &mutex) + : m_reflection_ctx(reflection_ctx), m_lock(mutex, std::adopt_lock) {} + + static ThreadSafeReflectionContext MakeInvalid() { + // This exists so we can create an "empty" reflection context in the stub + // language runtime. + static std::recursive_mutex mutex; + return ThreadSafeReflectionContext(nullptr, mutex); + } + + ReflectionContextInterface *operator->() const { return m_reflection_ctx; } + + operator bool() const { return m_reflection_ctx != nullptr; } + +private: + ReflectionContextInterface *m_reflection_ctx; + // This lock operates on a recursive mutex because the initialization + // of ReflectionContext recursive calls itself (see + // SwiftLanguageRuntimeImpl::SetupReflection). + std::lock_guard m_lock; +}; + +} // namespace lldb_private +#endif diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp index 25c09b88e503e..447c23ddad039 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp @@ -12,6 +12,7 @@ #include "SwiftLanguageRuntime.h" #include "Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h" +#include "ReflectionContextInterface.h" #include "SwiftLanguageRuntimeImpl.h" #include "SwiftMetadataCache.h" @@ -233,6 +234,11 @@ class SwiftLanguageRuntimeStub { assert(false && "called into swift language runtime stub"); \ } while (0) + ThreadSafeReflectionContext GetReflectionContext() { + STUB_LOG(); + return ThreadSafeReflectionContext::MakeInvalid(); + } + bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, @@ -445,7 +451,7 @@ static bool HasReflectionInfo(ObjectFile *obj_file) { return hasReflectionSection; } -SwiftLanguageRuntimeImpl::ThreadSafeReflectionContext +ThreadSafeReflectionContext SwiftLanguageRuntimeImpl::GetReflectionContext() { m_reflection_ctx_mutex.lock(); SetupReflection(); @@ -2333,6 +2339,11 @@ void SwiftLanguageRuntime::Terminate() { assert(m_impl || m_stub); \ return m_impl ? m_impl->METHOD(__VA_ARGS__) : m_stub->METHOD(__VA_ARGS__); +ThreadSafeReflectionContext +SwiftLanguageRuntime::GetReflectionContext() { + FORWARD(GetReflectionContext); +} + bool SwiftLanguageRuntime::GetDynamicTypeAndAddress( ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address, diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h index 6e6d043ce5b5b..af016377b4f18 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h @@ -14,6 +14,7 @@ #define liblldb_SwiftLanguageRuntime_h_ #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h" +#include "Plugins/LanguageRuntime/Swift/SwiftMetadataCache.h" #include "Plugins/TypeSystem/Swift/SwiftASTContext.h" #include "lldb/Breakpoint/BreakpointPrecondition.h" #include "lldb/Core/PluginInterface.h" @@ -50,6 +51,7 @@ class TypeBase; } // namespace swift namespace lldb_private { +struct ThreadSafeReflectionContext; /// Statically cast a CompilerType to a Swift type. swift::Type GetSwiftType(CompilerType type); @@ -58,6 +60,7 @@ swift::CanType GetCanonicalSwiftType(CompilerType type); class SwiftLanguageRuntimeStub; class SwiftLanguageRuntimeImpl; +class ReflectionContextInterface; class SwiftLanguageRuntime : public LanguageRuntime { protected: @@ -73,6 +76,7 @@ class SwiftLanguageRuntime : public LanguageRuntime { std::unique_ptr m_impl; public: + ThreadSafeReflectionContext GetReflectionContext(); static char ID; bool isA(const void *ClassID) const override { diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 432cdd9d14795..400a0dcb67273 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "LLDBMemoryReader.h" +#include "ReflectionContextInterface.h" #include "SwiftLanguageRuntime.h" #include "SwiftLanguageRuntimeImpl.h" #include "SwiftMetadataCache.h" @@ -220,9 +221,6 @@ lldb::addr_t SwiftLanguageRuntime::MaybeMaskNonTrivialReferencePointer( return addr & ~mask; } -SwiftLanguageRuntimeImpl::ReflectionContextInterface:: - ~ReflectionContextInterface() {} - const CompilerType &SwiftLanguageRuntimeImpl::GetBoxMetadataType() { if (m_box_metadata_type.IsValid()) return m_box_metadata_type; diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h index 031b631656d74..9d129f0a10a98 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h @@ -27,6 +27,8 @@ class TypeRef; namespace lldb_private { class Process; class LLDBTypeInfoProvider; +class ReflectionContextInterface; +struct SuperClassType; /// A full LLDB language runtime backed by the Swift runtime library /// in the process. @@ -193,112 +195,12 @@ class SwiftLanguageRuntimeImpl { void DumpTyperef(CompilerType type, TypeSystemSwiftTypeRef *module_holder, Stream *s); - /// Returned by \ref ForEachSuperClassType. Not every user of \p - /// ForEachSuperClassType needs all of these. By returning this - /// object we call into the runtime only when needed. - /// Using function objects to avoid instantiating ReflectionContext in this header. - struct SuperClassType { - std::function get_record_type_info; - std::function get_typeref; - }; Process &GetProcess() const; - /// An abstract interface to swift::reflection::ReflectionContext - /// objects of varying pointer sizes. This class encapsulates all - /// traffic to ReflectionContext and abstracts the detail that - /// ReflectionContext is a template that needs to be specialized for - /// a specific pointer width. - class ReflectionContextInterface { - public: - /// Return a reflection context. - static std::unique_ptr - CreateReflectionContext(uint8_t pointer_size, - std::shared_ptr reader, bool objc_interop, - SwiftMetadataCache *swift_metadata_cache); - - virtual ~ReflectionContextInterface(); - - virtual llvm::Optional AddImage( - llvm::function_ref, uint64_t>( - swift::ReflectionSectionKind)> - find_section, - llvm::SmallVector likely_module_names = {}) = 0; - virtual llvm::Optional AddImage( - swift::remote::RemoteAddress image_start, - llvm::SmallVector likely_module_names = {}) = 0; - virtual llvm::Optional - ReadELF(swift::remote::RemoteAddress ImageStart, - llvm::Optional FileBuffer, - llvm::SmallVector likely_module_names = {}) = 0; - virtual const swift::reflection::TypeRef * - GetTypeRefOrNull(StringRef mangled_type_name) = 0; - virtual const swift::reflection::TypeRef * - GetTypeRefOrNull(swift::Demangle::Demangler &dem, - swift::Demangle::NodePointer node) = 0; - virtual const swift::reflection::TypeInfo * - GetClassInstanceTypeInfo(const swift::reflection::TypeRef *type_ref, - swift::remote::TypeInfoProvider *provider) = 0; - virtual const swift::reflection::TypeInfo * - GetTypeInfo(const swift::reflection::TypeRef *type_ref, - swift::remote::TypeInfoProvider *provider) = 0; - virtual const swift::reflection::TypeInfo * - GetTypeInfoFromInstance(lldb::addr_t instance, - swift::remote::TypeInfoProvider *provider) = 0; - virtual swift::remote::MemoryReader &GetReader() = 0; - virtual const swift::reflection::TypeRef * - LookupSuperclass(const swift::reflection::TypeRef *tr) = 0; - virtual bool - ForEachSuperClassType(swift::remote::TypeInfoProvider *tip, - lldb::addr_t pointer, - std::function fn) = 0; - virtual llvm::Optional> - ProjectExistentialAndUnwrapClass( - swift::remote::RemoteAddress existential_addess, - const swift::reflection::TypeRef &existential_tr) = 0; - virtual llvm::Optional - ProjectEnumValue(swift::remote::RemoteAddress enum_addr, - const swift::reflection::TypeRef *enum_type_ref, - swift::remote::TypeInfoProvider *provider) = 0; - virtual const swift::reflection::TypeRef * - ReadTypeFromMetadata(lldb::addr_t metadata_address, - bool skip_artificial_subclasses = false) = 0; - virtual const swift::reflection::TypeRef * - ReadTypeFromInstance(lldb::addr_t instance_address, - bool skip_artificial_subclasses = false) = 0; - virtual llvm::Optional IsValueInlinedInExistentialContainer( - swift::remote::RemoteAddress existential_address) = 0; - virtual const swift::reflection::TypeRef * - ApplySubstitutions(const swift::reflection::TypeRef *type_ref, - swift::reflection::GenericArgumentMap substitutions) = 0; - virtual swift::remote::RemoteAbsolutePointer - StripSignedPointer(swift::remote::RemoteAbsolutePointer pointer) = 0; - }; - - /// A wrapper around TargetReflectionContext, which holds a lock to ensure - /// exclusive access. - struct ThreadSafeReflectionContext { - ThreadSafeReflectionContext(ReflectionContextInterface *reflection_ctx, - std::recursive_mutex &mutex) - : m_reflection_ctx(reflection_ctx), m_lock(mutex, std::adopt_lock) {} - - ReflectionContextInterface *operator->() const { - return m_reflection_ctx; - } - - operator bool() const { - return m_reflection_ctx != nullptr; - } - - private: - ReflectionContextInterface *m_reflection_ctx; - // This lock operates on a recursive mutex because the initialization - // of ReflectionContext recursive calls itself (see - // SwiftLanguageRuntimeImpl::SetupReflection). - std::lock_guard m_lock; - }; - + /// Lazily initialize the reflection context. Returns a + /// ThreadSafeReflectionContext with a \p nullptr on failure. + ThreadSafeReflectionContext GetReflectionContext(); protected: static void ForEachGenericParameter(swift::Demangle::NodePointer node, @@ -314,8 +216,9 @@ class SwiftLanguageRuntimeImpl { /// RecordTypeInfo and pass it to the callback \p fn. Repeat the /// process with all superclasses. If \p fn returns \p true, early /// exit and return \p true. Otherwise return \p false. - bool ForEachSuperClassType(ValueObject &instance, - std::function fn); + bool ForEachSuperClassType( + ValueObject &instance, + std::function fn); // Classes that inherit from SwiftLanguageRuntime can see and modify these Value::ValueType GetValueType(ValueObject &in_value, @@ -461,10 +364,6 @@ class SwiftLanguageRuntimeImpl { /// Lazily initialize and return \p m_dynamic_exclusivity_flag_addr. llvm::Optional GetDynamicExclusivityFlagAddr(); - /// Lazily initialize the reflection context. Returns a - /// ThreadSafeReflectionContext with a \p nullptr on failure. - ThreadSafeReflectionContext GetReflectionContext(); - // Add the modules in m_modules_to_add to the Reflection Context. The // ModulesDidLoad() callback appends to m_modules_to_add. void ProcessModulesToAdd(); diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp index a344af02d0d21..8ab8574bcfa58 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "ReflectionContextInterface.h" #include "SwiftLanguageRuntimeImpl.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Utility/LLDBLog.h"