Skip to content

Commit 851bb55

Browse files
committed
[LLDBTypeInfoProvider] Store anonymous clang types in a side table
so they can be found again when their TypeInfo is requested. This changes the behavior of the modified test such that it now uses TypeSystemSwiftTypeRef, which slightly alters the textual output. I took this as an opportunity to convert it to check_variable.
1 parent 471bfae commit 851bb55

File tree

5 files changed

+96
-28
lines changed

5 files changed

+96
-28
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,12 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
331331
auto ts = swift_type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>();
332332
if (!ts)
333333
return nullptr;
334-
CompilerType clang_type;
335-
bool is_imported =
336-
ts->IsImportedType(swift_type.GetOpaqueQualType(), &clang_type);
334+
bool is_imported = true;
335+
CompilerType clang_type =
336+
m_runtime.LookupAnonymousClangType(mangled.AsCString());
337+
if (!clang_type)
338+
is_imported =
339+
ts->IsImportedType(swift_type.GetOpaqueQualType(), &clang_type);
337340
if (!is_imported || !clang_type) {
338341
HEALTH_LOG("[LLDBTypeInfoProvider] Could not find clang debug type info "
339342
"for {0}",
@@ -373,8 +376,20 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
373376
"[LLDBTypeInfoProvider] bitfield support is not yet implemented");
374377
continue;
375378
}
376-
CompilerType swift_type =
377-
typesystem.ConvertClangTypeToSwiftType(field_type);
379+
CompilerType swift_type;
380+
if (field_type.IsAnonymousType()) {
381+
// Store anonymous tuples in a side table, to solve the
382+
// problem that they cannot be looked up by name.
383+
static unsigned m_num_anonymous_clang_types = 0;
384+
std::string unique_swift_name(field_type.GetTypeName());
385+
llvm::raw_string_ostream(unique_swift_name)
386+
<< '#' << m_num_anonymous_clang_types++;
387+
swift_type = typesystem.CreateClangStructType(unique_swift_name);
388+
auto *key = swift_type.GetMangledTypeName().AsCString();
389+
m_runtime.RegisterAnonymousClangType(key, field_type);
390+
} else {
391+
swift_type = typesystem.ConvertClangTypeToSwiftType(field_type);
392+
}
378393
auto *typeref = m_runtime.GetTypeRef(swift_type, &typesystem);
379394
swift::reflection::FieldInfo field_info = {
380395
name, (unsigned)bit_offset_ptr / 8, 0, typeref,
@@ -386,6 +401,18 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
386401
}
387402
};
388403

