Skip to content

Commit f7b9123

Browse files
committed
Support nested generic type aliases (and thus Swift.Array) in Embedded Swift
In order to format a Swift.Array in Swift it is necessary to properly resolve type aliases to generic types from DWARF. This patch adds support for properly generic type aliases in and out of context when reconstructing them from DWARF. rdar://159429896
1 parent a45f19c commit f7b9123

File tree

9 files changed

+472
-92
lines changed

9 files changed

+472
-92
lines changed

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

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "LLDBMemoryReader.h"
14+
#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h"
1415
#include "ReflectionContextInterface.h"
1516
#include "SwiftLanguageRuntime.h"
1617
#include "SwiftMetadataCache.h"
@@ -607,13 +608,14 @@ std::optional<uint64_t> SwiftLanguageRuntime::GetMemberVariableOffset(
607608
namespace {
608609

609610
CompilerType GetTypeFromTypeRef(TypeSystemSwiftTypeRef &ts,
610-
const swift::reflection::TypeRef *type_ref) {
611+
const swift::reflection::TypeRef *type_ref,
612+
swift::Mangle::ManglingFlavor flavor) {
611613
if (!type_ref)
612614
return {};
613615
swift::Demangle::Demangler dem;
614616
swift::Demangle::NodePointer node = type_ref->getDemangling(dem);
615617
// TODO: the mangling flavor should come from the TypeRef.
616-
return ts.RemangleAsType(dem, node, ts.GetManglingFlavor());
618+
return ts.RemangleAsType(dem, node, flavor);
617619
}
618620

619621
struct ExistentialSyntheticChild {
@@ -627,7 +629,8 @@ struct ExistentialSyntheticChild {
627629
llvm::SmallVector<ExistentialSyntheticChild, 4>
628630
GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts,
629631
const swift::reflection::TypeRef *tr,
630-
const swift::reflection::TypeInfo *ti) {
632+
const swift::reflection::TypeInfo *ti,
633+
swift::Mangle::ManglingFlavor flavor) {
631634
llvm::SmallVector<ExistentialSyntheticChild, 4> children;
632635
auto *protocol_composition_tr =
633636
llvm::dyn_cast<swift::reflection::ProtocolCompositionTypeRef>(tr);
@@ -641,7 +644,8 @@ GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts,
641644
children.push_back({"object", [=]() {
642645
if (auto *super_class_tr =
643646
protocol_composition_tr->getSuperclass())
644-
return GetTypeFromTypeRef(*ts_sp, super_class_tr);
647+
return GetTypeFromTypeRef(*ts_sp, super_class_tr,
648+
flavor);
645649
else
646650
return rti ? ts_sp->GetBuiltinUnknownObjectType()
647651
: ts_sp->GetBuiltinRawPointerType();
@@ -652,9 +656,9 @@ GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts,
652656
for (unsigned i = 1; i < fields.size(); ++i) {
653657
TypeSystemSwiftTypeRefSP ts_sp = ts.GetTypeSystemSwiftTypeRef();
654658
auto *type_ref = fields[i].TR;
655-
children.push_back({fields[i].Name, [=]() {
656-
return GetTypeFromTypeRef(*ts_sp, type_ref);
657-
}});
659+
children.push_back(
660+
{fields[i].Name,
661+
[=]() { return GetTypeFromTypeRef(*ts_sp, type_ref, flavor); }});
658662
}
659663
}
660664
}
@@ -702,12 +706,20 @@ CompilerType GetTypedefedTypeRecursive(CompilerType type) {
702706
class SwiftRuntimeTypeVisitor {
703707
SwiftLanguageRuntime &m_runtime;
704708
ExecutionContext m_exe_ctx;
709+
swift::Mangle::ManglingFlavor m_flavor =
710+
swift::Mangle::ManglingFlavor::Default;
705711
CompilerType m_type;
706712
ValueObject *m_valobj = nullptr;
707713
bool m_hide_superclass = false;
708714
bool m_include_clang_types = false;
709715
bool m_visit_superclass = false;
710716

717+
void SetFlavor() {
718+
if (auto ts_sp =
719+
m_type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwiftTypeRef>())
720+
m_flavor = ts_sp->GetManglingFlavor(&m_exe_ctx);
721+
}
722+
711723
public:
712724
struct ChildInfo {
713725
uint32_t byte_size = 0;
@@ -732,6 +744,7 @@ class SwiftRuntimeTypeVisitor {
732744
: m_runtime(runtime), m_type(type), m_valobj(valobj) {
733745
if (valobj)
734746
m_exe_ctx = valobj->GetExecutionContextRef();
747+
SetFlavor();
735748
}
736749
SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type,
737750
ExecutionContextScope *exe_scope,
@@ -740,6 +753,7 @@ class SwiftRuntimeTypeVisitor {
740753
m_include_clang_types(include_clang_types) {
741754
if (exe_scope)
742755
exe_scope->CalculateExecutionContext(m_exe_ctx);
756+
SetFlavor();
743757
}
744758
SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type,
745759
ExecutionContext *exe_ctx, bool hide_superclass,
@@ -749,6 +763,7 @@ class SwiftRuntimeTypeVisitor {
749763
m_visit_superclass(visit_superclass) {
750764
if (exe_ctx)
751765
m_exe_ctx = *exe_ctx;
766+
SetFlavor();
752767
}
753768
llvm::Error VisitAllChildren(VisitCallback callback) {
754769
return VisitImpl({}, callback).takeError();
@@ -871,7 +886,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
871886
field_type = tuple->element_type;
872887
else {
873888
if (!field_type)
874-
field_type = GetTypeFromTypeRef(ts, field.TR);
889+
field_type = GetTypeFromTypeRef(ts, field.TR, m_flavor);
875890
}
876891
auto get_info = [&]() -> llvm::Expected<ChildInfo> {
877892
ChildInfo child;
@@ -968,7 +983,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
968983
if (rti->getRecordKind() ==
969984
swift::reflection::RecordKind::ClassExistential) {
970985
// Compatibility with SwiftASTContext.
971-
auto children = GetExistentialSyntheticChildren(ts, tr, ti);
986+
auto children = GetExistentialSyntheticChildren(ts, tr, ti, m_flavor);
972987
if (count_only)
973988
return children.size();
974989
auto visit_existential = [&](ExistentialSyntheticChild c, unsigned idx) {
@@ -1019,7 +1034,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
10191034
llvm::dyn_cast_or_null<swift::reflection::ReferenceTypeInfo>(ti)) {
10201035
// Is this an Existential?
10211036
unsigned i = 0;
1022-
auto children = GetExistentialSyntheticChildren(ts, tr, ti);
1037+
auto children = GetExistentialSyntheticChildren(ts, tr, ti, m_flavor);
10231038
if (children.size()) {
10241039
if (count_only)
10251040
return children.size();
@@ -1109,7 +1124,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
11091124
if (auto *super_tr = reflection_ctx->LookupSuperclass(
11101125
*tr, ts.GetDescriptorFinder()))
11111126
if (auto error = visit_callback(
1112-
GetTypeFromTypeRef(ts, super_tr), depth,
1127+
GetTypeFromTypeRef(ts, super_tr, m_flavor), depth,
11131128
[]() -> std::string { return "<base class>"; },
11141129
[]() -> llvm::Expected<ChildInfo> {
11151130
return ChildInfo();
@@ -1143,8 +1158,9 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
11431158
return ChildInfo();
11441159
};
11451160

1146-
if (auto error = visit_callback(GetTypeFromTypeRef(ts, super_tr), 0,
1147-
get_name, get_info))
1161+
if (auto error =
1162+
visit_callback(GetTypeFromTypeRef(ts, super_tr, m_flavor), 0,
1163+
get_name, get_info))
11481164
return error;
11491165
}
11501166

@@ -1263,7 +1279,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
12631279
return success;
12641280
}
12651281

1266-
CompilerType super_type = GetTypeFromTypeRef(ts, type_ref);
1282+
CompilerType super_type = GetTypeFromTypeRef(ts, type_ref, m_flavor);
12671283
auto get_name = [&]() -> std::string {
12681284
auto child_name = super_type.GetTypeName().GetStringRef().str();
12691285
// FIXME: This should be fixed in GetDisplayTypeName instead!
@@ -1471,6 +1487,8 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) {
14711487
if (!ti_or_err)
14721488
return ti_or_err.takeError();
14731489
auto *ti = &*ti_or_err;
1490+
auto flavor =
1491+
SwiftLanguageRuntime::GetManglingFlavor(enum_type.GetMangledTypeName());
14741492

14751493
auto project_indirect_enum =
14761494
[&](uint64_t offset, std::string name) -> llvm::Expected<ValueObjectSP> {
@@ -1496,13 +1514,14 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) {
14961514
auto &field = rti->getFields()[0];
14971515
auto *type_ref = field.TR;
14981516
payload += field.Offset;
1499-
payload_type = GetTypeFromTypeRef(ts, type_ref);
1517+
payload_type = GetTypeFromTypeRef(ts, type_ref, flavor);
15001518
break;
15011519
}
15021520
case swift::reflection::RecordKind::Tuple: {
15031521
std::vector<TypeSystemSwift::TupleElement> elts;
15041522
for (auto &field : rti->getFields())
1505-
elts.emplace_back(ConstString(), GetTypeFromTypeRef(ts, field.TR));
1523+
elts.emplace_back(ConstString(),
1524+
GetTypeFromTypeRef(ts, field.TR, flavor));
15061525
payload_type = ts.CreateTupleType(elts);
15071526
break;
15081527
}
@@ -1571,7 +1590,7 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) {
15711590
if (is_indirect_enum)
15721591
return project_indirect_enum(field_info.Offset, field_info.Name);
15731592

1574-
CompilerType projected_type = GetTypeFromTypeRef(ts, field_info.TR);
1593+
CompilerType projected_type = GetTypeFromTypeRef(ts, field_info.TR, flavor);
15751594
if (field_info.Offset != 0) {
15761595
assert(false);
15771596
return llvm::createStringError("enum with unexpected offset");
@@ -1679,7 +1698,9 @@ CompilerType SwiftLanguageRuntime::GetBaseClass(CompilerType class_ty) {
16791698
}
16801699
auto *super_tr = reflection_ctx->LookupSuperclass(
16811700
*type_ref_or_err, tr_ts->GetDescriptorFinder());
1682-
return GetTypeFromTypeRef(*tr_ts, super_tr);
1701+
auto flavor =
1702+
SwiftLanguageRuntime::GetManglingFlavor(class_ty.GetMangledTypeName());
1703+
return GetTypeFromTypeRef(*tr_ts, super_tr, flavor);
16831704
}
16841705

16851706
bool SwiftLanguageRuntime::ForEachSuperClassType(
@@ -3399,9 +3420,9 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo(
33993420
// Resolve all generic type parameters in the type for the current
34003421
// frame. Generic parameter binding has to happen in the scratch
34013422
// context.
3423+
ExecutionContext exe_ctx;
34023424
if (exe_scope)
34033425
if (StackFrame *frame = exe_scope->CalculateStackFrame().get()) {
3404-
ExecutionContext exe_ctx;
34053426
frame->CalculateExecutionContext(exe_ctx);
34063427
auto bound_type_or_err = BindGenericTypeParameters(*frame, type);
34073428
if (!bound_type_or_err)
@@ -3423,6 +3444,30 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo(
34233444
if (!reflection_ctx)
34243445
return llvm::createStringError("no reflection context");
34253446

3447+
// The TypeSystemSwiftTypeRefForExpressions doesn't ve a SymbolFile,
3448+
// so any DWARF lookups for Embedded Swift fail.
3449+
//
3450+
// FIXME: It's unclear whether this is safe to do in a non-LTO Swift program.
3451+
if (llvm::isa<TypeSystemSwiftTypeRefForExpressions>(tr_ts.get()) &&
3452+
tr_ts->GetManglingFlavor(&exe_ctx) ==
3453+
swift::Mangle::ManglingFlavor::Embedded) {
3454+
if (auto frame_sp = exe_ctx.GetFrameSP()) {
3455+
auto &sc = frame_sp->GetSymbolContext(eSymbolContextModule);
3456+
if (sc.module_sp) {
3457+
auto ts_or_err =
3458+
sc.module_sp->GetTypeSystemForLanguage(eLanguageTypeSwift);
3459+
if (!ts_or_err)
3460+
return ts_or_err.takeError();
3461+
if (auto *tr_ts = llvm::dyn_cast_or_null<TypeSystemSwiftTypeRef>(
3462+
ts_or_err->get())) {
3463+
LLDBTypeInfoProvider provider(*this, *tr_ts);
3464+
return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider,
3465+
tr_ts->GetDescriptorFinder());
3466+
}
3467+
}
3468+
}
3469+
}
3470+
34263471
LLDBTypeInfoProvider provider(*this, ts);
34273472
return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider,
34283473
tr_ts->GetDescriptorFinder());
@@ -3561,7 +3606,7 @@ SwiftLanguageRuntime::ResolveTypeAlias(CompilerType alias) {
35613606
type_ref = &*type_ref_or_err;
35623607
}
35633608

3564-
CompilerType resolved = GetTypeFromTypeRef(*tr_ts, type_ref);
3609+
CompilerType resolved = GetTypeFromTypeRef(*tr_ts, type_ref, flavor);
35653610
LLDB_LOG(GetLog(LLDBLog::Types),
35663611
"Resolved type alias {0} = {1} using reflection metadata.",
35673612
alias.GetMangledTypeName(), resolved.GetMangledTypeName());

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,9 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
173173
if (TypeSP desugared_type = get_type(die)) {
174174
// For a typedef, store the once desugared type as the name.
175175
CompilerType type = desugared_type->GetForwardCompilerType();
176-
if (auto swift_ast_ctx =
176+
if (auto ts =
177177
type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>())
178-
preferred_name =
179-
swift_ast_ctx->GetMangledTypeName(type.GetOpaqueQualType());
178+
preferred_name = ts->GetMangledTypeName(type.GetOpaqueQualType());
180179
}
181180
}
182181
}

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class DWARFASTParserSwift : public lldb_private::plugin::dwarf::DWARFASTParser,
3737

3838
virtual ~DWARFASTParserSwift();
3939

40+
static std::pair<lldb::TypeSP, lldb_private::CompilerType>
41+
ResolveTypeAlias(lldb_private::CompilerType alias);
4042
lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
4143
const DWARFDIE &die,
4244
bool *type_is_new_ptr) override;

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,77 @@ findUnsubstitutedGenericTypeAndDIE(TypeSystemSwiftTypeRef &ts,
5656
ts.GetTypeFromMangledTypename(ConstString(mangled_name));
5757
return {{unsubstituted_type, unsubstituted_die}};
5858
}
59+
60+
lldb_private::CompilerType static MapTypeIntoContext(
61+
TypeSystemSwiftTypeRef &ts, lldb_private::CompilerType other,
62+
lldb_private::CompilerType type) {
63+
return ts.ApplySubstitutions(type.GetOpaqueQualType(),
64+
ts.GetSubstitutions(other.GetOpaqueQualType()));
65+
}
66+
67+
std::pair<lldb::TypeSP, lldb_private::CompilerType>
68+
DWARFASTParserSwift::ResolveTypeAlias(lldb_private::CompilerType alias) {
69+
if (!alias)
70+
return {};
71+
auto ts_sp = alias.GetTypeSystem().dyn_cast_or_null<TypeSystemSwiftTypeRef>();
72+
if (!ts_sp)
73+
return {};
74+
auto &ts = *ts_sp;
75+
auto *dwarf = llvm::dyn_cast_or_null<SymbolFileDWARF>(ts.GetSymbolFile());
76+
if (!dwarf)
77+
return {};
78+
79+
// Type aliases are (for LLVM implementation reasons) using the
80+
// DW_AT_name as linkage name, so they can't be looked up by base
81+
// name. This should be fixed.
82+
// Meanwhile, instead find them inside their parent type.
83+
CompilerType parent_ctx = ts.GetParentType(alias.GetOpaqueQualType());
84+
if (!parent_ctx)
85+
return {};
86+
87+
DWARFDIE parent_die;
88+
if (TypeSP parent_type =
89+
ts.FindTypeInModule(parent_ctx.GetOpaqueQualType())) {
90+
parent_die = dwarf->GetDIE(parent_type->GetID());
91+
auto unsubstituted_pair =
92+
findUnsubstitutedGenericTypeAndDIE(ts, parent_die);
93+
if (unsubstituted_pair)
94+
parent_die = unsubstituted_pair->second;
95+
}
96+
if (!parent_die)
97+
return {};
98+
std::string alias_name = ts.GetBaseName(alias.GetOpaqueQualType());
99+
for (DWARFDIE child_die : parent_die.children()) {
100+
auto tag = child_die.Tag();
101+
if (tag == DW_TAG_member)
102+
continue;
103+
std::string base_name;
104+
const auto *name =
105+
child_die.GetAttributeValueAsString(llvm::dwarf::DW_AT_name, "");
106+
if (name && *name == '$') {
107+
CompilerType candidate = ts.GetTypeFromMangledTypename(ConstString(name));
108+
base_name = ts.GetBaseName(candidate.GetOpaqueQualType());
109+
} else {
110+
base_name = name;
111+
}
112+
if (base_name != alias_name)
113+
continue;
114+
115+
// Follow the typedef.
116+
auto *dwarf_parser = ts.GetDWARFParser();
117+
if (!dwarf_parser)
118+
return {};
119+
Type *t = dwarf_parser->GetTypeForDIE(child_die);
120+
if (!t)
121+
return {};
122+
CompilerType cty = t->GetForwardCompilerType();
123+
if (ts.IsMeaninglessWithoutDynamicResolution(cty.GetOpaqueQualType()))
124+
return {t->shared_from_this(), MapTypeIntoContext(ts, alias, cty)};
125+
return {t->shared_from_this(), cty};
126+
}
127+
return {};
128+
}
129+
59130
/// Given a type system and a typeref, return the compiler type and die of the
60131
/// type that matches that mangled name, looking up the in the type system's
61132
/// module's debug information.
@@ -79,10 +150,17 @@ getTypeAndDie(TypeSystemSwiftTypeRef &ts,
79150
auto *dwarf = llvm::cast_or_null<SymbolFileDWARF>(ts.GetSymbolFile());
80151
if (!dwarf)
81152
return {};
82-
auto lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType());
153+
TypeSP lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType());
83154
if (!lldb_type) {
84-
// TODO: for embedded Swift this is fine but consult other modules here for
85-
// general case?
155+
std::tie(lldb_type, type) = DWARFASTParserSwift::ResolveTypeAlias(type);
156+
if (lldb_type) {
157+
auto die = dwarf->GetDIE(lldb_type->GetID());
158+
return {{type, die}};
159+
}
160+
}
161+
if (!lldb_type) {
162+
// TODO: for embedded Swift this is fine but consult other modules
163+
// here for general case?
86164
LLDB_LOGV(GetLog(LLDBLog::Types), "Could not find type {0} in module",
87165
type.GetMangledTypeName());
88166
return {};
@@ -375,7 +453,6 @@ DWARFASTParserSwift::getFieldDescriptor(const swift::reflection::TypeRef *TR) {
375453
lldb_private::AutoBool::False &&
376454
"Full DWARF debugging for Swift is disabled!");
377455

378-
379456
auto pair = getTypeAndDie(m_swift_typesystem, TR);
380457
if (!pair)
381458
return nullptr;

0 commit comments

Comments
 (0)