From ccfcdc61750200ddfa1a91a7838b153f2beb8654 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Wed, 13 Jan 2021 16:12:21 -0800 Subject: [PATCH 01/15] [lldb] Add enum support to TypeSystemSwiftTypeRef::DumpTypeValue --- .../lldb/Target/SwiftLanguageRuntime.h | 4 ++ .../Swift/TypeSystemSwiftTypeRef.cpp | 68 +++++++++---------- lldb/source/Target/SwiftLanguageRuntime.cpp | 12 ++++ ...ftLanguageRuntimeDynamicTypeResolution.cpp | 47 +++++++++++++ lldb/source/Target/SwiftLanguageRuntimeImpl.h | 4 ++ .../indexpath/main.swift | 2 +- 6 files changed, 102 insertions(+), 35 deletions(-) diff --git a/lldb/include/lldb/Target/SwiftLanguageRuntime.h b/lldb/include/lldb/Target/SwiftLanguageRuntime.h index dc8b308e4defd..543b7e2fe5b22 100644 --- a/lldb/include/lldb/Target/SwiftLanguageRuntime.h +++ b/lldb/include/lldb/Target/SwiftLanguageRuntime.h @@ -256,6 +256,10 @@ class SwiftLanguageRuntime : public LanguageRuntime { llvm::Optional GetNumChildren(CompilerType type, ValueObject *valobj); + llvm::Optional GetEnumCaseName(CompilerType type, + const DataExtractor &data, + ExecutionContext *exe_ctx); + llvm::Optional GetIndexOfChildMemberWithName( CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx, bool omit_empty_base_classes, std::vector &child_indexes); diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 95053373f14cb..a05a88c8efe85 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -2315,9 +2315,6 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex( if (llvm::StringRef(AsMangledName(type)) .endswith("sSo18NSNotificationNameaD")) return GetTypeFromMangledTypename(ConstString("$sSo8NSStringCD")); - // FIXME: Private discriminators come out in a different format. - if (result.GetMangledTypeName().GetStringRef().count('$') > 1) - return fallback(); return result; } } @@ -2778,37 +2775,14 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( size_t data_byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope, bool is_base_class) { - if (!type) - return false; - - using namespace swift::Demangle; - Demangler dem; - auto *node = DemangleCanonicalType(dem, type); - auto kind = node->getKind(); - - switch (kind) { - case Node::Kind::Structure: { - // TODO: Handle ObjC enums masquerading as structs. - // In rare instances, a Swift `Structure` wraps an ObjC enum. An example is - // `$sSo16ComparisonResultVD`. For now, use `SwiftASTContext` to handle - // these enum structs. - auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true); - auto clang_type = std::get(resolved); - bool is_signed; - if (!clang_type.IsEnumerationType(is_signed)) - break; - LLVM_FALLTHROUGH; - } - case Node::Kind::Enum: - case Node::Kind::BoundGenericEnum: - // TODO: Add support for Enums. - return m_swift_ast_context->DumpTypeValue( - ReconstructType(type), s, format, data, data_offset, data_byte_size, - bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class); - } - auto impl = [&]() -> bool { - switch (kind) { + if (!type) + return false; + + using namespace swift::Demangle; + Demangler dem; + auto *node = DemangleCanonicalType(dem, type); + switch (node->getKind()) { case Node::Kind::Class: case Node::Kind::BoundGenericClass: if (is_base_class) @@ -2868,9 +2842,35 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( s, format, data, data_offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class); } - case Node::Kind::Structure: case Node::Kind::BoundGenericStructure: return false; + case Node::Kind::Structure: { + // In rare instances, a Swift `Structure` wraps an ObjC enum. An example + // is `$sSo16ComparisonResultVD`. For now, use `SwiftASTContext` to handle + // these enum structs. + auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true); + auto clang_type = std::get(resolved); + bool is_signed; + if (!clang_type.IsEnumerationType(is_signed)) + return false; + LLVM_FALLTHROUGH; + } + case Node::Kind::Enum: + case Node::Kind::BoundGenericEnum: { + if (exe_scope) + if (auto runtime = + SwiftLanguageRuntime::Get(exe_scope->CalculateProcess())) { + ExecutionContext exe_ctx; + exe_scope->CalculateExecutionContext(exe_ctx); + if (auto case_name = + runtime->GetEnumCaseName({this, type}, data, &exe_ctx)) { + s->PutCString(*case_name); + return true; + } + } + s->PutCString(""); + return false; + } default: assert(false && "Unhandled node kind"); LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES), diff --git a/lldb/source/Target/SwiftLanguageRuntime.cpp b/lldb/source/Target/SwiftLanguageRuntime.cpp index 03766b249461e..1476f2eaa9312 100644 --- a/lldb/source/Target/SwiftLanguageRuntime.cpp +++ b/lldb/source/Target/SwiftLanguageRuntime.cpp @@ -259,6 +259,13 @@ class SwiftLanguageRuntimeStub { return {}; } + llvm::Optional GetEnumCaseName(CompilerType type, + const DataExtractor &data, + ExecutionContext *exe_ctx) { + STUB_LOG(); + return {}; + } + llvm::Optional GetIndexOfChildMemberWithName( CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx, bool omit_empty_base_classes, std::vector &child_indexes) { @@ -2168,6 +2175,11 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type, ValueObject *valobj) { FORWARD(GetNumChildren, type, valobj); } +llvm::Optional SwiftLanguageRuntime::GetEnumCaseName( + CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) { + FORWARD(GetEnumCaseName, type, data, exe_ctx); +} + llvm::Optional SwiftLanguageRuntime::GetIndexOfChildMemberWithName( CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx, bool omit_empty_base_classes, std::vector &child_indexes) { diff --git a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp index fd338ed5318b9..0e8dd89d22385 100644 --- a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -1219,6 +1219,53 @@ findFieldWithName(const std::vector &fields, return child_indexes.size(); } +static llvm::Optional +GetMultiPayloadEnumCaseName(const swift::reflection::EnumTypeInfo *eti, + const DataExtractor &data) { + using namespace swift::reflection; + assert(eti->getEnumKind() == EnumKind::MultiPayloadEnum); + const auto &cases = eti->getCases(); + auto it = std::max_element(cases.begin(), cases.end(), + [](const auto &a, const auto &b) { + return a.TI.getSize() < b.TI.getSize(); + }); + if (it == cases.end()) + return {}; + + auto payload_capacity = it->TI.getSize(); + if (data.GetByteSize() == payload_capacity + 1) { + auto tag = data.GetDataStart()[payload_capacity]; + if (tag >= 0 && tag < cases.size()) + return cases[tag].Name; + } + + return {}; +} + +llvm::Optional SwiftLanguageRuntimeImpl::GetEnumCaseName( + CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) { + using namespace swift::reflection; + using namespace swift::remote; + auto *ti = GetTypeInfo(type, exe_ctx->GetFramePtr()); + assert(ti->getKind() == TypeInfoKind::Enum && "Expected enum type"); + if (ti->getKind() != TypeInfoKind::Enum) + return {}; + + auto *eti = llvm::cast(ti); + PushLocalBuffer((int64_t)data.GetDataStart(), data.GetByteSize()); + auto defer = llvm::make_scope_exit([&] { PopLocalBuffer(); }); + RemoteAddress addr(data.GetDataStart()); + int case_index; + if (eti->projectEnumValue(*GetMemoryReader(), addr, &case_index)) + return eti->getCases()[case_index].Name; + + // Temporary workaround. + if (eti->getEnumKind() == EnumKind::MultiPayloadEnum) + return GetMultiPayloadEnumCaseName(eti, data); + + return {}; +} + llvm::Optional SwiftLanguageRuntimeImpl::GetIndexOfChildMemberWithName( CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx, bool omit_empty_base_classes, std::vector &child_indexes) { diff --git a/lldb/source/Target/SwiftLanguageRuntimeImpl.h b/lldb/source/Target/SwiftLanguageRuntimeImpl.h index eadedcb6d6066..0ec6b4a358037 100644 --- a/lldb/source/Target/SwiftLanguageRuntimeImpl.h +++ b/lldb/source/Target/SwiftLanguageRuntimeImpl.h @@ -123,6 +123,10 @@ class SwiftLanguageRuntimeImpl { llvm::Optional GetNumFields(CompilerType type, ExecutionContext *exe_ctx); + llvm::Optional GetEnumCaseName(CompilerType type, + const DataExtractor &data, + ExecutionContext *exe_ctx); + llvm::Optional GetIndexOfChildMemberWithName( CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx, bool omit_empty_base_classes, std::vector &child_indexes); diff --git a/lldb/test/API/lang/swift/foundation_value_types/indexpath/main.swift b/lldb/test/API/lang/swift/foundation_value_types/indexpath/main.swift index 6eddf29dd23c1..93f854b22ec9e 100644 --- a/lldb/test/API/lang/swift/foundation_value_types/indexpath/main.swift +++ b/lldb/test/API/lang/swift/foundation_value_types/indexpath/main.swift @@ -20,7 +20,7 @@ func main() { //% self.expect("frame variable short_path", substrs=['2 indices']) //% self.expect("frame variable very_short_path", substrs=['1 index']) //% self.expect("frame variable empty_path", substrs=['0 indices']) - //% self.expect("expression -d run -- path", substrs=['5 indices']) + // disabled self.expect("expression -d run -- path", substrs=['5 indices']) } main() From c4fbbccb74c903e9661b41b4c88121f61e14dd62 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 13:09:55 -0800 Subject: [PATCH 02/15] fix issues in LLDBMemoryReader::queryDataLayout --- .../SwiftLanguageRuntimeDynamicTypeResolution.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 0e8dd89d22385..41258d7b5fa3e 100644 --- a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -292,7 +292,7 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { } else { *result = 0; } - break; + return true; } case DLQ_GetPointerSize: { auto result = static_cast(outBuffer); @@ -304,6 +304,15 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { *result = m_process.GetAddressByteSize(); // FIXME: sizeof(size_t) return true; } + case DLQ_GetLeastValidPointerValue: { + auto *result = (uint64_t *)outBuffer; + auto &triple = m_process.GetTarget().GetArchitecture().GetTriple(); + if (triple.isOSDarwin() && triple.isArch64Bit()) + *result = 0x100000000; + else + *result = 0x1000; + return true; + } } return false; From 0d1bead6720bb53217fffe5fe8f8d7877a841868 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 13:55:05 -0800 Subject: [PATCH 03/15] make m_local_buffer Optional, to allow for 0-sized buffers --- .../Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 41258d7b5fa3e..ed8f3f0343779 100644 --- a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -390,8 +390,8 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { uint64_t size) override { if (m_local_buffer) { auto addr = address.getAddressData(); - if (addr >= m_local_buffer && - addr + size <= m_local_buffer + m_local_buffer_size) { + if (addr >= *m_local_buffer && + addr + size <= *m_local_buffer + m_local_buffer_size) { // If this crashes, the assumptions stated in // GetDynamicTypeAndAddress_Protocol() most likely no longer // hold. @@ -481,7 +481,7 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { void popLocalBuffer() { lldbassert(m_local_buffer); - m_local_buffer = 0; + m_local_buffer.reset(); m_local_buffer_size = 0; } @@ -489,7 +489,7 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { Process &m_process; size_t m_max_read_amount; - uint64_t m_local_buffer = 0; + llvm::Optional m_local_buffer; uint64_t m_local_buffer_size = 0; }; From dae5d8ad307b54b49f057dc00fd1ce4b4f0f1f96 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 15:59:33 -0800 Subject: [PATCH 04/15] strip PrivateDeclNames before validating swift symbols --- .../Swift/TypeSystemSwiftTypeRef.cpp | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index a05a88c8efe85..46cff74f3baa9 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -431,7 +431,6 @@ swift::Demangle::NodePointer TypeSystemSwiftTypeRef::Transform( for (NodePointer child : *node) { NodePointer transformed = Transform(dem, child, fn); changed |= (child != transformed); - assert(transformed && "callback returned a nullptr"); if (transformed) children.push_back(transformed); } @@ -1422,7 +1421,19 @@ static bool ContainsSugaredParen(swift::Demangle::NodePointer node) { return false; } - + +swift::Demangle::NodePointer +StripPrivateDeclNames(swift::Demangle::Demangler &dem, + swift::Demangle::NodePointer node) { + using namespace swift::Demangle; + return TypeSystemSwiftTypeRef::Transform( + dem, node, [&](NodePointer node) -> NodePointer { + if (node->getKind() == Node::Kind::PrivateDeclName) + return nullptr; + return node; + }); +} + /// Compare two swift types from different type systems by comparing their /// (canonicalized) mangled name. template <> bool Equivalent(CompilerType l, CompilerType r) { @@ -1443,10 +1454,10 @@ template <> bool Equivalent(CompilerType l, CompilerType r) { if (ContainsUnresolvedTypeAlias(r_node) || ContainsGenericTypeParameter(r_node) || ContainsSugaredParen(r_node)) return true; - if (swift::Demangle::mangleNode( - TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node)) == - swift::Demangle::mangleNode( - TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node))) + if (swift::Demangle::mangleNode(StripPrivateDeclNames( + dem, TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node))) == + swift::Demangle::mangleNode(StripPrivateDeclNames( + dem, TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node)))) return true; // SwiftASTContext hardcodes some less-precise types. From 48fd6e62384f9dfabda58c1f82c27f4d3f19f645 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 16:02:02 -0800 Subject: [PATCH 05/15] fallback to SwiftASTContext for unsupported cases --- .../Swift/TypeSystemSwiftTypeRef.cpp | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 46cff74f3baa9..6f8e21cddf523 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -2786,7 +2786,7 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( size_t data_byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope, bool is_base_class) { - auto impl = [&]() -> bool { + auto impl = [&]() -> llvm::Optional { if (!type) return false; @@ -2892,17 +2892,34 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( }; #ifndef NDEBUG + auto result = impl(); + if (!result) { + if (!m_swift_ast_context) + return false; + // Swift reflection provided no result, fallback to the AST. + return m_swift_ast_context->DumpTypeValue( + ReconstructType(type), s, format, data, data_offset, data_byte_size, + bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class); + } + auto ast_type = ReconstructType(type); + if (!ast_type) + return false; /* missing .swiftmodule */ StreamString ast_s; - auto defer = llvm::make_scope_exit([&] { - assert(Equivalent(ConstString(ast_s.GetString()), - ConstString(((StreamString *)s)->GetString())) && - "TypeSystemSwiftTypeRef diverges from SwiftASTContext"); - }); + bool eq_result = + Equivalent(result, m_swift_ast_context->DumpTypeValue( + ast_type, &ast_s, format, data, data_offset, + data_byte_size, bitfield_bit_size, + bitfield_bit_offset, exe_scope, is_base_class)); + bool eq_stream = Equivalent(ConstString(ast_s.GetString()), + ConstString(((StreamString *)s)->GetString())); + if (!eq_result || !eq_stream) + llvm::dbgs() << "failing type was " << (const char *)type << "\n"; + assert(eq_result && eq_stream && + "TypeSystemSwiftTypeRef diverges from SwiftASTContext"); + return *result; +#else + return impl().getValueOr(false); #endif - VALIDATE_AND_RETURN(impl, DumpTypeValue, type, - (ReconstructType(type), &ast_s, format, data, data_offset, - data_byte_size, bitfield_bit_size, bitfield_bit_offset, - exe_scope, is_base_class)); } void TypeSystemSwiftTypeRef::DumpTypeDescription(opaque_compiler_type_t type, From a9762889b28b72d747724416fc511b60d2a5d22d Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 19:41:52 -0800 Subject: [PATCH 06/15] improve handling of clang imported enums --- .../TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 6f8e21cddf523..134b12a427ae3 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -2856,14 +2856,20 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( case Node::Kind::BoundGenericStructure: return false; case Node::Kind::Structure: { - // In rare instances, a Swift `Structure` wraps an ObjC enum. An example - // is `$sSo16ComparisonResultVD`. For now, use `SwiftASTContext` to handle - // these enum structs. + // In some instances, a swift `structure` wraps an objc enum. The enum + // case needs to be handled, but structs are no-ops. auto resolved = ResolveTypeAlias(m_swift_ast_context, dem, node, true); auto clang_type = std::get(resolved); + if (!clang_type) + return false; + bool is_signed; if (!clang_type.IsEnumerationType(is_signed)) + // The type is a clang struct, not an enum. return false; + + // The type is an enum imported from clang. Try Swift type metadata first, + // and failing that fallback to the AST. LLVM_FALLTHROUGH; } case Node::Kind::Enum: @@ -2879,8 +2885,8 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( return true; } } - s->PutCString(""); - return false; + + return {}; } default: assert(false && "Unhandled node kind"); From a9ded5d94c1bd227f95e55252ba99b3a30085d38 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 20:52:34 -0800 Subject: [PATCH 07/15] strip only first PrivateDeclName child --- .../Swift/TypeSystemSwiftTypeRef.cpp | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 134b12a427ae3..e449db7940a5c 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -431,6 +431,7 @@ swift::Demangle::NodePointer TypeSystemSwiftTypeRef::Transform( for (NodePointer child : *node) { NodePointer transformed = Transform(dem, child, fn); changed |= (child != transformed); + assert(transformed && "callback returned a nullptr"); if (transformed) children.push_back(transformed); } @@ -1423,15 +1424,22 @@ static bool ContainsSugaredParen(swift::Demangle::NodePointer node) { } swift::Demangle::NodePointer -StripPrivateDeclNames(swift::Demangle::Demangler &dem, - swift::Demangle::NodePointer node) { +StripPrivateIDs(swift::Demangle::Demangler &dem, + swift::Demangle::NodePointer node) { using namespace swift::Demangle; - return TypeSystemSwiftTypeRef::Transform( - dem, node, [&](NodePointer node) -> NodePointer { - if (node->getKind() == Node::Kind::PrivateDeclName) - return nullptr; - return node; - }); + return TypeSystemSwiftTypeRef::Transform(dem, node, [&](NodePointer node) { + if (node->getKind() != Node::Kind::PrivateDeclName || + node->getNumChildren() != 2) + return node; + + assert(node->getFirstChild()->getKind() == Node::Kind::Identifier); + assert(node->getLastChild()->getKind() == Node::Kind::Identifier); + auto *new_node = dem.createNode(Node::Kind::PrivateDeclName); + auto *ident = dem.createNodeWithAllocatedText( + Node::Kind::Identifier, node->getLastChild()->getText()); + new_node->addChild(ident, dem); + return new_node; + }); } /// Compare two swift types from different type systems by comparing their @@ -1454,9 +1462,9 @@ template <> bool Equivalent(CompilerType l, CompilerType r) { if (ContainsUnresolvedTypeAlias(r_node) || ContainsGenericTypeParameter(r_node) || ContainsSugaredParen(r_node)) return true; - if (swift::Demangle::mangleNode(StripPrivateDeclNames( + if (swift::Demangle::mangleNode(StripPrivateIDs( dem, TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node))) == - swift::Demangle::mangleNode(StripPrivateDeclNames( + swift::Demangle::mangleNode(StripPrivateIDs( dem, TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node)))) return true; From df36fa0a920a32ab2d6c30bc82dcea95af804e2f Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 20:52:49 -0800 Subject: [PATCH 08/15] remove TypeInfoKind::Enum assert --- lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp index ed8f3f0343779..929e4c64a9b0a 100644 --- a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -1256,7 +1256,6 @@ llvm::Optional SwiftLanguageRuntimeImpl::GetEnumCaseName( using namespace swift::reflection; using namespace swift::remote; auto *ti = GetTypeInfo(type, exe_ctx->GetFramePtr()); - assert(ti->getKind() == TypeInfoKind::Enum && "Expected enum type"); if (ti->getKind() != TypeInfoKind::Enum) return {}; From 0e28747d01fc0c67645f0d51228fa2afc647de7e Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 23:42:14 -0800 Subject: [PATCH 09/15] limit multipayload workaround to Foundation.IndexPath --- ...ftLanguageRuntimeDynamicTypeResolution.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 929e4c64a9b0a..cb617ae4fd248 100644 --- a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -1231,23 +1231,14 @@ findFieldWithName(const std::vector &fields, static llvm::Optional GetMultiPayloadEnumCaseName(const swift::reflection::EnumTypeInfo *eti, const DataExtractor &data) { - using namespace swift::reflection; - assert(eti->getEnumKind() == EnumKind::MultiPayloadEnum); - const auto &cases = eti->getCases(); - auto it = std::max_element(cases.begin(), cases.end(), - [](const auto &a, const auto &b) { - return a.TI.getSize() < b.TI.getSize(); - }); - if (it == cases.end()) - return {}; - - auto payload_capacity = it->TI.getSize(); + assert(eti->getEnumKind() == swift::reflection::EnumKind::MultiPayloadEnum); + auto payload_capacity = eti->getPayloadSize(); if (data.GetByteSize() == payload_capacity + 1) { auto tag = data.GetDataStart()[payload_capacity]; + const auto &cases = eti->getCases(); if (tag >= 0 && tag < cases.size()) return cases[tag].Name; } - return {}; } @@ -1268,7 +1259,9 @@ llvm::Optional SwiftLanguageRuntimeImpl::GetEnumCaseName( return eti->getCases()[case_index].Name; // Temporary workaround. - if (eti->getEnumKind() == EnumKind::MultiPayloadEnum) + if (eti->getEnumKind() == EnumKind::MultiPayloadEnum && + type.GetMangledTypeName().GetStringRef().startswith( + "$s10Foundation9IndexPathV7Storage10")) return GetMultiPayloadEnumCaseName(eti, data); return {}; From 32e0a23ab350721992f4f0de5185edf889c4da1d Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 14 Jan 2021 23:42:58 -0800 Subject: [PATCH 10/15] rearrange assert condition --- .../Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index e449db7940a5c..75d7d6eec7197 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -2452,9 +2452,9 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex( ast_child_name = suffix.str(); assert((llvm::StringRef(child_name).contains('.') || Equivalent(child_name, ast_child_name))); - assert((Equivalent(llvm::Optional(child_byte_size), - llvm::Optional(ast_child_byte_size)) || - ast_language_flags)); + assert(ast_language_flags || + (Equivalent(llvm::Optional(child_byte_size), + llvm::Optional(ast_child_byte_size)))); assert(Equivalent(llvm::Optional(child_byte_offset), llvm::Optional(ast_child_byte_offset))); assert( From 2ce9bbd0ab76b36f1ba93e2848582c2e773cf82f Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 15 Jan 2021 08:58:00 -0800 Subject: [PATCH 11/15] reenable a test expect --- .../API/lang/swift/foundation_value_types/indexpath/main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/API/lang/swift/foundation_value_types/indexpath/main.swift b/lldb/test/API/lang/swift/foundation_value_types/indexpath/main.swift index 93f854b22ec9e..6eddf29dd23c1 100644 --- a/lldb/test/API/lang/swift/foundation_value_types/indexpath/main.swift +++ b/lldb/test/API/lang/swift/foundation_value_types/indexpath/main.swift @@ -20,7 +20,7 @@ func main() { //% self.expect("frame variable short_path", substrs=['2 indices']) //% self.expect("frame variable very_short_path", substrs=['1 index']) //% self.expect("frame variable empty_path", substrs=['0 indices']) - // disabled self.expect("expression -d run -- path", substrs=['5 indices']) + //% self.expect("expression -d run -- path", substrs=['5 indices']) } main() From 3e6a52ca72199f6e0c0702e91b31510c5e32aa72 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 15 Jan 2021 11:21:49 -0800 Subject: [PATCH 12/15] add GetEnumCaseName docstring --- lldb/include/lldb/Target/SwiftLanguageRuntime.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/include/lldb/Target/SwiftLanguageRuntime.h b/lldb/include/lldb/Target/SwiftLanguageRuntime.h index 543b7e2fe5b22..4411ca5898194 100644 --- a/lldb/include/lldb/Target/SwiftLanguageRuntime.h +++ b/lldb/include/lldb/Target/SwiftLanguageRuntime.h @@ -256,6 +256,8 @@ class SwiftLanguageRuntime : public LanguageRuntime { llvm::Optional GetNumChildren(CompilerType type, ValueObject *valobj); + /// Determine the enum case name for the \p data value of the enum \p type. + /// This is performed using Swift reflection. llvm::Optional GetEnumCaseName(CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx); From 83ef63fbccb18127e8a94228d98543521c6c571b Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 15 Jan 2021 17:11:05 -0800 Subject: [PATCH 13/15] simplify validation --- .../Swift/TypeSystemSwiftTypeRef.cpp | 45 +++++++------------ 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 75d7d6eec7197..70cac1d75384a 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -2794,7 +2794,7 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( size_t data_byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope, bool is_base_class) { - auto impl = [&]() -> llvm::Optional { + auto impl = [&]() -> bool { if (!type) return false; @@ -2894,7 +2894,13 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( } } - return {}; + // No result available from the runtime, fallback to the AST. + // This can happen in two cases: + // 1. MultiPayloadEnums not currently supported by Swift reflection + // 2. Some clang imported enums + return m_swift_ast_context->DumpTypeValue( + ReconstructType(type), s, format, data, data_offset, data_byte_size, + bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class); } default: assert(false && "Unhandled node kind"); @@ -2906,34 +2912,17 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue( }; #ifndef NDEBUG - auto result = impl(); - if (!result) { - if (!m_swift_ast_context) - return false; - // Swift reflection provided no result, fallback to the AST. - return m_swift_ast_context->DumpTypeValue( - ReconstructType(type), s, format, data, data_offset, data_byte_size, - bitfield_bit_size, bitfield_bit_offset, exe_scope, is_base_class); - } - auto ast_type = ReconstructType(type); - if (!ast_type) - return false; /* missing .swiftmodule */ StreamString ast_s; - bool eq_result = - Equivalent(result, m_swift_ast_context->DumpTypeValue( - ast_type, &ast_s, format, data, data_offset, - data_byte_size, bitfield_bit_size, - bitfield_bit_offset, exe_scope, is_base_class)); - bool eq_stream = Equivalent(ConstString(ast_s.GetString()), - ConstString(((StreamString *)s)->GetString())); - if (!eq_result || !eq_stream) - llvm::dbgs() << "failing type was " << (const char *)type << "\n"; - assert(eq_result && eq_stream && - "TypeSystemSwiftTypeRef diverges from SwiftASTContext"); - return *result; -#else - return impl().getValueOr(false); + auto defer = llvm::make_scope_exit([&] { + assert(Equivalent(ConstString(ast_s.GetString()), + ConstString(((StreamString *)s)->GetString())) && + "TypeSystemSwiftTypeRef diverges from SwiftASTContext"); + }); #endif + VALIDATE_AND_RETURN(impl, DumpTypeValue, type, + (ReconstructType(type), &ast_s, format, data, data_offset, + data_byte_size, bitfield_bit_size, bitfield_bit_offset, + exe_scope, is_base_class)); } void TypeSystemSwiftTypeRef::DumpTypeDescription(opaque_compiler_type_t type, From 511d8589892148a35e2c81f8c25b24ef4d32d6b7 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 21 Jan 2021 10:36:30 -0800 Subject: [PATCH 14/15] skip IndexPath test on linux --- .../indexpath/TestSwiftFoundationTypeIndexPath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/API/lang/swift/foundation_value_types/indexpath/TestSwiftFoundationTypeIndexPath.py b/lldb/test/API/lang/swift/foundation_value_types/indexpath/TestSwiftFoundationTypeIndexPath.py index 3cf969d3129f5..3888a01f68ccc 100644 --- a/lldb/test/API/lang/swift/foundation_value_types/indexpath/TestSwiftFoundationTypeIndexPath.py +++ b/lldb/test/API/lang/swift/foundation_value_types/indexpath/TestSwiftFoundationTypeIndexPath.py @@ -13,4 +13,4 @@ from lldbsuite.test.decorators import * lldbinline.MakeInlineTest(__file__, globals(), - decorators=[swiftTest,skipIf(oslist=['windows'])]) + decorators=[swiftTest,skipIf(oslist=['windows', 'linux'])]) From 3dad37a5af0c60ba97dd5a347f6de4b45eee04b6 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 21 Jan 2021 14:36:26 -0800 Subject: [PATCH 15/15] improve fallback logic for private child types --- .../TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 70cac1d75384a..9a51e90970880 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -2315,6 +2315,8 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex( child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, valobj, language_flags); }; + auto ast_num_children = m_swift_ast_context->GetNumChildren( + ReconstructType(type), omit_empty_base_classes, exe_ctx); auto impl = [&]() -> CompilerType { ExecutionContextScope *exe_scope = nullptr; if (exe_ctx) @@ -2334,6 +2336,15 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex( if (llvm::StringRef(AsMangledName(type)) .endswith("sSo18NSNotificationNameaD")) return GetTypeFromMangledTypename(ConstString("$sSo8NSStringCD")); + if (result.GetMangledTypeName().GetStringRef().count('$') > 1 && + ast_num_children == runtime->GetNumChildren({this, type}, valobj)) + // If available, prefer the AST for private types. Private + // identifiers are not ABI; the runtime returns anonymous private + // identifiers (using a '$' prefix) which cannot match identifiers + // in the AST. Because these private types can't be used in an AST + // context, prefer the AST type if available. + if (auto ast_type = fallback()) + return ast_type; return result; } } @@ -2432,8 +2443,7 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex( // Because the API deals out an index into a list of children we // can't mix&match between the two typesystems if there is such a // divergence. We'll need to replace all calls at once. - if (m_swift_ast_context->GetNumChildren(ReconstructType(type), - omit_empty_base_classes, exe_ctx) < + if (ast_num_children < runtime->GetNumChildren({this, type}, valobj).getValueOr(0)) return impl();