diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 26bfb9e5dd7c7..65fb81d501d85 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -331,9 +331,12 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { auto ts = swift_type.GetTypeSystem().dyn_cast_or_null(); if (!ts) return nullptr; - CompilerType clang_type; - bool is_imported = - ts->IsImportedType(swift_type.GetOpaqueQualType(), &clang_type); + bool is_imported = true; + CompilerType clang_type = + m_runtime.LookupAnonymousClangType(mangled.AsCString()); + if (!clang_type) + is_imported = + ts->IsImportedType(swift_type.GetOpaqueQualType(), &clang_type); if (!is_imported || !clang_type) { HEALTH_LOG("[LLDBTypeInfoProvider] Could not find clang debug type info " "for {0}", @@ -373,8 +376,20 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { "[LLDBTypeInfoProvider] bitfield support is not yet implemented"); continue; } - CompilerType swift_type = - typesystem.ConvertClangTypeToSwiftType(field_type); + CompilerType swift_type; + if (field_type.IsAnonymousType()) { + // Store anonymous tuples in a side table, to solve the + // problem that they cannot be looked up by name. + static unsigned m_num_anonymous_clang_types = 0; + std::string unique_swift_name(field_type.GetTypeName()); + llvm::raw_string_ostream(unique_swift_name) + << '#' << m_num_anonymous_clang_types++; + swift_type = typesystem.CreateClangStructType(unique_swift_name); + auto *key = swift_type.GetMangledTypeName().AsCString(); + m_runtime.RegisterAnonymousClangType(key, field_type); + } else { + swift_type = typesystem.ConvertClangTypeToSwiftType(field_type); + } auto *typeref = m_runtime.GetTypeRef(swift_type, &typesystem); swift::reflection::FieldInfo field_info = { name, (unsigned)bit_offset_ptr / 8, 0, typeref, @@ -386,6 +401,18 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { } }; +void SwiftLanguageRuntimeImpl::RegisterAnonymousClangType( + const char *key, CompilerType clang_type) { + const std::lock_guard locker(m_clang_type_info_mutex); + m_anonymous_clang_types.insert({key, clang_type}); +} + +CompilerType +SwiftLanguageRuntimeImpl::LookupAnonymousClangType(const char *key) { + const std::lock_guard locker(m_clang_type_info_mutex); + return m_anonymous_clang_types.lookup(key); +} + std::optional SwiftLanguageRuntimeImpl::lookupClangTypeInfo(CompilerType clang_type) { std::lock_guard locker(m_clang_type_info_mutex); diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h index 6f557830ea160..bfca1b59587c3 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h @@ -170,6 +170,11 @@ class SwiftLanguageRuntimeImpl { CompilerType BindGenericTypeParameters(StackFrame &stack_frame, CompilerType base_type); + /// Enter an anonymous Clang type with a name key into a side table. + void RegisterAnonymousClangType(const char *key, CompilerType clang_type); + /// Look up an anonymous Clang type with a name key into a side table. + CompilerType LookupAnonymousClangType(const char *key); + CompilerType GetConcreteType(ExecutionContextScope *exe_scope, ConstString abstract_type_name); @@ -434,6 +439,8 @@ class SwiftLanguageRuntimeImpl { llvm::DenseMap> m_clang_record_type_info; + llvm::DenseMap m_anonymous_clang_types; + unsigned m_num_anonymous_clang_types = 0; std::recursive_mutex m_clang_type_info_mutex; /// \} diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 760a89beec8aa..0e21751530b23 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -321,6 +321,22 @@ NodePointer TypeSystemSwiftTypeRef::CreateBoundGenericStruct( return outer_type; } +CompilerType +TypeSystemSwiftTypeRef::CreateClangStructType(llvm::StringRef name) { + using namespace swift::Demangle; + Demangler dem; + NodePointer module = dem.createNodeWithAllocatedText( + Node::Kind::Module, swift::MANGLING_MODULE_OBJC); + NodePointer identifier = + dem.createNodeWithAllocatedText(Node::Kind::Identifier, name); + NodePointer nominal = dem.createNode(Node::Kind::Structure); + nominal->addChild(module, dem); + nominal->addChild(identifier, dem); + NodePointer type = dem.createNode(Node::Kind::Type); + type->addChild(nominal, dem); + return RemangleAsType(dem, type); +} + /// Return a demangle tree leaf node representing \p clang_type. swift::Demangle::NodePointer TypeSystemSwiftTypeRef::GetClangTypeNode(CompilerType clang_type, diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h index ea40ce41f33fd..af7da24e703e9 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h @@ -327,6 +327,9 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { CompilerType CreateGenericTypeParamType(unsigned int depth, unsigned int index) override; + /// Create a __C imported struct type. + CompilerType CreateClangStructType(llvm::StringRef name); + /// Builds a bound generic struct demangle tree with the name, module name, /// and the struct's elements. static swift::Demangle::NodePointer CreateBoundGenericStruct( diff --git a/lldb/test/API/lang/swift/clangimporter/anonymous-clang-types/TestSwiftAnonymousClangTypes.py b/lldb/test/API/lang/swift/clangimporter/anonymous-clang-types/TestSwiftAnonymousClangTypes.py index 14963ad36155c..f253e6cb7e6ea 100644 --- a/lldb/test/API/lang/swift/clangimporter/anonymous-clang-types/TestSwiftAnonymousClangTypes.py +++ b/lldb/test/API/lang/swift/clangimporter/anonymous-clang-types/TestSwiftAnonymousClangTypes.py @@ -6,33 +6,48 @@ class TestSwiftAnonymousClangTypes(lldbtest.TestBase): @swiftTest - # FIMXE: This broke when adapting the swift-driver based Makefile.rules + # FIXME: This broke when adapting the swift-driver based Makefile.rules @expectedFailureAll(oslist=['linux']) def test(self): self.build() - lldbutil.run_to_source_breakpoint( + target, _, _, _ = lldbutil.run_to_source_breakpoint( self, "break here", lldb.SBFileSpec("main.swift") ) - self.expect( - "frame variable twoStructs", - substrs=[ - "(TwoAnonymousStructs) twoStructs = {", - "= (x = 1, y = 2, z = 3)", - "= (a = 4)", - ], - ) + def check(field, value): + self.assertTrue(field.IsValid()) + lldbutil.check_variable(self, field, False, value=value) - self.expect( - "frame variable twoUnions", - substrs=[ - "(TwoAnonymousUnions) twoUnions = {", - " = {", - " = (x = 2)", - " = (y = 2, z = 3)", - " }", - " = {", - " = (a = 4, b = 5, c = 6)", - " = (d = 4, e = 5)", - ], - ) + twoStructs = target.FindFirstGlobalVariable("twoStructs") + self.assertTrue(twoStructs.IsValid()) + + field0 = twoStructs.GetChildAtIndex(0) + self.assertTrue(field0.IsValid()) + check(field0.GetChildMemberWithName("x"), value="1") + check(field0.GetChildMemberWithName("y"), value="2") + check(field0.GetChildMemberWithName("z"), value="3") + + field1 = twoStructs.GetChildAtIndex(1) + self.assertTrue(field1.IsValid()) + check(field1.GetChildMemberWithName("a"), value="4") + + + twoUnions = target.FindFirstGlobalVariable("twoUnions") + self.assertTrue(twoUnions.IsValid()) + field0 = twoUnions.GetChildAtIndex(0) + self.assertTrue(field0.IsValid()) + field0_0 = field0.GetChildAtIndex(0) + check(field0_0.GetChildMemberWithName("x"), value="2") + field0_1 = field0.GetChildAtIndex(1) + check(field0_1.GetChildMemberWithName("y"), value="2") + check(field0_1.GetChildMemberWithName("z"), value="3") + + field1 = twoUnions.GetChildAtIndex(1) + self.assertTrue(field1.IsValid()) + field1_0 = field1.GetChildAtIndex(0) + check(field1_0.GetChildMemberWithName("a"), value="4") + check(field1_0.GetChildMemberWithName("b"), value="5") + check(field1_0.GetChildMemberWithName("c"), value="6") + field1_1 = field1.GetChildAtIndex(1) + check(field1_1.GetChildMemberWithName("d"), value="4") + check(field1_1.GetChildMemberWithName("e"), value="5")