404+
void SwiftLanguageRuntimeImpl::RegisterAnonymousClangType(
405+
const char *key, CompilerType clang_type) {
406+
const std::lock_guard<std::recursive_mutex> locker(m_clang_type_info_mutex);
407+
m_anonymous_clang_types.insert({key, clang_type});
408+
}
409+
410+
CompilerType
411+
SwiftLanguageRuntimeImpl::LookupAnonymousClangType(const char *key) {
412+
const std::lock_guard<std::recursive_mutex> locker(m_clang_type_info_mutex);
413+
return m_anonymous_clang_types.lookup(key);
414+
}
415+
389416
std::optional<const swift::reflection::TypeInfo *>
390417
SwiftLanguageRuntimeImpl::lookupClangTypeInfo(CompilerType clang_type) {
391418
std::lock_guard<std::recursive_mutex> locker(m_clang_type_info_mutex);

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ class SwiftLanguageRuntimeImpl {
170170
CompilerType BindGenericTypeParameters(StackFrame &stack_frame,
171171
CompilerType base_type);
172172

173+
/// Enter an anonymous Clang type with a name key into a side table.
174+
void RegisterAnonymousClangType(const char *key, CompilerType clang_type);
175+
/// Look up an anonymous Clang type with a name key into a side table.
176+
CompilerType LookupAnonymousClangType(const char *key);
177+
173178
CompilerType GetConcreteType(ExecutionContextScope *exe_scope,
174179
ConstString abstract_type_name);
175180

@@ -434,6 +439,8 @@ class SwiftLanguageRuntimeImpl {
434439
llvm::DenseMap<lldb::opaque_compiler_type_t,
435440
std::optional<swift::reflection::RecordTypeInfo>>
436441
m_clang_record_type_info;
442+
llvm::DenseMap<const char *, CompilerType> m_anonymous_clang_types;
443+
unsigned m_num_anonymous_clang_types = 0;
437444
std::recursive_mutex m_clang_type_info_mutex;
438445
/// \}
439446

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,22 @@ NodePointer TypeSystemSwiftTypeRef::CreateBoundGenericStruct(
321321
return outer_type;
322322
}
323323

324+
CompilerType
325+
TypeSystemSwiftTypeRef::CreateClangStructType(llvm::StringRef name) {
326+
using namespace swift::Demangle;
327+
Demangler dem;
328+
NodePointer module = dem.createNodeWithAllocatedText(
329+
Node::Kind::Module, swift::MANGLING_MODULE_OBJC);
330+
NodePointer identifier =
331+
dem.createNodeWithAllocatedText(Node::Kind::Identifier, name);
332+
NodePointer nominal = dem.createNode(Node::Kind::Structure);
333+
nominal->addChild(module, dem);
334+
nominal->addChild(identifier, dem);
335+
NodePointer type = dem.createNode(Node::Kind::Type);
336+
type->addChild(nominal, dem);
337+
return RemangleAsType(dem, type);
338+
}
339+
324340
/// Return a demangle tree leaf node representing \p clang_type.
325341
swift::Demangle::NodePointer
326342
TypeSystemSwiftTypeRef::GetClangTypeNode(CompilerType clang_type,

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,9 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
327327
CompilerType CreateGenericTypeParamType(unsigned int depth,
328328
unsigned int index) override;
329329

330+
/// Create a __C imported struct type.
331+
CompilerType CreateClangStructType(llvm::StringRef name);
332+
330333
/// Builds a bound generic struct demangle tree with the name, module name,
331334
/// and the struct's elements.
332335
static swift::Demangle::NodePointer CreateBoundGenericStruct(

lldb/test/API/lang/swift/clangimporter/anonymous-clang-types/TestSwiftAnonymousClangTypes.py

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,48 @@
66

77
class TestSwiftAnonymousClangTypes(lldbtest.TestBase):
88
@swiftTest
9-
# FIMXE: This broke when adapting the swift-driver based Makefile.rules
9+
# FIXME: This broke when adapting the swift-driver based Makefile.rules
1010
@expectedFailureAll(oslist=['linux'])
1111
def test(self):
1212
self.build()
1313

14-
lldbutil.run_to_source_breakpoint(
14+
target, _, _, _ = lldbutil.run_to_source_breakpoint(
1515
self, "break here", lldb.SBFileSpec("main.swift")
1616
)
17-
self.expect(
18-
"frame variable twoStructs",
19-
substrs=[
20-
"(TwoAnonymousStructs) twoStructs = {",
21-
"= (x = 1, y = 2, z = 3)",
22-
"= (a = 4)",
23-
],
24-
)
17+
def check(field, value):
18+
self.assertTrue(field.IsValid())
19+
lldbutil.check_variable(self, field, False, value=value)
2520

26-
self.expect(
27-
"frame variable twoUnions",
28-
substrs=[
29-
"(TwoAnonymousUnions) twoUnions = {",
30-
" = {",
31-
" = (x = 2)",
32-
" = (y = 2, z = 3)",
33-
" }",
34-
" = {",
35-
" = (a = 4, b = 5, c = 6)",
36-
" = (d = 4, e = 5)",
37-
],
38-
)
21+
twoStructs = target.FindFirstGlobalVariable("twoStructs")
22+
self.assertTrue(twoStructs.IsValid())
23+
24+
field0 = twoStructs.GetChildAtIndex(0)
25+
self.assertTrue(field0.IsValid())
26+
check(field0.GetChildMemberWithName("x"), value="1")
27+
check(field0.GetChildMemberWithName("y"), value="2")
28+
check(field0.GetChildMemberWithName("z"), value="3")
29+
30+
field1 = twoStructs.GetChildAtIndex(1)
31+
self.assertTrue(field1.IsValid())
32+
check(field1.GetChildMemberWithName("a"), value="4")
33+
34+
35+
twoUnions = target.FindFirstGlobalVariable("twoUnions")
36+
self.assertTrue(twoUnions.IsValid())
37+
field0 = twoUnions.GetChildAtIndex(0)
38+
self.assertTrue(field0.IsValid())
39+
field0_0 = field0.GetChildAtIndex(0)
40+
check(field0_0.GetChildMemberWithName("x"), value="2")
41+
field0_1 = field0.GetChildAtIndex(1)
42+
check(field0_1.GetChildMemberWithName("y"), value="2")
43+
check(field0_1.GetChildMemberWithName("z"), value="3")
44+
45+
field1 = twoUnions.GetChildAtIndex(1)
46+
self.assertTrue(field1.IsValid())
47+
field1_0 = field1.GetChildAtIndex(0)
48+
check(field1_0.GetChildMemberWithName("a"), value="4")
49+
check(field1_0.GetChildMemberWithName("b"), value="5")
50+
check(field1_0.GetChildMemberWithName("c"), value="6")
51+
field1_1 = field1.GetChildAtIndex(1)
52+
check(field1_1.GetChildMemberWithName("d"), value="4")
53+
check(field1_1.GetChildMemberWithName("e"), value="5")

0 commit comments

Comments
 (0)