diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/Swift/CMakeLists.txt index 3ba4b24567a6b..0318e5c3fbfd0 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/Swift/CMakeLists.txt @@ -1,8 +1,10 @@ add_lldb_library(lldbPluginSwiftLanguageRuntime PLUGIN LLDBMemoryReader.cpp + ReflectionContext.cpp SwiftLanguageRuntime.cpp SwiftLanguageRuntimeDynamicTypeResolution.cpp SwiftLanguageRuntimeNames.cpp + SwiftLanguageRuntimeRemoteAST.cpp SwiftMetadataCache.cpp LINK_LIBS diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp new file mode 100644 index 0000000000000..ed3640069f6d5 --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp @@ -0,0 +1,214 @@ +//===-- ReflectionContext.cpp --------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include "SwiftLanguageRuntimeImpl.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +/// An implementation of the generic ReflectionContextInterface that +/// is templatized on target pointer width and specialized to either +/// 32-bit or 64-bit pointers, with and without ObjC interoperability. +template +class TargetReflectionContext + : public SwiftLanguageRuntimeImpl::ReflectionContextInterface { + ReflectionContext m_reflection_ctx; + +public: + TargetReflectionContext( + std::shared_ptr reader, + SwiftMetadataCache *swift_metadata_cache) + : m_reflection_ctx(reader, swift_metadata_cache) {} + + llvm::Optional AddImage( + llvm::function_ref, uint64_t>( + swift::ReflectionSectionKind)> + find_section, + llvm::SmallVector likely_module_names) override { + return m_reflection_ctx.addImage(find_section, likely_module_names); + } + + llvm::Optional + AddImage(swift::remote::RemoteAddress image_start, + llvm::SmallVector likely_module_names) override { + return m_reflection_ctx.addImage(image_start, likely_module_names); + } + + llvm::Optional ReadELF( + swift::remote::RemoteAddress ImageStart, + llvm::Optional FileBuffer, + llvm::SmallVector likely_module_names = {}) override { + return m_reflection_ctx.readELF(ImageStart, FileBuffer, + likely_module_names); + } + + const swift::reflection::TypeInfo * + GetTypeInfo(const swift::reflection::TypeRef *type_ref, + swift::remote::TypeInfoProvider *provider) override { + if (!type_ref) + return nullptr; + + Log *log(GetLog(LLDBLog::Types)); + if (log && log->GetVerbose()) { + std::stringstream ss; + type_ref->dump(ss); + LLDB_LOGF(log, + "[TargetReflectionContext::getTypeInfo] Getting " + "type info for typeref:\n%s", + ss.str().c_str()); + } + + auto type_info = m_reflection_ctx.getTypeInfo(type_ref, provider); + if (log && !type_info) { + std::stringstream ss; + type_ref->dump(ss); + LLDB_LOGF(log, + "[TargetReflectionContext::getTypeInfo] Could not get " + "type info for typeref:\n%s", + ss.str().c_str()); + } + + if (type_info && log && log->GetVerbose()) { + std::stringstream ss; + type_info->dump(ss); + log->Printf("[TargetReflectionContext::getTypeInfo] Found " + "type info:\n%s", + ss.str().c_str()); + } + return type_info; + } + + swift::reflection::MemoryReader &GetReader() override { + return m_reflection_ctx.getReader(); + } + + 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); + if (!md_ptr) + return false; + + // Class object. + while (md_ptr && *md_ptr && --limit) { + // Reading metadata is potentially expensive since (in a remote + // debugging scenario it may even incur network traffic) so we + // just return closures that the caller can use to query details + // if they need them.' + auto metadata = *md_ptr; + if (fn({[=]() -> const swift::reflection::RecordTypeInfo * { + auto *ti = m_reflection_ctx.getMetadataTypeInfo(metadata, tip); + return llvm::dyn_cast_or_null< + swift::reflection::RecordTypeInfo>(ti); + }, + [=]() -> const swift::reflection::TypeRef * { + return m_reflection_ctx.readTypeFromMetadata(metadata); + }})) + return true; + + // Continue with the base class. + md_ptr = m_reflection_ctx.readSuperClassFromClassMetadata(metadata); + } + return false; + } + + llvm::Optional> + ProjectExistentialAndUnwrapClass( + swift::reflection::RemoteAddress existential_address, + const swift::reflection::TypeRef &existential_tr) override { + return m_reflection_ctx.projectExistentialAndUnwrapClass( + existential_address, existential_tr); + } + + const swift::reflection::TypeRef * + ReadTypeFromMetadata(lldb::addr_t metadata_address, + bool skip_artificial_subclasses) override { + return m_reflection_ctx.readTypeFromMetadata(metadata_address, + skip_artificial_subclasses); + } + + const swift::reflection::TypeRef * + ReadTypeFromInstance(lldb::addr_t instance_address, + bool skip_artificial_subclasses) override { + auto metadata_address = + m_reflection_ctx.readMetadataFromInstance(instance_address); + if (!metadata_address) { + LLDB_LOGF(GetLog(LLDBLog::Types), + "could not read heap metadata for object at %llu\n", + instance_address); + return nullptr; + } + + return m_reflection_ctx.readTypeFromMetadata(*metadata_address, + skip_artificial_subclasses); + } + + swift::reflection::TypeRefBuilder &GetBuilder() override { + return m_reflection_ctx.getBuilder(); + } + + llvm::Optional IsValueInlinedInExistentialContainer( + swift::remote::RemoteAddress existential_address) override { + return m_reflection_ctx.isValueInlinedInExistentialContainer( + existential_address); + } + + swift::remote::RemoteAbsolutePointer + StripSignedPointer(swift::remote::RemoteAbsolutePointer pointer) override { + return m_reflection_ctx.stripSignedPointer(pointer); + } +}; + +} // namespace + +namespace lldb_private { +std::unique_ptr +SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext( + uint8_t ptr_size, std::shared_ptr reader, + bool ObjCInterop, SwiftMetadataCache *swift_metadata_cache) { + using ReflectionContext32ObjCInterop = + TargetReflectionContext>>>>; + using ReflectionContext32NoObjCInterop = + TargetReflectionContext>>>>; + using ReflectionContext64ObjCInterop = + TargetReflectionContext>>>>; + using ReflectionContext64NoObjCInterop = + TargetReflectionContext>>>>; + if (ptr_size == 4) { + if (ObjCInterop) + return std::make_unique( + reader, swift_metadata_cache); + return std::make_unique( + reader, swift_metadata_cache); + } + if (ptr_size == 8) { + if (ObjCInterop) + return std::make_unique( + reader, swift_metadata_cache); + return std::make_unique( + reader, swift_metadata_cache); + } + return {}; +} +} // namespace lldb_private diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp index d09a43125b5ba..077521b9577b4 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp @@ -44,8 +44,6 @@ #include "lldb/Utility/Timer.h" #include "swift/AST/ASTMangler.h" -#include "swift/AST/Decl.h" -#include "swift/AST/Module.h" #include "swift/Demangling/Demangle.h" #include "swift/RemoteInspection/ReflectionContext.h" #include "swift/RemoteAST/RemoteAST.h" @@ -519,23 +517,16 @@ void SwiftLanguageRuntimeImpl::SetupReflection() { objc_interop ? "with Objective-C interopability" : "Swift only"; auto &triple = exe_module->GetArchitecture().GetTriple(); - auto byte_size = m_process.GetAddressByteSize(); - if (byte_size == 8) { - LLDB_LOGF(log, "Initializing a 64-bit reflection context (%s) for \"%s\"", - triple.str().c_str(), objc_interop_msg); - m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext64( - this->GetMemoryReader(), objc_interop, GetSwiftMetadataCache()); - } else if (byte_size == 4) { - LLDB_LOGF(log, - "Initializing a 32-bit reflection context (%s) for \"%s\"", - triple.str().c_str(), objc_interop_msg); - m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext32( - this->GetMemoryReader(), objc_interop, GetSwiftMetadataCache()); - } else { - LLDB_LOGF(log, - "Could not initialize reflection context for \"%s\"", - triple.str().c_str()); - } + uint32_t ptr_size = m_process.GetAddressByteSize(); + LLDB_LOG(log, "Initializing a {0}-bit reflection context ({1}) for \"{2}\"", + ptr_size * 8, triple.str(), objc_interop_msg); + if (ptr_size == 4 || ptr_size == 8) + m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext( + ptr_size, this->GetMemoryReader(), objc_interop, + GetSwiftMetadataCache()); + if (!m_reflection_ctx) + LLDB_LOG(log, "Could not initialize reflection context for \"{0}\"", + triple.str()); // We set m_initialized_reflection_ctx to true here because // AddModuleToReflectionContext can potentially call into SetupReflection // again (which will early exit). This is safe to do since every other thread @@ -680,7 +671,7 @@ bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext( if (!obj_file_format) return false; - auto reflection_info_id = m_reflection_ctx->addImage( + auto reflection_info_id = m_reflection_ctx->AddImage( [&](swift::ReflectionSectionKind section_kind) -> std::pair, uint64_t> { auto section_name = obj_file_format->getSectionName(section_kind); @@ -845,7 +836,7 @@ SwiftLanguageRuntimeImpl::AddObjectFileToReflectionContext( return {}; }; - return m_reflection_ctx->addImage( + return m_reflection_ctx->AddImage( [&](swift::ReflectionSectionKind section_kind) -> std::pair, uint64_t> { auto pair = find_section_with_kind(segment, section_kind); @@ -904,7 +895,7 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext( auto size = obj_file->GetData(0, obj_file->GetByteSize(), extractor); const uint8_t *file_data = extractor.GetDataStart(); llvm::sys::MemoryBlock file_buffer((void *)file_data, size); - info_id = m_reflection_ctx->readELF( + info_id = m_reflection_ctx->ReadELF( swift::remote::RemoteAddress(load_ptr), llvm::Optional(file_buffer), likely_module_names); @@ -912,10 +903,10 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext( obj_file->GetPluginName().equals("mach-o")) { info_id = AddObjectFileToReflectionContext(module_sp, likely_module_names); if (!info_id) - info_id = m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr), + info_id = m_reflection_ctx->AddImage(swift::remote::RemoteAddress(load_ptr), likely_module_names); } else { - info_id = m_reflection_ctx->addImage(swift::remote::RemoteAddress(load_ptr), + info_id = m_reflection_ctx->AddImage(swift::remote::RemoteAddress(load_ptr), likely_module_names); } diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h index ddc3fa252fbe0..0d3ccaa9b04f2 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h @@ -19,7 +19,6 @@ #include "lldb/Core/PluginInterface.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/lldb-private.h" -#include "swift/Demangling/Demangle.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSet.h" diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 6be8b73729e0c..af1097d346caa 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -18,7 +18,6 @@ #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "Plugins/TypeSystem/Swift/SwiftDemangle.h" -#include "lldb/Symbol/Function.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ProcessStructReader.h" @@ -32,14 +31,9 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/ASTMangler.h" #include "swift/AST/ASTWalker.h" -#include "swift/AST/Decl.h" -#include "swift/AST/Types.h" #include "swift/Demangling/Demangle.h" #include "swift/RemoteInspection/ReflectionContext.h" #include "swift/RemoteInspection/TypeRefBuilder.h" -#include "swift/Remote/MemoryReader.h" -#include "swift/RemoteAST/RemoteAST.h" -#include "swift/Runtime/Metadata.h" #include "swift/Strings.h" #include @@ -232,200 +226,6 @@ lldb::addr_t SwiftLanguageRuntime::MaybeMaskNonTrivialReferencePointer( return addr & ~mask; } -namespace { - -/// An implementation of the generic ReflectionContextInterface that -/// is templatized on target pointer width and specialized to either -/// 32-bit or 64-bit pointers, with and without ObjC interoperability. -template -class TargetReflectionContext - : public SwiftLanguageRuntimeImpl::ReflectionContextInterface { - ReflectionContext m_reflection_ctx; - -public: - TargetReflectionContext( - std::shared_ptr reader, - SwiftMetadataCache *swift_metadata_cache) - : m_reflection_ctx(reader, swift_metadata_cache) {} - - llvm::Optional addImage( - llvm::function_ref, uint64_t>( - swift::ReflectionSectionKind)> - find_section, - llvm::SmallVector likely_module_names) override { - return m_reflection_ctx.addImage(find_section, likely_module_names); - } - - llvm::Optional - addImage(swift::remote::RemoteAddress image_start, - llvm::SmallVector likely_module_names) override { - return m_reflection_ctx.addImage(image_start, likely_module_names); - } - - llvm::Optional readELF( - swift::remote::RemoteAddress ImageStart, - llvm::Optional FileBuffer, - llvm::SmallVector likely_module_names = {}) override { - return m_reflection_ctx.readELF(ImageStart, FileBuffer, - likely_module_names); - } - - const swift::reflection::TypeInfo * - getTypeInfo(const swift::reflection::TypeRef *type_ref, - swift::remote::TypeInfoProvider *provider) override { - if (!type_ref) - return nullptr; - - Log *log(GetLog(LLDBLog::Types)); - if (log && log->GetVerbose()) { - std::stringstream ss; - type_ref->dump(ss); - LLDB_LOGF(log, "[TargetReflectionContext::getTypeInfo] Getting " - "type info for typeref:\n%s", - ss.str().c_str()); - } - - auto type_info = m_reflection_ctx.getTypeInfo(type_ref, provider); - if (log && !type_info) { - std::stringstream ss; - type_ref->dump(ss); - LLDB_LOGF(log, - "[TargetReflectionContext::getTypeInfo] Could not get " - "type info for typeref:\n%s", - ss.str().c_str()); - } - - if (type_info && log && log->GetVerbose()) { - std::stringstream ss; - type_info->dump(ss); - log->Printf("[TargetReflectionContext::getTypeInfo] Found " - "type info:\n%s", - ss.str().c_str()); - } - return type_info; - } - - swift::reflection::MemoryReader &getReader() override { - return m_reflection_ctx.getReader(); - } - - bool ForEachSuperClassType( - LLDBTypeInfoProvider *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); - if (!md_ptr) - return false; - - // Class object. - while (md_ptr && *md_ptr && --limit) { - // Reading metadata is potentially expensive since (in a remote - // debugging scenario it may even incur network traffic) so we - // just return closures that the caller can use to query details - // if they need them.' - auto metadata = *md_ptr; - if (fn({[=]() -> const swift::reflection::RecordTypeInfo * { - auto *ti = m_reflection_ctx.getMetadataTypeInfo(metadata, tip); - return llvm::dyn_cast_or_null< - swift::reflection::RecordTypeInfo>(ti); - }, - [=]() -> const swift::reflection::TypeRef * { - return m_reflection_ctx.readTypeFromMetadata(metadata); - }})) - return true; - - // Continue with the base class. - md_ptr = m_reflection_ctx.readSuperClassFromClassMetadata(metadata); - } - return false; - } - - llvm::Optional> - projectExistentialAndUnwrapClass( - swift::reflection::RemoteAddress existential_address, - const swift::reflection::TypeRef &existential_tr) override { - return m_reflection_ctx.projectExistentialAndUnwrapClass( - existential_address, existential_tr); - } - - const swift::reflection::TypeRef * - readTypeFromMetadata(lldb::addr_t metadata_address, - bool skip_artificial_subclasses) override { - return m_reflection_ctx.readTypeFromMetadata(metadata_address, - skip_artificial_subclasses); - } - - const swift::reflection::TypeRef * - readTypeFromInstance(lldb::addr_t instance_address, - bool skip_artificial_subclasses) override { - auto metadata_address = - m_reflection_ctx.readMetadataFromInstance(instance_address); - if (!metadata_address) { - LLDB_LOGF(GetLog(LLDBLog::Types), - "could not read heap metadata for object at %llu\n", - instance_address); - return nullptr; - } - - return m_reflection_ctx.readTypeFromMetadata(*metadata_address, - skip_artificial_subclasses); - } - - swift::reflection::TypeRefBuilder &getBuilder() override { - return m_reflection_ctx.getBuilder(); - } - - llvm::Optional isValueInlinedInExistentialContainer( - swift::remote::RemoteAddress existential_address) override { - return m_reflection_ctx.isValueInlinedInExistentialContainer( - existential_address); - } - - swift::remote::RemoteAbsolutePointer - stripSignedPointer(swift::remote::RemoteAbsolutePointer pointer) override { - return m_reflection_ctx.stripSignedPointer(pointer); - } -}; - -} // namespace - -std::unique_ptr -SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext32( - std::shared_ptr reader, bool ObjCInterop, - SwiftMetadataCache *swift_metadata_cache) { - using ReflectionContext32ObjCInterop = - TargetReflectionContext>>>>; - using ReflectionContext32NoObjCInterop = - TargetReflectionContext>>>>; - if (ObjCInterop) - return std::make_unique( - reader, swift_metadata_cache); - return std::make_unique( - reader, swift_metadata_cache); -} - -std::unique_ptr -SwiftLanguageRuntimeImpl::ReflectionContextInterface::CreateReflectionContext64( - std::shared_ptr reader, bool ObjCInterop, - SwiftMetadataCache *swift_metadata_cache) { - using ReflectionContext64ObjCInterop = - TargetReflectionContext>>>>; - using ReflectionContext64NoObjCInterop = - TargetReflectionContext>>>>; - if (ObjCInterop) - return std::make_unique( - reader, swift_metadata_cache); - return std::make_unique( - reader, swift_metadata_cache); -} - SwiftLanguageRuntimeImpl::ReflectionContextInterface:: ~ReflectionContextInterface() {} @@ -455,7 +255,7 @@ SwiftLanguageRuntimeImpl::GetMemoryReader() { m_process, [&](swift::remote::RemoteAbsolutePointer pointer) { ThreadSafeReflectionContext reflection_context = GetReflectionContext(); - return reflection_context->stripSignedPointer(pointer); + return reflection_context->StripSignedPointer(pointer); })); } @@ -472,148 +272,6 @@ void SwiftLanguageRuntimeImpl::PopLocalBuffer() { ((LLDBMemoryReader *)GetMemoryReader().get())->popLocalBuffer(); } -SwiftLanguageRuntime::MetadataPromise::MetadataPromise( - ValueObject &for_object, SwiftLanguageRuntimeImpl &runtime, - lldb::addr_t location) - : m_for_object_sp(for_object.GetSP()), m_swift_runtime(runtime), - m_metadata_location(location) {} - -CompilerType -SwiftLanguageRuntime::MetadataPromise::FulfillTypePromise(Status *error) { - if (error) - error->Clear(); - - Log *log(GetLog(LLDBLog::Types)); - - if (log) - log->Printf("[MetadataPromise] asked to fulfill type promise at location " - "0x%" PRIx64, - m_metadata_location); - - if (m_compiler_type.has_value()) - return m_compiler_type.value(); - - llvm::Optional maybe_swift_scratch_ctx = - m_for_object_sp->GetSwiftScratchContext(); - if (!maybe_swift_scratch_ctx) { - error->SetErrorString("couldn't get Swift scratch context"); - return CompilerType(); - } - auto scratch_ctx = maybe_swift_scratch_ctx->get(); - if (!scratch_ctx) { - error->SetErrorString("couldn't get Swift scratch context"); - return CompilerType(); - } - SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); - if (!swift_ast_ctx) { - error->SetErrorString("couldn't get Swift scratch context"); - return CompilerType(); - } - auto &remote_ast = m_swift_runtime.GetRemoteASTContext(*swift_ast_ctx); - swift::remoteAST::Result result = - remote_ast.getTypeForRemoteTypeMetadata( - swift::remote::RemoteAddress(m_metadata_location)); - - if (result) { - m_compiler_type = {swift_ast_ctx->weak_from_this(), - result.getValue().getPointer()}; - if (log) - log->Printf("[MetadataPromise] result is type %s", - m_compiler_type->GetTypeName().AsCString()); - return m_compiler_type.value(); - } else { - const auto &failure = result.getFailure(); - if (error) - error->SetErrorStringWithFormat("error in resolving type: %s", - failure.render().c_str()); - if (log) - log->Printf("[MetadataPromise] failure: %s", failure.render().c_str()); - return (m_compiler_type = CompilerType()).value(); - } -} - -SwiftLanguageRuntime::MetadataPromiseSP -SwiftLanguageRuntimeImpl::GetMetadataPromise(lldb::addr_t addr, - ValueObject &for_object) { - llvm::Optional maybe_swift_scratch_ctx = - for_object.GetSwiftScratchContext(); - if (!maybe_swift_scratch_ctx) - return nullptr; - auto scratch_ctx = maybe_swift_scratch_ctx->get(); - if (!scratch_ctx) - return nullptr; - SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); - if (!swift_ast_ctx) - return nullptr; - if (swift_ast_ctx->HasFatalErrors()) - return nullptr; - if (addr == 0 || addr == LLDB_INVALID_ADDRESS) - return nullptr; - - auto key = std::make_pair(swift_ast_ctx->GetASTContext(), addr); - auto iter = m_promises_map.find(key); - if (iter != m_promises_map.end()) - return iter->second; - - SwiftLanguageRuntime::MetadataPromiseSP promise_sp( - new SwiftLanguageRuntime::MetadataPromise(for_object, *this, addr)); - m_promises_map.insert({key, promise_sp}); - return promise_sp; -} - -swift::remoteAST::RemoteASTContext & -SwiftLanguageRuntimeImpl::GetRemoteASTContext(SwiftASTContext &swift_ast_ctx) { - // If we already have a remote AST context for this AST context, - // return it. - auto known = m_remote_ast_contexts.find(swift_ast_ctx.GetASTContext()); - if (known != m_remote_ast_contexts.end()) - return *known->second; - - // Initialize a new remote AST context. - (void)GetReflectionContext(); - auto remote_ast_up = std::make_unique( - *swift_ast_ctx.GetASTContext(), GetMemoryReader()); - auto &remote_ast = *remote_ast_up; - m_remote_ast_contexts.insert( - {swift_ast_ctx.GetASTContext(), std::move(remote_ast_up)}); - return remote_ast; -} - -void SwiftLanguageRuntimeImpl::ReleaseAssociatedRemoteASTContext( - swift::ASTContext *ctx) { - m_remote_ast_contexts.erase(ctx); -} - -namespace { -class ASTVerifier : public swift::ASTWalker { - bool hasMissingPatterns = false; - - PreWalkAction walkToDeclPre(swift::Decl *D) override { - if (auto *PBD = llvm::dyn_cast(D)) { - if (PBD->getPatternList().empty()) { - hasMissingPatterns = true; - return Action::SkipChildren(); - } - } - return Action::Continue(); - } - -public: - /// Detect (one form of) incomplete types. These may appear if - /// member variables have Clang-imported types that couldn't be - /// resolved. - static bool Verify(swift::Decl *D) { - if (!D) - return false; - - ASTVerifier verifier; - D->walk(verifier); - return !verifier.hasMissingPatterns; - } -}; - -} // namespace - class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { SwiftLanguageRuntimeImpl &m_runtime; TypeSystemSwift &m_typesystem; @@ -775,101 +433,6 @@ SwiftLanguageRuntimeImpl::emplaceClangTypeInfo( return &*it_b.first->second; } -llvm::Optional -SwiftLanguageRuntimeImpl::GetMemberVariableOffsetRemoteAST( - CompilerType instance_type, ValueObject *instance, - llvm::StringRef member_name) { - auto scratch_ctx = - instance_type.GetTypeSystem().dyn_cast_or_null(); - if (scratch_ctx == nullptr || scratch_ctx->HasFatalErrors()) - return {}; - - auto *remote_ast = &GetRemoteASTContext(*scratch_ctx); - // Check whether we've already cached this offset. - swift::TypeBase *swift_type = - GetCanonicalSwiftType(instance_type).getPointer(); - if (swift_type == nullptr) - return {}; - - // Perform the cache lookup. - MemberID key{swift_type, ConstString(member_name).GetCString()}; - auto it = m_member_offsets.find(key); - if (it != m_member_offsets.end()) - return it->second; - - // Dig out metadata describing the type, if it's easy to find. - // FIXME: the Remote AST library should make this easier. - swift::remote::RemoteAddress optmeta(nullptr); - const swift::TypeKind type_kind = swift_type->getKind(); - switch (type_kind) { - case swift::TypeKind::Class: - case swift::TypeKind::BoundGenericClass: { - LLDB_LOGF(GetLog(LLDBLog::Types), - "[MemberVariableOffsetResolver] type is a class - trying to " - "get metadata for valueobject %s", - (instance ? instance->GetName().AsCString() : "")); - if (instance) { - lldb::addr_t pointer = instance->GetPointerValue(); - if (!pointer || pointer == LLDB_INVALID_ADDRESS) - break; - swift::remote::RemoteAddress address(pointer); - if (auto metadata = remote_ast->getHeapMetadataForObject(address)) - optmeta = metadata.getValue(); - } - LLDB_LOGF(GetLog(LLDBLog::Types), - "[MemberVariableOffsetResolver] optmeta = 0x%" PRIx64, - optmeta.getAddressData()); - break; - } - - default: - // Bind generic parameters if necessary. - if (instance && swift_type->hasTypeParameter()) - if (auto *frame = instance->GetExecutionContextRef().GetFrameSP().get()) - if (auto bound = BindGenericTypeParameters(*frame, instance_type)) { - LLDB_LOGF( - GetLog(LLDBLog::Types), - "[MemberVariableOffsetResolver] resolved non-class type = %s", - bound.GetTypeName().AsCString()); - - swift_type = GetCanonicalSwiftType(bound).getPointer(); - MemberID key{swift_type, ConstString(member_name).GetCString()}; - auto it = m_member_offsets.find(key); - if (it != m_member_offsets.end()) - return it->second; - } - } - - // Try to determine whether it is safe to use RemoteAST. RemoteAST - // is faster than RemoteMirrors, but can't do dynamic types (checked - // inside RemoteAST) or incomplete types (checked here). - bool safe_to_use_remote_ast = true; - if (swift::Decl *type_decl = swift_type->getNominalOrBoundGenericNominal()) - safe_to_use_remote_ast &= ASTVerifier::Verify(type_decl); - - // Use RemoteAST to determine the member offset. - if (safe_to_use_remote_ast) { - swift::remoteAST::Result result = - remote_ast->getOffsetOfMember(swift_type, optmeta, member_name); - if (result) { - LLDB_LOGF(GetLog(LLDBLog::Types), - "[MemberVariableOffsetResolver] offset discovered = %" PRIu64, - (uint64_t)result.getValue()); - - // Cache this result. - MemberID key{swift_type, ConstString(member_name).GetCString()}; - m_member_offsets.insert({key, result.getValue()}); - return result.getValue(); - } - - const auto &failure = result.getFailure(); - LLDB_LOGF(GetLog(LLDBLog::Types), - "[MemberVariableOffsetResolver] failure: %s", - failure.render().c_str()); - } - return {}; -} - llvm::Optional SwiftLanguageRuntimeImpl::GetMemberVariableOffsetRemoteMirrors( CompilerType instance_type, ValueObject *instance, llvm::StringRef member_name, Status *error) { @@ -1106,7 +669,7 @@ SwiftLanguageRuntimeImpl::GetNumChildren(CompilerType type, return {}; ThreadSafeReflectionContext reflection_ctx = GetReflectionContext(); - auto &builder = reflection_ctx->getBuilder(); + auto &builder = reflection_ctx->GetBuilder(); auto tc = swift::reflection::TypeConverter(builder); LLDBTypeInfoProvider tip(*this, *ts); auto *cti = tc.getClassInstanceTypeInfo(tr, 0, &tip); @@ -1180,7 +743,7 @@ SwiftLanguageRuntimeImpl::GetNumFields(CompilerType type, return referent.GetNumFields(exe_ctx); return 0; case ReferenceKind::Strong: - TypeConverter tc(GetReflectionContext()->getBuilder()); + TypeConverter tc(GetReflectionContext()->GetBuilder()); LLDBTypeInfoProvider tip(*this, *ts); auto *cti = tc.getClassInstanceTypeInfo(tr, 0, &tip); if (auto *rti = llvm::dyn_cast_or_null(cti)) { @@ -1313,7 +876,7 @@ SwiftLanguageRuntimeImpl::GetIndexOfChildMemberWithName( child_indexes); case ReferenceKind::Strong: { ThreadSafeReflectionContext reflection_ctx = GetReflectionContext(); - auto &builder = reflection_ctx->getBuilder(); + auto &builder = reflection_ctx->GetBuilder(); TypeConverter tc(builder); LLDBTypeInfoProvider tip(*this, *ts); // `current_tr` iterates the class hierarchy, from the current class, each @@ -1804,7 +1367,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Pack( return {}; } - auto *type_ref = reflection_ctx->readTypeFromMetadata(md); + auto *type_ref = reflection_ctx->ReadTypeFromMetadata(md); if (!type_ref) { LLDB_LOGF(log, "cannot decode pack_expansion type: failed to decode type " @@ -1831,7 +1394,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Pack( // Build a TypeRef from the demangle tree. auto typeref_or_err = - decodeMangledType(reflection_ctx->getBuilder(), pack_element); + decodeMangledType(reflection_ctx->GetBuilder(), pack_element); if (typeref_or_err.isError()) { LLDB_LOGF(log, "Couldn't get TypeRef for %s", pack_type.GetMangledTypeName().GetCString()); @@ -1841,7 +1404,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Pack( // Apply the substitutions. auto bound_typeref = - typeref->subst(reflection_ctx->getBuilder(), substitutions); + typeref->subst(reflection_ctx->GetBuilder(), substitutions); swift::Demangle::NodePointer node = bound_typeref->getDemangling(dem); CompilerType type = ts->RemangleAsType(dem, node); @@ -1915,8 +1478,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Pack( } #ifndef NDEBUG -/// Assert helper to determine if the scratch SwiftASTContext is locked. -static bool IsScratchContextLocked(Target &target) { +bool SwiftLanguageRuntimeImpl::IsScratchContextLocked(Target &target) { if (target.GetSwiftScratchContextLock().try_lock()) { target.GetSwiftScratchContextLock().unlock(); return false; @@ -1924,8 +1486,7 @@ static bool IsScratchContextLocked(Target &target) { return true; } -/// Assert helper to determine if the scratch SwiftASTContext is locked. -static bool IsScratchContextLocked(TargetSP target) { +bool SwiftLanguageRuntimeImpl::IsScratchContextLocked(TargetSP target) { return target ? IsScratchContextLocked(*target) : true; } #endif @@ -1995,7 +1556,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class( } Log *log(GetLog(LLDBLog::Types)); ThreadSafeReflectionContext reflection_ctx = GetReflectionContext(); - const auto *typeref = reflection_ctx->readTypeFromInstance(instance_ptr); + const auto *typeref = reflection_ctx->ReadTypeFromInstance(instance_ptr); if (!typeref) { LLDB_LOGF(log, "could not read typeref for type: %s (instance_ptr = 0x%" PRIx64 @@ -2011,45 +1572,15 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class( class_type_or_name.SetCompilerType(dynamic_type); #ifndef NDEBUG - // Dynamic type resolution in RemoteAST might pull in other Swift modules, so - // use the scratch context where such operations are legal and safe. if (ModuleList::GetGlobalModuleListProperties() .GetSwiftValidateTypeSystem()) { - llvm::Optional maybe_scratch_ctx = - in_value.GetSwiftScratchContext(); - if (!maybe_scratch_ctx) - return false; - auto scratch_ctx = maybe_scratch_ctx->get(); - if (!scratch_ctx) - return false; - SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); - if (!swift_ast_ctx) - return true; - - auto &remote_ast = GetRemoteASTContext(*swift_ast_ctx); - auto remote_ast_metadata_address = remote_ast.getHeapMetadataForObject( - swift::remote::RemoteAddress(instance_ptr)); - if (remote_ast_metadata_address) { - auto instance_type = remote_ast.getTypeForRemoteTypeMetadata( - remote_ast_metadata_address.getValue(), - /*skipArtificial=*/true); - if (instance_type) { - auto ref_type = ToCompilerType(instance_type.getValue()); - ConstString a = ref_type.GetMangledTypeName(); - ConstString b = - class_type_or_name.GetCompilerType().GetMangledTypeName(); - if (a != b) - llvm::dbgs() << "RemoteAST and runtime diverge " << a << " != " << b - << "\n"; - } else { - if (log) { - log->Printf("could not get type metadata: %s\n", - instance_type.getFailure().render().c_str()); - } - } - } + ConstString a = class_type_or_name.GetCompilerType().GetMangledTypeName(); + ConstString b = SwiftLanguageRuntimeImpl::GetDynamicTypeName_ClassRemoteAST( + in_value, instance_ptr); + if (b && a != b) + llvm::dbgs() << "RemoteAST and runtime diverge " << a << " != " << b + << "\n"; } - #endif return true; } @@ -2123,48 +1654,6 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Protocol( ValueObject &in_value, CompilerType protocol_type, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address) { - auto remote_ast_impl = [&](bool use_local_buffer, - lldb::addr_t existential_address) - -> llvm::Optional> { - // Dynamic type resolution in RemoteAST might pull in other Swift modules, - // so - // use the scratch context where such operations are legal and safe. - llvm::Optional maybe_scratch_ctx = - in_value.GetSwiftScratchContext(); - if (!maybe_scratch_ctx) - return {}; - auto scratch_ctx = maybe_scratch_ctx->get(); - if (!scratch_ctx) - return {}; - SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); - if (!swift_ast_ctx) - return {}; - - swift::remote::RemoteAddress remote_existential(existential_address); - auto &remote_ast = GetRemoteASTContext(*swift_ast_ctx); - auto swift_type = GetSwiftType(protocol_type); - if (!swift_type) - return {}; - if (use_local_buffer) - PushLocalBuffer(existential_address, - in_value.GetByteSize().value_or(0)); - - auto result = remote_ast.getDynamicTypeAndAddressForExistential( - remote_existential, swift_type); - if (use_local_buffer) - PopLocalBuffer(); - - if (!result.isSuccess()) - return {}; - - auto type_and_address = result.getValue(); - - CompilerType type = ToCompilerType(type_and_address.InstanceType); - Address address; - address.SetRawAddress(type_and_address.PayloadAddress.getAddressData()); - return {{type, address}}; - }; - Log *log(GetLog(LLDBLog::Types)); auto tss = protocol_type.GetTypeSystem().dyn_cast_or_null(); @@ -2218,7 +1707,7 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Protocol( swift::remote::RemoteAddress remote_existential(existential_address); ThreadSafeReflectionContext reflection_ctx = GetReflectionContext(); - auto pair = reflection_ctx->projectExistentialAndUnwrapClass( + auto pair = reflection_ctx->ProjectExistentialAndUnwrapClass( remote_existential, *protocol_typeref); if (use_local_buffer) PopLocalBuffer(); @@ -2241,8 +1730,8 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Protocol( #ifndef NDEBUG if (ModuleList::GetGlobalModuleListProperties() .GetSwiftValidateTypeSystem()) { - auto reference_pair = - remote_ast_impl(use_local_buffer, existential_address); + auto reference_pair = GetDynamicTypeAndAddress_ProtocolRemoteAST( + in_value, protocol_type, use_local_buffer, existential_address); assert(pair.has_value() >= reference_pair.has_value() && "RemoteAST and runtime diverge"); @@ -2284,35 +1773,6 @@ SwiftLanguageRuntimeImpl::GetTypeMetadataForTypeNameAndFrame( return metadata_location; } - SwiftLanguageRuntime::MetadataPromiseSP -SwiftLanguageRuntimeImpl::GetPromiseForTypeNameAndFrame(const char *type_name, - StackFrame *frame) { - if (!frame || !type_name || !type_name[0]) - return nullptr; - - StreamString type_metadata_ptr_var_name; - type_metadata_ptr_var_name.Printf("$%s", type_name); - VariableList *var_list = frame->GetVariableList(false, nullptr); - if (!var_list) - return nullptr; - - VariableSP var_sp(var_list->FindVariable( - ConstString(type_metadata_ptr_var_name.GetData()))); - if (!var_sp) - return nullptr; - - ValueObjectSP metadata_ptr_var_sp( - frame->GetValueObjectForFrameVariable(var_sp, lldb::eNoDynamicValues)); - if (!metadata_ptr_var_sp || - metadata_ptr_var_sp->UpdateValueIfNeeded() == false) - return nullptr; - - lldb::addr_t metadata_location(metadata_ptr_var_sp->GetValueAsUnsigned(0)); - if (metadata_location == 0 || metadata_location == LLDB_INVALID_ADDRESS) - return nullptr; - return GetMetadataPromise(metadata_location, *metadata_ptr_var_sp); -} - void SwiftLanguageRuntime::ForEachGenericParameter( swift::Demangle::NodePointer node, std::function callback) { @@ -2359,7 +1819,7 @@ CompilerType SwiftLanguageRuntimeImpl::BindGenericTypeParameters( NodePointer unbound_node = dem.demangleSymbol(unbound_type.GetMangledTypeName().GetStringRef()); auto type_ref_or_err = - decodeMangledType(reflection_ctx->getBuilder(), unbound_node); + decodeMangledType(reflection_ctx->GetBuilder(), unbound_node); if (type_ref_or_err.isError()) { LLDB_LOG(GetLog(LLDBLog::Expressions | LLDBLog::Types), "Couldn't get TypeRef of unbound type."); @@ -2385,7 +1845,7 @@ CompilerType SwiftLanguageRuntimeImpl::BindGenericTypeParameters( NodePointer child_node = dem.demangleSymbol(type.GetMangledTypeName().GetStringRef()); auto type_ref_or_err = - decodeMangledType(reflection_ctx->getBuilder(), child_node); + decodeMangledType(reflection_ctx->GetBuilder(), child_node); if (type_ref_or_err.isError()) { LLDB_LOG(GetLog(LLDBLog::Expressions | LLDBLog::Types), "Couldn't get TypeRef when binding generic type parameters."); @@ -2403,7 +1863,7 @@ CompilerType SwiftLanguageRuntimeImpl::BindGenericTypeParameters( // Apply the substitutions. const swift::reflection::TypeRef *bound_type_ref = - type_ref->subst(reflection_ctx->getBuilder(), substitutions); + type_ref->subst(reflection_ctx->GetBuilder(), substitutions); NodePointer node = bound_type_ref->getDemangling(dem); return ts->GetTypeSystemSwiftTypeRef().RemangleAsType(dem, node); } @@ -2441,7 +1901,7 @@ SwiftLanguageRuntimeImpl::BindGenericTypeParameters(StackFrame &stack_frame, if (!metadata_location) return; const swift::reflection::TypeRef *type_ref = - reflection_ctx->readTypeFromMetadata(*metadata_location); + reflection_ctx->ReadTypeFromMetadata(*metadata_location); if (!type_ref) return; substitutions.insert({{depth, index}, type_ref}); @@ -2459,7 +1919,7 @@ SwiftLanguageRuntimeImpl::BindGenericTypeParameters(StackFrame &stack_frame, // Build a TypeRef from the demangle tree. auto type_ref_or_err = - decodeMangledType(reflection_ctx->getBuilder(), canonical); + decodeMangledType(reflection_ctx->GetBuilder(), canonical); if (type_ref_or_err.isError()) { LLDB_LOG(GetLog(LLDBLog::Expressions | LLDBLog::Types), "Couldn't get TypeRef"); @@ -2469,7 +1929,7 @@ SwiftLanguageRuntimeImpl::BindGenericTypeParameters(StackFrame &stack_frame, // Apply the substitutions. const swift::reflection::TypeRef *bound_type_ref = - type_ref->subst(reflection_ctx->getBuilder(), substitutions); + type_ref->subst(reflection_ctx->GetBuilder(), substitutions); NodePointer node = bound_type_ref->getDemangling(dem); // Import the type into the scratch context. Subsequent conversions @@ -2501,174 +1961,13 @@ SwiftLanguageRuntimeImpl::BindGenericTypeParameters(StackFrame &stack_frame, CompilerType SwiftLanguageRuntimeImpl::BindGenericTypeParameters(StackFrame &stack_frame, CompilerType base_type) { - LLDB_SCOPED_TIMER(); - // If this is a TypeRef type, bind that. auto sc = stack_frame.GetSymbolContext(lldb::eSymbolContextEverything); if (auto ts = base_type.GetTypeSystem().dyn_cast_or_null()) return BindGenericTypeParameters(stack_frame, *ts, base_type.GetMangledTypeName()); - - Status error; - auto &target = m_process.GetTarget(); - assert(IsScratchContextLocked(target) && - "Swift scratch context not locked ahead of archetype binding"); - - // A failing Clang import in a module context permanently damages - // that module context. Binding archetypes can trigger an import of - // another module, so switch to a scratch context where such an - // operation is safe. - llvm::Optional maybe_scratch_ctx = - target.GetSwiftScratchContext(error, stack_frame); - if (!maybe_scratch_ctx) - return base_type; - auto scratch_ctx = maybe_scratch_ctx->get(); - if (!scratch_ctx) - return base_type; - SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); - if (!swift_ast_ctx) - return base_type; - base_type = swift_ast_ctx->ImportType(base_type, error); - - if (base_type.GetTypeInfo() & lldb::eTypeIsSwift) { - swift::Type target_swift_type(GetSwiftType(base_type)); - if (target_swift_type->hasArchetype()) - target_swift_type = target_swift_type->mapTypeOutOfContext().getPointer(); - - // FIXME: This is wrong, but it doesn't actually matter right now since - // all conformances are always visible - auto *module_decl = swift_ast_ctx->GetASTContext()->getStdlibModule(); - - // Replace opaque types with their underlying types when possible. - swift::Mangle::ASTMangler mangler(true); - - // Rewrite all dynamic self types to their static self types. - target_swift_type = - target_swift_type.transform([](swift::Type type) -> swift::Type { - if (auto *dynamic_self = - llvm::dyn_cast(type.getPointer())) - return dynamic_self->getSelfType(); - return type; - }); - - // Thicken generic metatypes. Once substituted, they should always - // be thick. TypeRef::subst() does the same transformation. - target_swift_type = - target_swift_type.transform([](swift::Type type) -> swift::Type { - using namespace swift; - const auto thin = MetatypeRepresentation::Thin; - const auto thick = MetatypeRepresentation::Thick; - if (auto *metatype = dyn_cast(type.getPointer())) - if (metatype->hasRepresentation() && - metatype->getRepresentation() == thin && - metatype->getInstanceType()->hasTypeParameter()) - return MetatypeType::get(metatype->getInstanceType(), thick); - return type; - }); - - while (target_swift_type->hasOpaqueArchetype()) { - auto old_type = target_swift_type; - target_swift_type = target_swift_type.subst( - [&](swift::SubstitutableType *type) -> swift::Type { - auto opaque_type = - llvm::dyn_cast(type); - if (!opaque_type || - !opaque_type->getInterfaceType() - ->is()) - return type; - - // Try to find the symbol for the opaque type descriptor in the - // process. - auto mangled_name = ConstString( - mangler.mangleOpaqueTypeDescriptor(opaque_type->getDecl())); - - SymbolContextList found; - target.GetImages().FindSymbolsWithNameAndType( - mangled_name, eSymbolTypeData, found); - - if (found.GetSize() == 0) - return type; - - swift::Type result_type; - - for (unsigned i = 0, e = found.GetSize(); i < e; ++i) { - SymbolContext found_sc; - if (!found.GetContextAtIndex(i, found_sc)) - continue; - - // See if the symbol has an address. - if (!found_sc.symbol) - continue; - - auto addr = found_sc.symbol->GetAddress().GetLoadAddress(&target); - if (!addr || addr == LLDB_INVALID_ADDRESS) - continue; - - // Ask RemoteAST to get the underlying type out of the descriptor. - auto &remote_ast = GetRemoteASTContext(*swift_ast_ctx); - auto genericParam = opaque_type->getInterfaceType() - ->getAs(); - auto underlying_type_result = - remote_ast.getUnderlyingTypeForOpaqueType( - swift::remote::RemoteAddress(addr), - opaque_type->getSubstitutions(), - genericParam->getIndex()); - - if (!underlying_type_result) - continue; - - // If we haven't yet gotten an underlying type, use this as our - // possible result. - if (!result_type) { - result_type = underlying_type_result.getValue(); - } - // If we have two possibilities, they should match. - else if (!result_type->isEqual( - underlying_type_result.getValue())) { - return type; - } - } - - if (!result_type) - return type; - - return result_type; - }, - swift::LookUpConformanceInModule(module_decl), - swift::SubstFlags::DesugarMemberTypes | - swift::SubstFlags::SubstituteOpaqueArchetypes); - - // Stop if we've reached a fixpoint where we can't further resolve opaque - // types. - if (old_type->isEqual(target_swift_type)) - break; - } - - target_swift_type = target_swift_type.subst( - [this, &stack_frame, - &swift_ast_ctx](swift::SubstitutableType *type) -> swift::Type { - StreamString type_name; - if (!SwiftLanguageRuntime::GetAbstractTypeName(type_name, type)) - return type; - CompilerType concrete_type = this->GetConcreteType( - &stack_frame, ConstString(type_name.GetString())); - Status import_error; - CompilerType target_concrete_type = - swift_ast_ctx->ImportType(concrete_type, import_error); - - if (target_concrete_type.IsValid()) - return swift::Type(GetSwiftType(target_concrete_type)); - - return type; - }, - swift::LookUpConformanceInModule(module_decl), - swift::SubstFlags::DesugarMemberTypes); - assert(target_swift_type); - - return ToCompilerType({target_swift_type.getPointer()}); - } - return base_type; + return BindGenericTypeParametersRemoteAST(stack_frame, base_type); } bool SwiftLanguageRuntime::GetAbstractTypeName(StreamString &name, @@ -2867,7 +2166,7 @@ SwiftLanguageRuntimeImpl::GetValueType(ValueObject &in_value, swift::remote::RemoteAddress remote_existential(existential_address); ThreadSafeReflectionContext reflection_ctx = GetReflectionContext(); llvm::Optional is_inlined = - reflection_ctx->isValueInlinedInExistentialContainer( + reflection_ctx->IsValueInlinedInExistentialContainer( remote_existential); if (use_local_buffer) @@ -3349,7 +2648,7 @@ SwiftLanguageRuntimeImpl::GetTypeRef(CompilerType type, return nullptr; auto type_ref_or_err = - swift::Demangle::decodeMangledType(reflection_ctx->getBuilder(), node); + swift::Demangle::decodeMangledType(reflection_ctx->GetBuilder(), node); if (type_ref_or_err.isError()) { LLDB_LOGF(log, "[SwiftLanguageRuntimeImpl::GetTypeRef] Could not find typeref " @@ -3424,7 +2723,7 @@ SwiftLanguageRuntimeImpl::GetSwiftRuntimeTypeInfo( return nullptr; LLDBTypeInfoProvider provider(*this, *ts); - return reflection_ctx->getTypeInfo(type_ref, &provider); + return reflection_ctx->GetTypeInfo(type_ref, &provider); } bool SwiftLanguageRuntimeImpl::IsStoredInlineInBuffer(CompilerType type) { diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h index 87c292d13adae..75f589359f729 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h @@ -16,7 +16,6 @@ #include "LLDBMemoryReader.h" #include "SwiftLanguageRuntime.h" #include "SwiftMetadataCache.h" -#include "swift/RemoteInspection/TypeLowering.h" #include "llvm/Support/Memory.h" namespace swift { @@ -36,6 +35,10 @@ class SwiftLanguageRuntimeImpl { public: SwiftLanguageRuntimeImpl(Process &process); + SwiftLanguageRuntimeImpl(const SwiftLanguageRuntimeImpl &) = delete; + const SwiftLanguageRuntimeImpl & + operator=(const SwiftLanguageRuntimeImpl &) = delete; + static lldb::BreakpointPreconditionSP GetBreakpointExceptionPrecondition(lldb::LanguageType language, bool throw_bp); @@ -154,6 +157,10 @@ class SwiftLanguageRuntimeImpl { TypeSystemSwiftTypeRef &ts, ConstString mangled_name); + /// Like \p BindGenericTypeParameters but for RemoteAST. + CompilerType BindGenericTypeParametersRemoteAST(StackFrame &stack_frame, + CompilerType base_type); + /// \see SwiftLanguageRuntime::BindGenericTypeParameters(). CompilerType BindGenericTypeParameters(StackFrame &stack_frame, CompilerType base_type); @@ -205,55 +212,50 @@ class SwiftLanguageRuntimeImpl { /// a specific pointer width. class ReflectionContextInterface { public: - /// Return a 32-bit reflection context. - static std::unique_ptr - CreateReflectionContext32( - std::shared_ptr reader, bool ObjCInterop, - SwiftMetadataCache *swift_metadata_cache); - - /// Return a 64-bit reflection context. + /// Return a reflection context. static std::unique_ptr - CreateReflectionContext64( - std::shared_ptr reader, bool ObjCInterop, + CreateReflectionContext(uint8_t pointer_size, + std::shared_ptr reader, bool objc_interop, SwiftMetadataCache *swift_metadata_cache); virtual ~ReflectionContextInterface(); - virtual llvm::Optional addImage( + virtual llvm::Optional AddImage( llvm::function_ref, uint64_t>( swift::ReflectionSectionKind)> find_section, llvm::SmallVector likely_module_names = {}) = 0; - virtual llvm::Optional addImage( + virtual llvm::Optional AddImage( swift::remote::RemoteAddress image_start, llvm::SmallVector likely_module_names = {}) = 0; virtual llvm::Optional - readELF(swift::remote::RemoteAddress ImageStart, + ReadELF(swift::remote::RemoteAddress ImageStart, llvm::Optional FileBuffer, llvm::SmallVector likely_module_names = {}) = 0; virtual const swift::reflection::TypeInfo * - getTypeInfo(const swift::reflection::TypeRef *type_ref, + GetTypeInfo(const swift::reflection::TypeRef *type_ref, swift::remote::TypeInfoProvider *provider) = 0; - virtual swift::remote::MemoryReader &getReader() = 0; + virtual swift::remote::MemoryReader &GetReader() = 0; virtual bool - ForEachSuperClassType(LLDBTypeInfoProvider *tip, lldb::addr_t pointer, + ForEachSuperClassType(swift::remote::TypeInfoProvider *tip, + lldb::addr_t pointer, std::function fn) = 0; virtual llvm::Optional> - projectExistentialAndUnwrapClass( + ProjectExistentialAndUnwrapClass( swift::remote::RemoteAddress existential_addess, const swift::reflection::TypeRef &existential_tr) = 0; virtual const swift::reflection::TypeRef * - readTypeFromMetadata(lldb::addr_t metadata_address, + ReadTypeFromMetadata(lldb::addr_t metadata_address, bool skip_artificial_subclasses = false) = 0; virtual const swift::reflection::TypeRef * - readTypeFromInstance(lldb::addr_t instance_address, + ReadTypeFromInstance(lldb::addr_t instance_address, bool skip_artificial_subclasses = false) = 0; - virtual swift::reflection::TypeRefBuilder &getBuilder() = 0; - virtual llvm::Optional isValueInlinedInExistentialContainer( + virtual swift::reflection::TypeRefBuilder &GetBuilder() = 0; + virtual llvm::Optional IsValueInlinedInExistentialContainer( swift::remote::RemoteAddress existential_address) = 0; virtual swift::remote::RemoteAbsolutePointer - stripSignedPointer(swift::remote::RemoteAbsolutePointer pointer) = 0; + StripSignedPointer(swift::remote::RemoteAbsolutePointer pointer) = 0; }; /// A wrapper around TargetReflectionContext, which holds a lock to ensure @@ -315,13 +317,22 @@ class SwiftLanguageRuntimeImpl { TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type); - +#ifndef NDEBUG + ConstString GetDynamicTypeName_ClassRemoteAST(ValueObject &in_value, + lldb::addr_t instance_ptr); +#endif bool GetDynamicTypeAndAddress_Protocol(ValueObject &in_value, CompilerType protocol_type, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address); - +#ifndef NDEBUG + llvm::Optional> + GetDynamicTypeAndAddress_ProtocolRemoteAST(ValueObject &in_value, + CompilerType protocol_type, + bool use_local_buffer, + lldb::addr_t existential_address); +#endif bool GetDynamicTypeAndAddress_Value(ValueObject &in_value, CompilerType &bound_type, lldb::DynamicValueType use_dynamic, @@ -479,9 +490,12 @@ class SwiftLanguageRuntimeImpl { /// Swift native NSError isa. llvm::Optional m_SwiftNativeNSErrorISA; - SwiftLanguageRuntimeImpl(const SwiftLanguageRuntimeImpl &) = delete; - const SwiftLanguageRuntimeImpl & - operator=(const SwiftLanguageRuntimeImpl &) = delete; +#ifndef NDEBUG + /// Assert helper to determine if the scratch SwiftASTContext is locked. + static bool IsScratchContextLocked(Target &target); + /// Assert helper to determine if the scratch SwiftASTContext is locked. + static bool IsScratchContextLocked(lldb::TargetSP target); +#endif }; } // namespace lldb_private diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp new file mode 100644 index 0000000000000..f761114cc3704 --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp @@ -0,0 +1,544 @@ +//===-- SwiftLanguageRuntimeRemoteAST.cpp --------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include "SwiftLanguageRuntimeImpl.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Timer.h" +#include "swift/AST/ASTContext.h" +#include "swift/AST/ASTMangler.h" +#include "swift/AST/ASTWalker.h" +#include "swift/RemoteAST/RemoteAST.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { +class ASTVerifier : public swift::ASTWalker { + bool hasMissingPatterns = false; + + PreWalkAction walkToDeclPre(swift::Decl *D) override { + if (auto *PBD = llvm::dyn_cast(D)) { + if (PBD->getPatternList().empty()) { + hasMissingPatterns = true; + return Action::SkipChildren(); + } + } + return Action::Continue(); + } + +public: + /// Detect (one form of) incomplete types. These may appear if + /// member variables have Clang-imported types that couldn't be + /// resolved. + static bool Verify(swift::Decl *D) { + if (!D) + return false; + + ASTVerifier verifier; + D->walk(verifier); + return !verifier.hasMissingPatterns; + } +}; + +} // namespace + +namespace lldb_private { + +swift::remoteAST::RemoteASTContext & +SwiftLanguageRuntimeImpl::GetRemoteASTContext(SwiftASTContext &swift_ast_ctx) { + // If we already have a remote AST context for this AST context, + // return it. + auto known = m_remote_ast_contexts.find(swift_ast_ctx.GetASTContext()); + if (known != m_remote_ast_contexts.end()) + return *known->second; + + // Initialize a new remote AST context. + (void)GetReflectionContext(); + auto remote_ast_up = std::make_unique( + *swift_ast_ctx.GetASTContext(), GetMemoryReader()); + auto &remote_ast = *remote_ast_up; + m_remote_ast_contexts.insert( + {swift_ast_ctx.GetASTContext(), std::move(remote_ast_up)}); + return remote_ast; +} + +void SwiftLanguageRuntimeImpl::ReleaseAssociatedRemoteASTContext( + swift::ASTContext *ctx) { + m_remote_ast_contexts.erase(ctx); +} + +llvm::Optional +SwiftLanguageRuntimeImpl::GetMemberVariableOffsetRemoteAST( + CompilerType instance_type, ValueObject *instance, + llvm::StringRef member_name) { + auto scratch_ctx = + instance_type.GetTypeSystem().dyn_cast_or_null(); + if (scratch_ctx == nullptr || scratch_ctx->HasFatalErrors()) + return {}; + + auto *remote_ast = &GetRemoteASTContext(*scratch_ctx); + // Check whether we've already cached this offset. + swift::TypeBase *swift_type = + GetCanonicalSwiftType(instance_type).getPointer(); + if (swift_type == nullptr) + return {}; + + // Perform the cache lookup. + MemberID key{swift_type, ConstString(member_name).GetCString()}; + auto it = m_member_offsets.find(key); + if (it != m_member_offsets.end()) + return it->second; + + // Dig out metadata describing the type, if it's easy to find. + // FIXME: the Remote AST library should make this easier. + swift::remote::RemoteAddress optmeta(nullptr); + const swift::TypeKind type_kind = swift_type->getKind(); + switch (type_kind) { + case swift::TypeKind::Class: + case swift::TypeKind::BoundGenericClass: { + LLDB_LOGF(GetLog(LLDBLog::Types), + "[MemberVariableOffsetResolver] type is a class - trying to " + "get metadata for valueobject %s", + (instance ? instance->GetName().AsCString() : "")); + if (instance) { + lldb::addr_t pointer = instance->GetPointerValue(); + if (!pointer || pointer == LLDB_INVALID_ADDRESS) + break; + swift::remote::RemoteAddress address(pointer); + if (auto metadata = remote_ast->getHeapMetadataForObject(address)) + optmeta = metadata.getValue(); + } + LLDB_LOGF(GetLog(LLDBLog::Types), + "[MemberVariableOffsetResolver] optmeta = 0x%" PRIx64, + optmeta.getAddressData()); + break; + } + + default: + // Bind generic parameters if necessary. + if (instance && swift_type->hasTypeParameter()) + if (auto *frame = instance->GetExecutionContextRef().GetFrameSP().get()) + if (auto bound = BindGenericTypeParameters(*frame, instance_type)) { + LLDB_LOGF( + GetLog(LLDBLog::Types), + "[MemberVariableOffsetResolver] resolved non-class type = %s", + bound.GetTypeName().AsCString()); + + swift_type = GetCanonicalSwiftType(bound).getPointer(); + MemberID key{swift_type, ConstString(member_name).GetCString()}; + auto it = m_member_offsets.find(key); + if (it != m_member_offsets.end()) + return it->second; + } + } + + // Try to determine whether it is safe to use RemoteAST. RemoteAST + // is faster than RemoteMirrors, but can't do dynamic types (checked + // inside RemoteAST) or incomplete types (checked here). + bool safe_to_use_remote_ast = true; + if (swift::Decl *type_decl = swift_type->getNominalOrBoundGenericNominal()) + safe_to_use_remote_ast &= ASTVerifier::Verify(type_decl); + + // Use RemoteAST to determine the member offset. + if (safe_to_use_remote_ast) { + swift::remoteAST::Result result = + remote_ast->getOffsetOfMember(swift_type, optmeta, member_name); + if (result) { + LLDB_LOGF(GetLog(LLDBLog::Types), + "[MemberVariableOffsetResolver] offset discovered = %" PRIu64, + (uint64_t)result.getValue()); + + // Cache this result. + MemberID key{swift_type, ConstString(member_name).GetCString()}; + m_member_offsets.insert({key, result.getValue()}); + return result.getValue(); + } + + const auto &failure = result.getFailure(); + LLDB_LOGF(GetLog(LLDBLog::Types), + "[MemberVariableOffsetResolver] failure: %s", + failure.render().c_str()); + } + return {}; +} + +#ifndef NDEBUG +ConstString SwiftLanguageRuntimeImpl::GetDynamicTypeName_ClassRemoteAST( + ValueObject &in_value, lldb::addr_t instance_ptr) { + // Dynamic type resolution in RemoteAST might pull in other Swift modules, so + // use the scratch context where such operations are legal and safe. + + llvm::Optional maybe_scratch_ctx = + in_value.GetSwiftScratchContext(); + if (!maybe_scratch_ctx) + return {}; + auto scratch_ctx = maybe_scratch_ctx->get(); + if (!scratch_ctx) + return {}; + SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); + if (!swift_ast_ctx) + return {}; + + auto &remote_ast = GetRemoteASTContext(*swift_ast_ctx); + auto remote_ast_metadata_address = remote_ast.getHeapMetadataForObject( + swift::remote::RemoteAddress(instance_ptr)); + if (remote_ast_metadata_address) { + auto instance_type = remote_ast.getTypeForRemoteTypeMetadata( + remote_ast_metadata_address.getValue(), + /*skipArtificial=*/true); + if (instance_type) { + auto ref_type = ToCompilerType(instance_type.getValue()); + ConstString name = ref_type.GetMangledTypeName(); + if (!name) + LLDB_LOG(GetLog(LLDBLog::Types), "could not get type metadata:{0}\n", + instance_type.getFailure().render()); + return name; + } + } + return {}; +} + +llvm::Optional> +SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_ProtocolRemoteAST( + ValueObject &in_value, CompilerType protocol_type, bool use_local_buffer, + lldb::addr_t existential_address) { + // Dynamic type resolution in RemoteAST might pull in other Swift + // modules, so use the scratch context where such operations are + // legal and safe. + llvm::Optional maybe_scratch_ctx = + in_value.GetSwiftScratchContext(); + if (!maybe_scratch_ctx) + return {}; + auto scratch_ctx = maybe_scratch_ctx->get(); + if (!scratch_ctx) + return {}; + SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); + if (!swift_ast_ctx) + return {}; + + swift::remote::RemoteAddress remote_existential(existential_address); + auto &remote_ast = GetRemoteASTContext(*swift_ast_ctx); + auto swift_type = GetSwiftType(protocol_type); + if (!swift_type) + return {}; + if (use_local_buffer) + PushLocalBuffer(existential_address, in_value.GetByteSize().value_or(0)); + + auto result = remote_ast.getDynamicTypeAndAddressForExistential( + remote_existential, swift_type); + if (use_local_buffer) + PopLocalBuffer(); + + if (!result.isSuccess()) + return {}; + + auto type_and_address = result.getValue(); + + CompilerType type = ToCompilerType(type_and_address.InstanceType); + Address address; + address.SetRawAddress(type_and_address.PayloadAddress.getAddressData()); + return {{type, address}}; +} +#endif + +CompilerType SwiftLanguageRuntimeImpl::BindGenericTypeParametersRemoteAST( + StackFrame &stack_frame, CompilerType base_type) { + LLDB_SCOPED_TIMER(); + + // If this is a TypeRef type, bind that. + auto sc = stack_frame.GetSymbolContext(lldb::eSymbolContextEverything); + if (auto ts = + base_type.GetTypeSystem().dyn_cast_or_null()) + return BindGenericTypeParameters(stack_frame, *ts, + base_type.GetMangledTypeName()); + + Status error; + auto &target = m_process.GetTarget(); + assert(IsScratchContextLocked(target) && + "Swift scratch context not locked ahead of archetype binding"); + + // A failing Clang import in a module context permanently damages + // that module context. Binding archetypes can trigger an import of + // another module, so switch to a scratch context where such an + // operation is safe. + llvm::Optional maybe_scratch_ctx = + target.GetSwiftScratchContext(error, stack_frame); + if (!maybe_scratch_ctx) + return base_type; + auto scratch_ctx = maybe_scratch_ctx->get(); + if (!scratch_ctx) + return base_type; + SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); + if (!swift_ast_ctx) + return base_type; + base_type = swift_ast_ctx->ImportType(base_type, error); + + if (base_type.GetTypeInfo() & lldb::eTypeIsSwift) { + swift::Type target_swift_type(GetSwiftType(base_type)); + if (target_swift_type->hasArchetype()) + target_swift_type = target_swift_type->mapTypeOutOfContext().getPointer(); + + // FIXME: This is wrong, but it doesn't actually matter right now since + // all conformances are always visible + auto *module_decl = swift_ast_ctx->GetASTContext()->getStdlibModule(); + + // Replace opaque types with their underlying types when possible. + swift::Mangle::ASTMangler mangler(true); + + // Rewrite all dynamic self types to their static self types. + target_swift_type = + target_swift_type.transform([](swift::Type type) -> swift::Type { + if (auto *dynamic_self = + llvm::dyn_cast(type.getPointer())) + return dynamic_self->getSelfType(); + return type; + }); + + // Thicken generic metatypes. Once substituted, they should always + // be thick. TypeRef::subst() does the same transformation. + target_swift_type = + target_swift_type.transform([](swift::Type type) -> swift::Type { + using namespace swift; + const auto thin = MetatypeRepresentation::Thin; + const auto thick = MetatypeRepresentation::Thick; + if (auto *metatype = dyn_cast(type.getPointer())) + if (metatype->hasRepresentation() && + metatype->getRepresentation() == thin && + metatype->getInstanceType()->hasTypeParameter()) + return MetatypeType::get(metatype->getInstanceType(), thick); + return type; + }); + + while (target_swift_type->hasOpaqueArchetype()) { + auto old_type = target_swift_type; + target_swift_type = target_swift_type.subst( + [&](swift::SubstitutableType *type) -> swift::Type { + auto opaque_type = + llvm::dyn_cast(type); + if (!opaque_type || !opaque_type->getInterfaceType() + ->is()) + return type; + + // Try to find the symbol for the opaque type descriptor in the + // process. + auto mangled_name = ConstString( + mangler.mangleOpaqueTypeDescriptor(opaque_type->getDecl())); + + SymbolContextList found; + target.GetImages().FindSymbolsWithNameAndType( + mangled_name, eSymbolTypeData, found); + + if (found.GetSize() == 0) + return type; + + swift::Type result_type; + + for (unsigned i = 0, e = found.GetSize(); i < e; ++i) { + SymbolContext found_sc; + if (!found.GetContextAtIndex(i, found_sc)) + continue; + + // See if the symbol has an address. + if (!found_sc.symbol) + continue; + + auto addr = found_sc.symbol->GetAddress().GetLoadAddress(&target); + if (!addr || addr == LLDB_INVALID_ADDRESS) + continue; + + // Ask RemoteAST to get the underlying type out of the + // descriptor. + auto &remote_ast = GetRemoteASTContext(*swift_ast_ctx); + auto genericParam = opaque_type->getInterfaceType() + ->getAs(); + auto underlying_type_result = + remote_ast.getUnderlyingTypeForOpaqueType( + swift::remote::RemoteAddress(addr), + opaque_type->getSubstitutions(), + genericParam->getIndex()); + + if (!underlying_type_result) + continue; + + // If we haven't yet gotten an underlying type, use this as our + // possible result. + if (!result_type) { + result_type = underlying_type_result.getValue(); + } + // If we have two possibilities, they should match. + else if (!result_type->isEqual( + underlying_type_result.getValue())) { + return type; + } + } + + if (!result_type) + return type; + + return result_type; + }, + swift::LookUpConformanceInModule(module_decl), + swift::SubstFlags::DesugarMemberTypes | + swift::SubstFlags::SubstituteOpaqueArchetypes); + + // Stop if we've reached a fixpoint where we can't further resolve + // opaque types. + if (old_type->isEqual(target_swift_type)) + break; + } + + target_swift_type = target_swift_type.subst( + [this, &stack_frame, + &swift_ast_ctx](swift::SubstitutableType *type) -> swift::Type { + StreamString type_name; + if (!SwiftLanguageRuntime::GetAbstractTypeName(type_name, type)) + return type; + CompilerType concrete_type = this->GetConcreteType( + &stack_frame, ConstString(type_name.GetString())); + Status import_error; + CompilerType target_concrete_type = + swift_ast_ctx->ImportType(concrete_type, import_error); + + if (target_concrete_type.IsValid()) + return swift::Type(GetSwiftType(target_concrete_type)); + + return type; + }, + swift::LookUpConformanceInModule(module_decl), + swift::SubstFlags::DesugarMemberTypes); + assert(target_swift_type); + + return ToCompilerType({target_swift_type.getPointer()}); + } + return base_type; +} + +SwiftLanguageRuntime::MetadataPromise::MetadataPromise( + ValueObject &for_object, SwiftLanguageRuntimeImpl &runtime, + lldb::addr_t location) + : m_for_object_sp(for_object.GetSP()), m_swift_runtime(runtime), + m_metadata_location(location) {} + +CompilerType +SwiftLanguageRuntime::MetadataPromise::FulfillTypePromise(Status *error) { + if (error) + error->Clear(); + + Log *log(GetLog(LLDBLog::Types)); + + if (log) + log->Printf("[MetadataPromise] asked to fulfill type promise at location " + "0x%" PRIx64, + m_metadata_location); + + if (m_compiler_type.has_value()) + return m_compiler_type.value(); + + llvm::Optional maybe_swift_scratch_ctx = + m_for_object_sp->GetSwiftScratchContext(); + if (!maybe_swift_scratch_ctx) { + error->SetErrorString("couldn't get Swift scratch context"); + return CompilerType(); + } + auto scratch_ctx = maybe_swift_scratch_ctx->get(); + if (!scratch_ctx) { + error->SetErrorString("couldn't get Swift scratch context"); + return CompilerType(); + } + SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); + if (!swift_ast_ctx) { + error->SetErrorString("couldn't get Swift scratch context"); + return CompilerType(); + } + auto &remote_ast = m_swift_runtime.GetRemoteASTContext(*swift_ast_ctx); + swift::remoteAST::Result result = + remote_ast.getTypeForRemoteTypeMetadata( + swift::remote::RemoteAddress(m_metadata_location)); + + if (result) { + m_compiler_type = {swift_ast_ctx->weak_from_this(), + result.getValue().getPointer()}; + if (log) + log->Printf("[MetadataPromise] result is type %s", + m_compiler_type->GetTypeName().AsCString()); + return m_compiler_type.value(); + } else { + const auto &failure = result.getFailure(); + if (error) + error->SetErrorStringWithFormat("error in resolving type: %s", + failure.render().c_str()); + if (log) + log->Printf("[MetadataPromise] failure: %s", failure.render().c_str()); + return (m_compiler_type = CompilerType()).value(); + } +} + +SwiftLanguageRuntime::MetadataPromiseSP +SwiftLanguageRuntimeImpl::GetMetadataPromise(lldb::addr_t addr, + ValueObject &for_object) { + llvm::Optional maybe_swift_scratch_ctx = + for_object.GetSwiftScratchContext(); + if (!maybe_swift_scratch_ctx) + return nullptr; + auto scratch_ctx = maybe_swift_scratch_ctx->get(); + if (!scratch_ctx) + return nullptr; + SwiftASTContext *swift_ast_ctx = scratch_ctx->GetSwiftASTContext(); + if (!swift_ast_ctx) + return nullptr; + if (swift_ast_ctx->HasFatalErrors()) + return nullptr; + if (addr == 0 || addr == LLDB_INVALID_ADDRESS) + return nullptr; + + auto key = std::make_pair(swift_ast_ctx->GetASTContext(), addr); + auto iter = m_promises_map.find(key); + if (iter != m_promises_map.end()) + return iter->second; + + SwiftLanguageRuntime::MetadataPromiseSP promise_sp( + new SwiftLanguageRuntime::MetadataPromise(for_object, *this, addr)); + m_promises_map.insert({key, promise_sp}); + return promise_sp; +} + +SwiftLanguageRuntime::MetadataPromiseSP +SwiftLanguageRuntimeImpl::GetPromiseForTypeNameAndFrame(const char *type_name, + StackFrame *frame) { + if (!frame || !type_name || !type_name[0]) + return nullptr; + + StreamString type_metadata_ptr_var_name; + type_metadata_ptr_var_name.Printf("$%s", type_name); + VariableList *var_list = frame->GetVariableList(false, nullptr); + if (!var_list) + return nullptr; + + VariableSP var_sp(var_list->FindVariable( + ConstString(type_metadata_ptr_var_name.GetData()))); + if (!var_sp) + return nullptr; + + ValueObjectSP metadata_ptr_var_sp( + frame->GetValueObjectForFrameVariable(var_sp, lldb::eNoDynamicValues)); + if (!metadata_ptr_var_sp || + metadata_ptr_var_sp->UpdateValueIfNeeded() == false) + return nullptr; + + lldb::addr_t metadata_location(metadata_ptr_var_sp->GetValueAsUnsigned(0)); + if (metadata_location == 0 || metadata_location == LLDB_INVALID_ADDRESS) + return nullptr; + return GetMetadataPromise(metadata_location, *metadata_ptr_var_sp); +} + +} // namespace lldb_private