Skip to content

Commit 8345786

Browse files
committed
[LLDB] Add support for Dictionary in embedded Swift
1 parent 5d31bb6 commit 8345786

File tree

7 files changed

+203
-50
lines changed

7 files changed

+203
-50
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,10 @@ class SwiftLanguageRuntime : public LanguageRuntime {
582582
llvm::Expected<const swift::reflection::TypeRef &>
583583
GetTypeRef(CompilerType type, TypeSystemSwiftTypeRef *module_holder);
584584

585+
/// Returns a non-null type system or an error.
586+
static llvm::Expected<TypeSystemSwiftTypeRefSP>
587+
GetReflectionTypeSystem(CompilerType for_type, ExecutionContext exe_ctx);
588+
585589
/// Ask Remote Mirrors for the type info about a Swift type.
586590
/// This will return a nullptr if the lookup fails.
587591
llvm::Expected<const swift::reflection::TypeInfo &>

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

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "lldb/ValueObject/ValueObjectCast.h"
3333
#include "lldb/ValueObject/ValueObjectMemory.h"
3434
#include "llvm/ADT/STLExtras.h"
35+
#include "llvm/Support/Casting.h"
3536

3637
#include "swift/AST/ASTContext.h"
3738
#include "swift/AST/ASTMangler.h"
@@ -791,11 +792,11 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
791792

792793
const unsigned success = 0;
793794
bool count_only = !visit_callback;
794-
auto ts_sp =
795-
m_type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwiftTypeRef>();
796-
if (!ts_sp)
797-
return llvm::createStringError("no type system");
798-
auto &ts = *ts_sp;
795+
auto ts_or_err =
796+
SwiftLanguageRuntime::GetReflectionTypeSystem(m_type, m_exe_ctx);
797+
if (!ts_or_err)
798+
return ts_or_err.takeError();
799+
auto &ts = *ts_or_err->get();
799800

800801
// Deal with the LLDB-only SILPackType variant.
801802
if (auto pack_type_info = ts.IsSILPackType(m_type)) {
@@ -3383,6 +3384,42 @@ SwiftLanguageRuntime::GetTypeRef(CompilerType type,
33833384
return type_ref_or_err;
33843385
}
33853386

3387+
llvm::Expected<TypeSystemSwiftTypeRefSP>
3388+
SwiftLanguageRuntime::GetReflectionTypeSystem(CompilerType for_type,
3389+
ExecutionContext exe_ctx) {
3390+
auto ts_sp = for_type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>();
3391+
if (!ts_sp)
3392+
return llvm::createStringError("not a Swift type");
3393+
3394+
// The TypeSystemSwiftTypeRefForExpressions doesn't have a SymbolFile,
3395+
// so any DWARF lookups for Embedded Swift fail.
3396+
//
3397+
// FIXME: It's unclear whether this is safe to do in a non-LTO Swift program.
3398+
if (auto *tr_ts =
3399+
llvm::dyn_cast_or_null<TypeSystemSwiftTypeRefForExpressions>(
3400+
ts_sp.get())) {
3401+
if (tr_ts->GetManglingFlavor(&exe_ctx) ==
3402+
swift::Mangle::ManglingFlavor::Embedded) {
3403+
if (auto *frame = exe_ctx.GetFramePtr()) {
3404+
auto &sc = frame->GetSymbolContext(eSymbolContextModule);
3405+
if (sc.module_sp) {
3406+
auto ts_or_err =
3407+
sc.module_sp->GetTypeSystemForLanguage(eLanguageTypeSwift);
3408+
if (!ts_or_err)
3409+
return ts_or_err.takeError();
3410+
if (auto *tr_ts =
3411+
llvm::dyn_cast_or_null<TypeSystemSwift>(ts_or_err->get()))
3412+
ts_sp = tr_ts->GetTypeSystemSwiftTypeRef();
3413+
}
3414+
}
3415+
}
3416+
}
3417+
auto tr_ts = ts_sp->GetTypeSystemSwiftTypeRef();
3418+
if (!tr_ts)
3419+
return llvm::createStringError("no Swift typesystem");
3420+
return tr_ts;
3421+
}
3422+
33863423
llvm::Expected<const swift::reflection::TypeInfo &>
33873424
SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo(
33883425
CompilerType type, ExecutionContextScope *exe_scope,
@@ -3393,14 +3430,17 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo(
33933430
"[SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo] Getting "
33943431
"type info for type: {0}",
33953432
type.GetMangledTypeName());
3396-
3397-
auto ts_sp = type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>();
3398-
if (!ts_sp)
3399-
return llvm::createStringError("not a Swift type");
3400-
auto tr_ts = ts_sp->GetTypeSystemSwiftTypeRef();
3401-
if (!tr_ts)
3402-
return llvm::createStringError("no Swift typesystem");
3403-
auto &ts = *tr_ts;
3433+
StackFrame *frame = nullptr;
3434+
ExecutionContext exe_ctx;
3435+
if (exe_scope) {
3436+
frame = exe_scope->CalculateStackFrame().get();
3437+
if (frame)
3438+
frame->CalculateExecutionContext(exe_ctx);
3439+
}
3440+
auto ts_or_err = GetReflectionTypeSystem(type, exe_ctx);
3441+
if (!ts_or_err)
3442+
return ts_or_err.takeError();
3443+
auto &ts = *ts_or_err->get();
34043444

34053445
// Resolve all type aliases.
34063446
type = type.GetCanonicalType();
@@ -3414,15 +3454,13 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo(
34143454
// Resolve all generic type parameters in the type for the current
34153455
// frame. Generic parameter binding has to happen in the scratch
34163456
// context.
3417-
ExecutionContext exe_ctx;
3418-
if (exe_scope)
3419-
if (StackFrame *frame = exe_scope->CalculateStackFrame().get()) {
3420-
frame->CalculateExecutionContext(exe_ctx);
3421-
auto bound_type_or_err = BindGenericTypeParameters(*frame, type);
3422-
if (!bound_type_or_err)
3423-
return bound_type_or_err.takeError();
3424-
type = *bound_type_or_err;
3425-
}
3457+
if (frame) {
3458+
frame->CalculateExecutionContext(exe_ctx);
3459+
auto bound_type_or_err = BindGenericTypeParameters(*frame, type);
3460+
if (!bound_type_or_err)
3461+
return bound_type_or_err.takeError();
3462+
type = *bound_type_or_err;
3463+
}
34263464

34273465
// BindGenericTypeParameters imports the type into the scratch
34283466
// context, but we need to resolve (any DWARF links in) the typeref
@@ -3438,33 +3476,9 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo(
34383476
if (!reflection_ctx)
34393477
return llvm::createStringError("no reflection context");
34403478

3441-
// The TypeSystemSwiftTypeRefForExpressions doesn't ve a SymbolFile,
3442-
// so any DWARF lookups for Embedded Swift fail.
3443-
//
3444-
// FIXME: It's unclear whether this is safe to do in a non-LTO Swift program.
3445-
if (llvm::isa<TypeSystemSwiftTypeRefForExpressions>(tr_ts.get()) &&
3446-
tr_ts->GetManglingFlavor(&exe_ctx) ==
3447-
swift::Mangle::ManglingFlavor::Embedded) {
3448-
if (auto frame_sp = exe_ctx.GetFrameSP()) {
3449-
auto &sc = frame_sp->GetSymbolContext(eSymbolContextModule);
3450-
if (sc.module_sp) {
3451-
auto ts_or_err =
3452-
sc.module_sp->GetTypeSystemForLanguage(eLanguageTypeSwift);
3453-
if (!ts_or_err)
3454-
return ts_or_err.takeError();
3455-
if (auto *tr_ts = llvm::dyn_cast_or_null<TypeSystemSwiftTypeRef>(
3456-
ts_or_err->get())) {
3457-
LLDBTypeInfoProvider provider(*this, *tr_ts);
3458-
return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider,
3459-
tr_ts->GetDescriptorFinder());
3460-
}
3461-
}
3462-
}
3463-
}
3464-
34653479
LLDBTypeInfoProvider provider(*this, ts);
34663480
return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider,
3467-
tr_ts->GetDescriptorFinder());
3481+
ts.GetDescriptorFinder());
34683482
}
34693483

34703484
bool SwiftLanguageRuntime::IsStoredInlineInBuffer(CompilerType type) {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ getTypeAndDie(TypeSystemSwiftTypeRef &ts,
160160
if (!dwarf)
161161
return {};
162162
TypeSP lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType());
163+
if (!lldb_type) {
164+
if (ts.ContainsBoundGenericType(type.GetOpaqueQualType())) {
165+
CompilerType generic_type = ts.MapOutOfContext(type.GetOpaqueQualType());
166+
lldb_type = ts.FindTypeInModule(generic_type.GetOpaqueQualType());
167+
}
168+
}
163169
if (!lldb_type) {
164170
std::tie(lldb_type, type) = DWARFASTParserSwift::ResolveTypeAlias(type);
165171
if (lldb_type) {

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

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,91 @@ CompilerType TypeSystemSwiftTypeRef::ApplySubstitutions(
12671267
return RemangleAsType(dem, type_node, flavor);
12681268
}
12691269

1270+
CompilerType
1271+
TypeSystemSwiftTypeRef::MapOutOfContext(lldb::opaque_compiler_type_t type) {
1272+
using namespace swift::Demangle;
1273+
Demangler dem;
1274+
const char *mangled_typename = AsMangledName(type);
1275+
auto flavor = SwiftLanguageRuntime::GetManglingFlavor(mangled_typename);
1276+
NodePointer type_node =
1277+
swift_demangle::GetDemangledTypeMangling(dem, mangled_typename);
1278+
if (!type_node)
1279+
return {};
1280+
1281+
// First perform a pre-order traversal to record the depths of the type
1282+
// parameters.
1283+
bool error = false;
1284+
unsigned depth = 0;
1285+
using ParamVector = llvm::SmallVector<std::pair<unsigned, unsigned>, 4>;
1286+
llvm::SmallDenseMap<NodePointer, ParamVector, 8> subs;
1287+
PreOrderTraversal(type_node, [&](NodePointer node) {
1288+
switch (node->getKind()) {
1289+
case Node::Kind::BoundGenericClass:
1290+
case Node::Kind::BoundGenericEnum:
1291+
case Node::Kind::BoundGenericFunction:
1292+
case Node::Kind::BoundGenericProtocol:
1293+
case Node::Kind::BoundGenericOtherNominalType:
1294+
case Node::Kind::BoundGenericStructure:
1295+
case Node::Kind::BoundGenericTypeAlias: {
1296+
if (node->getNumChildren() != 2) {
1297+
error = true;
1298+
return false;
1299+
}
1300+
NodePointer type_list =
1301+
swift_demangle::NodeAtPath(node->getChild(1), {Node::Kind::TypeList});
1302+
if (!type_list) {
1303+
error = true;
1304+
return false;
1305+
}
1306+
unsigned i = 0;
1307+
auto it = subs.insert({node, {}});
1308+
if (!it.second) {
1309+
error = true;
1310+
return false;
1311+
}
1312+
ParamVector &types = it.first->second;
1313+
for (NodePointer type : *type_list)
1314+
if (type && type->getKind() == Node::Kind::Type)
1315+
types.push_back({depth, i++});
1316+
1317+
depth += 1;
1318+
1319+
return true;
1320+
}
1321+
default:
1322+
return true;
1323+
}
1324+
});
1325+
if (error)
1326+
return {};
1327+
1328+
// Now perform a post-order traversal to substitute the nodes with the right
1329+
// depth.
1330+
type_node = Transform(dem, type_node, [&](NodePointer node) -> NodePointer {
1331+
auto it = subs.find(node);
1332+
if (it == subs.end())
1333+
return node;
1334+
ParamVector &types = it->second;
1335+
NodePointer remapped = dem.createNode(node->getKind());
1336+
remapped->addChild(node->getChild(0), dem);
1337+
NodePointer type_list = dem.createNode(Node::Kind::TypeList);
1338+
remapped->addChild(type_list, dem);
1339+
for (auto &type : types) {
1340+
NodePointer dgpt = dem.createNode(Node::Kind::DependentGenericParamType);
1341+
dgpt->addChild(dem.createNode(Node::Kind::Index, type.first), dem);
1342+
dgpt->addChild(dem.createNode(Node::Kind::Index, type.second), dem);
1343+
type_list->addChild(dgpt, dem);
1344+
}
1345+
for (auto &constraint : *node->getChild(1))
1346+
if (constraint->getKind() != Node::Kind::Type)
1347+
type_list->addChild(constraint, dem);
1348+
1349+
return remapped;
1350+
});
1351+
1352+
return RemangleAsType(dem, type_node, flavor);
1353+
}
1354+
12701355
bool TypeSystemSwiftTypeRef::IsBoundGenericAliasType(
12711356
lldb::opaque_compiler_type_t type) {
12721357
using namespace swift::Demangle;
@@ -1283,6 +1368,39 @@ bool TypeSystemSwiftTypeRef::IsBoundGenericAliasType(
12831368
return node->getKind() == Node::Kind::BoundGenericTypeAlias;
12841369
}
12851370

1371+
static bool ContainsBoundGenericTypeNode(swift::Demangle::NodePointer node) {
1372+
if (!node)
1373+
return false;
1374+
switch (node->getKind()) {
1375+
case Node::Kind::BoundGenericClass:
1376+
case Node::Kind::BoundGenericEnum:
1377+
case Node::Kind::BoundGenericFunction:
1378+
case Node::Kind::BoundGenericProtocol:
1379+
case Node::Kind::BoundGenericOtherNominalType:
1380+
case Node::Kind::BoundGenericTypeAlias:
1381+
case Node::Kind::BoundGenericStructure:
1382+
return true;
1383+
default:
1384+
if (NodePointer parent = GetParentNode(node))
1385+
return ContainsBoundGenericTypeNode(parent);
1386+
return false;
1387+
}
1388+
}
1389+
1390+
bool TypeSystemSwiftTypeRef::ContainsBoundGenericType(
1391+
lldb::opaque_compiler_type_t type) {
1392+
using namespace swift::Demangle;
1393+
Demangler dem;
1394+
const char *mangled_typename = AsMangledName(type);
1395+
1396+
NodePointer node =
1397+
swift_demangle::GetDemangledTypeMangling(dem, mangled_typename);
1398+
if (!node || node->getKind() != Node::Kind::Type || !node->hasChildren())
1399+
return false;
1400+
node = node->getChild(0);
1401+
return ContainsBoundGenericTypeNode(node);
1402+
}
1403+
12861404
std::optional<TypeSystemSwift::TupleElement>
12871405
TypeSystemSwiftTypeRef::GetTupleElement(lldb::opaque_compiler_type_t type,
12881406
size_t idx) {
@@ -2632,7 +2750,9 @@ TypeSystemSwiftTypeRef::FindTypeInModule(opaque_compiler_type_t opaque_type) {
26322750

26332751
TypeResults results;
26342752
M->FindTypes(query, results);
2635-
return results.GetFirstType();
2753+
if (results.Done(query))
2754+
return results.GetFirstType();
2755+
return {};
26362756
}
26372757

26382758
// Tests

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,13 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
140140

141141
CompilerType GetParentType(lldb::opaque_compiler_type_t type);
142142
std::vector<std::vector<CompilerType>>
143+
/// Extract the substitutions from a bound generic type.
143144
GetSubstitutions(lldb::opaque_compiler_type_t type);
145+
/// Apply substitutions to a bound generic type that is mapped out of context.
144146
CompilerType ApplySubstitutions(lldb::opaque_compiler_type_t type,
145147
std::vector<std::vector<CompilerType>> subs);
148+
/// Apply substitutions to a bound generic type that is mapped out of context.
149+
CompilerType MapOutOfContext(lldb::opaque_compiler_type_t type);
146150

147151
Module *GetModule() const { return m_module; }
148152

@@ -366,6 +370,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
366370
/// Determine whether \p type is a protocol.
367371
bool IsExistentialType(lldb::opaque_compiler_type_t type);
368372
bool IsBoundGenericAliasType(lldb::opaque_compiler_type_t type);
373+
bool ContainsBoundGenericType(lldb::opaque_compiler_type_t type);
369374

370375
/// Recursively transform the demangle tree starting a \p node by
371376
/// doing a post-order traversal and replacing each node with
@@ -389,6 +394,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
389394

390395
/// A left-to-right preorder traversal. Don't visit children if
391396
/// visitor returns false.
397+
/// The NodePointer passed to \p fn is guaranteed to be non-null.
392398
static void
393399
PreOrderTraversal(swift::Demangle::NodePointer node,
394400
std::function<bool(swift::Demangle::NodePointer)>);

lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from lldbsuite.test.decorators import *
44
import lldbsuite.test.lldbutil as lldbutil
55

6-
@skipIf(bugnumber = "rdar://159531308")
76
class TestSwiftEmbeddedFrameVariable(TestBase):
87

98
@skipUnlessDarwin
@@ -32,7 +31,7 @@ def implementation(self, ast):
3231
if self.TraceOn():
3332
self.expect("log enable lldb types")
3433
self.expect("frame variable")
35-
34+
3635
alias1 = frame.FindVariable("alias1")
3736
field = alias1.GetChildMemberWithName("t")
3837
lldbutil.check_variable(self, field, False, value='1')
@@ -262,3 +261,6 @@ def implementation(self, ast):
262261

263262
string = frame.FindVariable("string")
264263
lldbutil.check_variable(self, string, False, summary='"Hello"')
264+
265+
dictionary = frame.FindVariable("dict")
266+
lldbutil.check_variable(self, dictionary, False, summary='4 key/value pairs')

lldb/test/API/lang/swift/embedded/frame_variable/main.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ func g() {
194194
let functionType = FunctionType()
195195
let innerFunctionType = InnerFunctionType()
196196
var inlineArray: InlineArray<4, Int> = [1, 2, 3, 4]
197+
var dict: Dictionary<Int, Int> = [1:4, 2:3, 3:2, 4:1]
197198

198199
let dummy = A()
199200
let string = StaticString("Hello")

0 commit comments

Comments
 (0)