Skip to content

Commit 8b29717

Browse files
committed
Support variadic generics in LLDB.
This implements dynamic type resolution for pack expansion types by walking the metadata and replacing them with an "expanded" SIL pack type that contains a tuple type in which all generic parameters from type packs have been substituted with the concrete types from the type pack(s). SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex() recognizes these expanded SIL pack types and performs the appropriate offset computation. rdar://104842059
1 parent aced64e commit 8b29717

File tree

12 files changed

+811
-15
lines changed

12 files changed

+811
-15
lines changed

lldb/include/lldb/lldb-enumerations.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,8 @@ FLAGS_ENUM(TypeFlags){
11031103
eTypeIsTuple = (1u << 26),
11041104
eTypeIsMetatype = (1u << 27),
11051105
eTypeHasUnboundGeneric = (1u << 28),
1106-
eTypeHasDynamicSelf = (1u << 29)};
1106+
eTypeHasDynamicSelf = (1u << 29),
1107+
eTypeIsPack = (1u << 30)};
11071108

11081109
FLAGS_ENUM(CommandFlags){
11091110
/// eCommandRequiresTarget

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,51 @@ class SwiftLanguageRuntime : public LanguageRuntime {
267267
const SymbolContext &sc,
268268
llvm::DenseMap<ArchetypePath, llvm::StringRef> &dict);
269269

270+
/// Invoke callback for each DependentGenericParamType.
271+
static void
272+
ForEachGenericParameter(swift::Demangle::NodePointer node,
273+
std::function<void(unsigned, unsigned)> callback);
274+
275+
/// One element for each value pack / pack expansion in the signature.
276+
struct GenericSignature {
277+
/// Represents a single generic parameter.
278+
struct GenericParam {
279+
unsigned depth;
280+
unsigned index;
281+
/// A vector of |generic_params| bits, indicating which other
282+
/// generic_params share the same shape.
283+
llvm::BitVector same_shape;
284+
GenericParam(unsigned d, unsigned i, unsigned nparams)
285+
: depth(d), index(i), same_shape(nparams) {}
286+
};
287+
288+
struct PackExpansion {
289+
llvm::BitVector generic_params;
290+
ConstString mangled_type;
291+
unsigned shape;
292+
PackExpansion(unsigned nparams, unsigned shape)
293+
: generic_params(nparams), shape(shape) {}
294+
};
295+
296+
llvm::SmallVector<GenericParam, 4> generic_params;
297+
/// Indices of the shape of the pack expansions.
298+
llvm::SmallVector<PackExpansion> pack_expansions;
299+
300+
llvm::SmallVector<unsigned, 4> count_for_value_pack;
301+
llvm::SmallVector<unsigned, 4> count_for_type_pack;
302+
303+
unsigned GetNumValuePacks() { return count_for_value_pack.size(); }
304+
unsigned GetNumTypePacks() { return count_for_type_pack.size(); }
305+
unsigned GetCountForValuePack(unsigned i) {
306+
return count_for_value_pack[i];
307+
}
308+
unsigned GetCountForTypePack(unsigned i) { return count_for_type_pack[i]; }
309+
};
310+
/// Extract the generic signature out of a mangled Swift function name.
311+
static llvm::Optional<GenericSignature>
312+
GetGenericSignature(llvm::StringRef function_name,
313+
TypeSystemSwiftTypeRef &ts);
314+
270315
/// Using the generic type parameters of \p stack_frame return a
271316
/// version of \p base_type that replaces all generic type
272317
/// parameters with bound generic types. If a generic type parameter

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

Lines changed: 272 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,11 @@ SwiftLanguageRuntimeImpl::GetNumChildren(CompilerType type,
995995
if (!ts)
996996
return {};
997997

998+
// Deal with the LLDB-only SILPackType variant.
999+
if (auto pack_type = ts->IsSILPackType(type))
1000+
if (pack_type->expanded)
1001+
return pack_type->count;
1002+
9981003
// Try the static type metadata.
9991004
const swift::reflection::TypeRef *tr = nullptr;
10001005
auto *ti = GetSwiftRuntimeTypeInfo(type, exe_scope, &tr);
@@ -1319,6 +1324,26 @@ CompilerType SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex(
13191324
if (!ts)
13201325
return {};
13211326

1327+
ExecutionContext exe_ctx;
1328+
if (valobj)
1329+
exe_ctx = valobj->GetExecutionContextRef();
1330+
1331+
// Deal with the LLDB-only SILPackType variant.
1332+
if (auto pack_element_type = ts->GetSILPackElementAtIndex(type, idx)) {
1333+
llvm::raw_string_ostream os(child_name);
1334+
os << '.' << idx;
1335+
child_byte_size =
1336+
GetBitSize(pack_element_type, exe_ctx.GetBestExecutionContextScope())
1337+
.getValueOr(0);
1338+
int stack_dir = -1;
1339+
child_byte_offset = ts->GetPointerByteSize() * idx * stack_dir;
1340+
child_bitfield_bit_size = 0;
1341+
child_bitfield_bit_offset = 0;
1342+
child_is_base_class = false;
1343+
child_is_deref_of_parent = true;
1344+
return pack_element_type;
1345+
}
1346+
13221347
// The actual conversion from the FieldInfo record.
13231348
auto get_from_field_info =
13241349
[&](const swift::reflection::FieldInfo &field,
@@ -1345,10 +1370,6 @@ CompilerType SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex(
13451370
};
13461371

13471372
// Try the static type metadata.
1348-
ExecutionContext exe_ctx;
1349-
if (valobj)
1350-
exe_ctx = valobj->GetExecutionContextRef();
1351-
13521373
auto *ti =
13531374
GetSwiftRuntimeTypeInfo(type, exe_ctx.GetBestExecutionContextScope());
13541375
if (!ti)
@@ -1599,6 +1620,247 @@ bool SwiftLanguageRuntime::IsSelf(Variable &variable) {
15991620
node_ptr->getKind() == swift::Demangle::Node::Kind::Allocator;
16001621
}
16011622

1623+
/// Strip off SILPack(In)Direct from a mangled type name.
1624+
static ConstString unwrapSILPackType(ConstString mangledName,
1625+
swift::Demangle::Demangler &demangler,
1626+
TypeSystemSwiftTypeRef &ts,
1627+
bool &indirect) {
1628+
swift::Demangle::Context dem;
1629+
auto node = dem.demangleSymbolAsNode(mangledName.GetStringRef());
1630+
if (!node || node->getKind() != swift::Demangle::Node::Kind::Global)
1631+
return mangledName;
1632+
if (node->getNumChildren() != 1)
1633+
return mangledName;
1634+
node = node->getChild(0);
1635+
if (!node || node->getKind() != swift::Demangle::Node::Kind::TypeMangling)
1636+
return mangledName;
1637+
if (node->getNumChildren() != 1)
1638+
return mangledName;
1639+
node = node->getChild(0);
1640+
if (!node || node->getKind() != swift::Demangle::Node::Kind::Type)
1641+
return mangledName;
1642+
if (node->getNumChildren() != 1)
1643+
return mangledName;
1644+
node = node->getChild(0);
1645+
if (!node)
1646+
return mangledName;
1647+
1648+
indirect = false;
1649+
if (node->getKind() == swift::Demangle::Node::Kind::SILPackIndirect)
1650+
indirect = true;
1651+
if (node->getKind() != swift::Demangle::Node::Kind::SILPackIndirect &&
1652+
node->getKind() != swift::Demangle::Node::Kind::SILPackDirect)
1653+
return mangledName;
1654+
1655+
if (node->getNumChildren() != 1)
1656+
return mangledName;
1657+
node = node->getChild(0);
1658+
1659+
return ts.RemangleAsType(demangler, node).GetMangledTypeName();
1660+
}
1661+
1662+
bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Pack(
1663+
ValueObject &in_value, CompilerType pack_type,
1664+
lldb::DynamicValueType use_dynamic, TypeAndOrName &pack_type_or_name,
1665+
Address &address) {
1666+
Log *log(GetLog(LLDBLog::Types));
1667+
auto *reflection_ctx = GetReflectionContext();
1668+
if (!reflection_ctx)
1669+
return false;
1670+
1671+
// Return a tuple type, with one element per pack element and its
1672+
// type has all DependentGenericParamType that appear in type packs
1673+
// substituted.
1674+
1675+
StackFrameSP frame = in_value.GetExecutionContextRef().GetFrameSP();
1676+
if (!frame)
1677+
return false;
1678+
ConstString func_name = frame->GetSymbolContext(eSymbolContextFunction)
1679+
.GetFunctionName(Mangled::ePreferMangled);
1680+
1681+
// Extract the generic signature from the function symbol.
1682+
auto ts =
1683+
pack_type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwiftTypeRef>();
1684+
if (!ts)
1685+
return false;
1686+
auto signature =
1687+
SwiftLanguageRuntime::GetGenericSignature(func_name.GetStringRef(), *ts);
1688+
if (!signature) {
1689+
LLDB_LOG(log, "cannot decode pack_expansion type: failed to decode generic "
1690+
"signature from function name");
1691+
return false;
1692+
}
1693+
// This type has already been resolved?
1694+
if (auto info = ts->IsSILPackType(pack_type))
1695+
if (info->expanded)
1696+
return false;
1697+
1698+
bool indirect = false;
1699+
swift::Demangle::Demangler dem;
1700+
ConstString mangled_pack_type = pack_type.GetMangledTypeName();
1701+
mangled_pack_type = unwrapSILPackType(mangled_pack_type, dem, *ts, indirect);
1702+
1703+
// Find pack_type in the pack_expansions.
1704+
unsigned i = 0;
1705+
Target &target = m_process.GetTarget();
1706+
size_t ptr_size = m_process.GetAddressByteSize();
1707+
SwiftLanguageRuntime::GenericSignature::PackExpansion *pack_expansion =
1708+
nullptr;
1709+
for (auto &pe : signature->pack_expansions) {
1710+
if (pe.mangled_type == mangled_pack_type) {
1711+
pack_expansion = &pe;
1712+
break;
1713+
}
1714+
++i;
1715+
}
1716+
if (!pack_expansion) {
1717+
LLDB_LOGF(log, "cannot decode pack_expansion type: failed to find a "
1718+
"matching type in the function signature");
1719+
return false;
1720+
}
1721+
1722+
// Extract the count.
1723+
llvm::SmallString<16> buf;
1724+
llvm::raw_svector_ostream os(buf);
1725+
os << "$pack_count_" << signature->GetCountForValuePack(i);
1726+
StringRef count_var = os.str();
1727+
llvm::Optional<lldb::addr_t> count =
1728+
GetTypeMetadataForTypeNameAndFrame(count_var, *frame);
1729+
if (!count) {
1730+
LLDB_LOGF(log,
1731+
"cannot decode pack_expansion type: failed to find count "
1732+
"argument \"%s\" in frame",
1733+
count_var.str().c_str());
1734+
return false;
1735+
}
1736+
1737+
// Extract the metadata for the type packs in this value pack.
1738+
llvm::SmallDenseMap<std::pair<unsigned, unsigned>, lldb::addr_t> type_packs;
1739+
swift::Demangle::NodePointer dem_pack_type =
1740+
dem.demangleSymbol(mangled_pack_type.GetStringRef());
1741+
auto shape = signature->generic_params[pack_expansion->shape];
1742+
// Filter out all type packs in this value pack.
1743+
bool error = false;
1744+
ForEachGenericParameter(dem_pack_type, [&](unsigned depth, unsigned index) {
1745+
if (type_packs.count({depth, index}))
1746+
return;
1747+
for (auto p : shape.same_shape.set_bits()) {
1748+
// If a generic parameter that shows up in the
1749+
// pack_expansion has the same shape as the pack expansion
1750+
// it's a type pack.
1751+
auto &generic_param = signature->generic_params[p];
1752+
if (generic_param.depth == depth && generic_param.index == index) {
1753+
llvm::SmallString<16> buf;
1754+
llvm::raw_svector_ostream os(buf);
1755+
os << u8"$\u03C4_" << shape.depth << '_' << shape.index;
1756+
StringRef mds_var = os.str();
1757+
llvm::Optional<lldb::addr_t> mds_ptr =
1758+
GetTypeMetadataForTypeNameAndFrame(mds_var, *frame);
1759+
if (!mds_ptr) {
1760+
LLDB_LOGF(log,
1761+
"cannot decode pack_expansion type: failed to find "
1762+
"metadata "
1763+
"for \"%s\" in frame",
1764+
mds_var.str().c_str());
1765+
error = true;
1766+
return;
1767+
}
1768+
type_packs.insert({{depth, index}, *mds_ptr});
1769+
}
1770+
}
1771+
});
1772+
if (error)
1773+
return false;
1774+
1775+
// Walk the type packs.
1776+
std::vector<TypeSystemSwift::TupleElement> elements;
1777+
for (unsigned j = 0; j < *count; ++j) {
1778+
1779+
// Build the list of type substitutions.
1780+
swift::reflection::GenericArgumentMap substitutions;
1781+
for (auto it : type_packs) {
1782+
unsigned depth = it.first.first;
1783+
unsigned index = it.first.second;
1784+
lldb::addr_t md_ptr = it.second + j * ptr_size;
1785+
1786+
// Read the type metadata pointer.
1787+
Status status;
1788+
lldb::addr_t md = LLDB_INVALID_ADDRESS;
1789+
target.ReadMemory(md_ptr, &md, ptr_size, status, true);
1790+
if (!status.Success()) {
1791+
LLDB_LOGF(log,
1792+
"cannot decode pack_expansion type: failed to read type "
1793+
"pack for type %d/%d of type pack with shape %d %d",
1794+
j, (unsigned)*count, depth, index);
1795+
return false;
1796+
}
1797+
1798+
auto *type_ref = reflection_ctx->readTypeFromMetadata(md);
1799+
if (!type_ref) {
1800+
LLDB_LOGF(log,
1801+
"cannot decode pack_expansion type: failed to decode type "
1802+
"metadata for type %d/%d of type pack with shape %d %d",
1803+
j, (unsigned)*count, depth, index);
1804+
return false;
1805+
}
1806+
substitutions.insert({{depth, index}, type_ref});
1807+
}
1808+
if (substitutions.empty())
1809+
return false;
1810+
1811+
// Replace all pack expansions with a singular type. Otherwise the
1812+
// reflection context won't accept them.
1813+
NodePointer pack_element = TypeSystemSwiftTypeRef::Transform(
1814+
dem, dem_pack_type, [](NodePointer node) {
1815+
if (node->getKind() != Node::Kind::PackExpansion)
1816+
return node;
1817+
assert(node->getNumChildren() == 2);
1818+
if (node->getNumChildren() != 2)
1819+
return node;
1820+
return node->getChild(0);
1821+
});
1822+
1823+
// Build a TypeRef from the demangle tree.
1824+
auto typeref_or_err =
1825+
decodeMangledType(reflection_ctx->getBuilder(), pack_element);
1826+
if (typeref_or_err.isError()) {
1827+
LLDB_LOG(log, "Couldn't get TypeRef for %s",
1828+
pack_type.GetMangledTypeName().GetCString());
1829+
return false;
1830+
}
1831+
auto typeref = typeref_or_err.getType();
1832+
1833+
// Apply the substitutions.
1834+
auto bound_typeref =
1835+
typeref->subst(reflection_ctx->getBuilder(), substitutions);
1836+
swift::Demangle::NodePointer node = bound_typeref->getDemangling(dem);
1837+
CompilerType type = ts->RemangleAsType(dem, node);
1838+
1839+
// Add the substituted type to the tuple.
1840+
elements.push_back({{}, type});
1841+
}
1842+
// Create a tuple type with all the concrete types in the pack.
1843+
CompilerType tuple = ts->CreateTupleType(elements);
1844+
// Wrap the type inside a SILPackType to mark it for GetChildAtIndex.
1845+
CompilerType sil_pack_type = ts->CreateSILPackType(tuple, indirect);
1846+
pack_type_or_name.SetCompilerType(sil_pack_type);
1847+
LLDB_LOGF(log, "decoded pack_expansion type: %s",
1848+
tuple.GetMangledTypeName().GetCString());
1849+
1850+
lldb::addr_t addr = in_value.GetAddressOf();
1851+
if (indirect) {
1852+
Status status;
1853+
addr = m_process.ReadPointerFromMemory(addr, status);
1854+
if (status.Fail()) {
1855+
LLDB_LOGF(log, "failed to dereference indirect pack: %s",
1856+
tuple.GetMangledTypeName().GetCString());
1857+
return false;
1858+
}
1859+
}
1860+
address.SetRawAddress(addr);
1861+
return true;
1862+
}
1863+
16021864
/// Determine whether the scratch SwiftASTContext has been locked.
16031865
static bool IsScratchContextLocked(Target &target) {
16041866
if (target.GetSwiftScratchContextLock().try_lock()) {
@@ -1986,9 +2248,9 @@ SwiftLanguageRuntimeImpl::GetPromiseForTypeNameAndFrame(const char *type_name,
19862248
return GetMetadataPromise(metadata_location, *metadata_ptr_var_sp);
19872249
}
19882250

1989-
static void
1990-
ForEachGenericParameter(swift::Demangle::NodePointer node,
1991-
std::function<void(unsigned, unsigned)> callback) {
2251+
void SwiftLanguageRuntime::ForEachGenericParameter(
2252+
swift::Demangle::NodePointer node,
2253+
std::function<void(unsigned, unsigned)> callback) {
19922254
if (!node)
19932255
return;
19942256

@@ -2124,7 +2386,6 @@ SwiftLanguageRuntimeImpl::BindGenericTypeParameters(StackFrame &stack_frame,
21242386
GetTypeMetadataForTypeNameAndFrame(mdvar_name.GetString(), stack_frame);
21252387
if (!metadata_location)
21262388
return;
2127-
21282389
const swift::reflection::TypeRef *type_ref =
21292390
reflection_ctx->readTypeFromMetadata(*metadata_location);
21302391
if (!type_ref)
@@ -2738,6 +2999,9 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress(
27382999
if (is_indirect_enum_case)
27393000
success = GetDynamicTypeAndAddress_IndirectEnumCase(
27403001
in_value, use_dynamic, class_type_or_name, address);
3002+
else if (type_info.AnySet(eTypeIsPack))
3003+
success = GetDynamicTypeAndAddress_Pack(in_value, val_type, use_dynamic,
3004+
class_type_or_name, address);
27413005
else if (type_info.AnySet(eTypeIsClass) ||
27423006
type_info.AllSet(eTypeIsBuiltIn | eTypeIsPointer | eTypeHasValue))
27433007
success = GetDynamicTypeAndAddress_Class(in_value, val_type, use_dynamic,

0 commit comments

Comments
 (0)