Skip to content

Commit 63a2981

Browse files
committed
Implement reflection support for Symbolic Extended Existential types.
This patch adds a new SymbolicExtendedExistentialTypeRef kind, and wires it up in TypeDecoder, TypeRefBuilder, TypeLowering, and ASTDemangler. This is tested indirectly via the matching LLDB commit.
1 parent 31a9b79 commit 63a2981

File tree

8 files changed

+326
-83
lines changed

8 files changed

+326
-83
lines changed

include/swift/Demangling/TypeDecoder.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,43 @@ void decodeRequirement(
555555
}
556556
}
557557

558+
/// Extract the protocol and requirement nodes from a shape symbol.
559+
static inline std::pair<NodePointer, NodePointer>
560+
decodeShape(NodePointer Node) {
561+
if (!Node || Node->getKind() != Node::Kind::Global ||
562+
Node->getNumChildren() != 1)
563+
return {nullptr, nullptr};
564+
Node = Node->getChild(0);
565+
if (Node && (Node->getKind() == Node::Kind::Uniquable) &&
566+
Node->getNumChildren() == 1)
567+
Node = Node->getChild(0);
568+
if (!Node || Node->getKind() != Node::Kind::ExtendedExistentialTypeShape ||
569+
Node->getNumChildren() != 2)
570+
return {nullptr, nullptr};
571+
Node = Node->getChild(1);
572+
if (!Node || Node->getKind() != Node::Kind::Type ||
573+
Node->getNumChildren() != 1)
574+
return {nullptr, nullptr};
575+
Node = Node->getChild(0);
576+
if (!Node || Node->getKind() != Node::Kind::ConstrainedExistential ||
577+
Node->getNumChildren() != 2)
578+
return {nullptr, nullptr};
579+
NodePointer Requirements = Node->getChild(1);
580+
if (!Requirements || Requirements->getKind() !=
581+
Node::Kind::ConstrainedExistentialRequirementList)
582+
return {nullptr, nullptr};
583+
584+
Node = Node->getChild(0);
585+
if (!Node || Node->getKind() != Node::Kind::Type ||
586+
Node->getNumChildren() != 1)
587+
return {nullptr, nullptr};
588+
NodePointer Protocol = Node;
589+
if (!Protocol)
590+
return {nullptr, nullptr};
591+
592+
return {Protocol, Requirements};
593+
}
594+
558595
#define MAKE_NODE_TYPE_ERROR(Node, Fmt, ...) \
559596
TYPE_LOOKUP_ERROR_FMT("TypeDecoder.h:%u: Node kind %u \"%.*s\" - " Fmt, \
560597
__LINE__, (unsigned)Node->getKind(), \

include/swift/Remote/MetadataReader.h

Lines changed: 93 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -509,8 +509,8 @@ class MetadataReader {
509509
// The symbolic reference points at a non-unique extended
510510
// existential type shape.
511511
return dem.createNode(
512-
Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference,
513-
resolved.getResolvedAddress().getAddressData());
512+
Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference,
513+
resolved.getResolvedAddress().getAddressData());
514514
}
515515
case Demangle::SymbolicReferenceKind::ObjectiveCProtocol: {
516516
// 'resolved' points to a struct of two relative addresses.
@@ -886,6 +886,77 @@ class MetadataReader {
886886
return resolver.swiftProtocol(Demangled);
887887
}
888888

889+
BuiltType readTypeFromShape(
890+
RemoteAbsolutePointer shapeAddress, bool non_unique,
891+
std::function<std::optional<std::vector<BuiltType>>(unsigned)> getArgs) {
892+
StoredPointer addr = shapeAddress.getResolvedAddress().getAddressData();
893+
// Non-unique shapes start with an offset to a cache variable.
894+
if (non_unique)
895+
addr += 4;
896+
ShapeRef Shape = readShape(addr);
897+
if (!Shape)
898+
return BuiltType();
899+
900+
assert(Shape->hasGeneralizationSignature());
901+
auto builtArgs = getArgs(Shape->getGenSigArgumentLayoutSizeInWords());
902+
903+
// Pull out the existential type from the mangled type name.
904+
Demangler dem;
905+
auto mangledExistentialAddr =
906+
resolveRelativeField(Shape, Shape->ExistentialType);
907+
auto node = readMangledName(RemoteAddress(mangledExistentialAddr),
908+
MangledNameKind::Type, dem);
909+
if (!node)
910+
return BuiltType();
911+
912+
BuiltType builtProto = decodeMangledType(node).getType();
913+
if (!builtProto)
914+
return BuiltType();
915+
916+
if (builtArgs) {
917+
// Build up a substitution map for the generalized signature.
918+
BuiltGenericSignature sig =
919+
decodeRuntimeGenericSignature(Shape,
920+
Shape->getGeneralizationSignature())
921+
.getType();
922+
if (!sig)
923+
return BuiltType();
924+
925+
BuiltSubstitutionMap subst =
926+
Builder.createSubstitutionMap(sig, *builtArgs);
927+
if (subst.empty())
928+
return BuiltType();
929+
930+
builtProto = Builder.subst(builtProto, subst);
931+
if (!builtProto)
932+
return BuiltType();
933+
}
934+
935+
// Read the type expression to build up any remaining layers of
936+
// existential metatype.
937+
if (Shape->Flags.hasTypeExpression()) {
938+
Demangler dem;
939+
940+
// Read the mangled name.
941+
auto mangledContextName = Shape->getTypeExpression();
942+
auto mangledNameAddress =
943+
resolveRelativeField(Shape, mangledContextName->name);
944+
auto node = readMangledName(RemoteAddress(mangledNameAddress),
945+
MangledNameKind::Type, dem);
946+
if (!node)
947+
return BuiltType();
948+
949+
while (node->getKind() == Demangle::Node::Kind::Type &&
950+
node->getNumChildren() &&
951+
node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype &&
952+
node->getChild(0)->getNumChildren()) {
953+
builtProto = Builder.createExistentialMetatypeType(builtProto);
954+
node = node->getChild(0)->getChild(0);
955+
}
956+
}
957+
return builtProto;
958+
}
959+
889960
/// Given a remote pointer to metadata, attempt to turn it into a type.
890961
BuiltType
891962
readTypeFromMetadata(StoredPointer MetadataAddress,
@@ -1081,79 +1152,27 @@ class MetadataReader {
10811152
}
10821153
case MetadataKind::ExtendedExistential: {
10831154
auto Exist = cast<TargetExtendedExistentialTypeMetadata<Runtime>>(Meta);
1084-
10851155
// Read the shape for this existential.
10861156
StoredPointer shapeAddress = stripSignedPointer(Exist->Shape);
1087-
ShapeRef Shape = readShape(shapeAddress);
1088-
if (!Shape)
1089-
return BuiltType();
1090-
1091-
const unsigned shapeArgumentCount
1092-
= Shape->getGenSigArgumentLayoutSizeInWords();
1093-
// Pull out the arguments to the generalization signature.
1094-
assert(Shape->hasGeneralizationSignature());
1095-
std::vector<BuiltType> builtArgs;
1096-
for (unsigned i = 0; i < shapeArgumentCount; ++i) {
1097-
auto remoteArg = Exist->getGeneralizationArguments()[i];
1098-
auto builtArg = readTypeFromMetadata(remoteArg, false, recursion_limit);
1099-
if (!builtArg)
1100-
return BuiltType();
1101-
builtArgs.push_back(builtArg);
1102-
}
1103-
1104-
// Pull out the existential type from the mangled type name.
1105-
Demangler dem;
1106-
auto mangledExistentialAddr =
1107-
resolveRelativeField(Shape, Shape->ExistentialType);
1108-
auto node = readMangledName(RemoteAddress(mangledExistentialAddr),
1109-
MangledNameKind::Type, dem);
1110-
if (!node)
1111-
return BuiltType();
1112-
1113-
BuiltType builtProto = decodeMangledType(node).getType();
1114-
if (!builtProto)
1115-
return BuiltType();
1116-
1117-
// Build up a substitution map for the generalized signature.
1118-
BuiltGenericSignature sig =
1119-
decodeRuntimeGenericSignature(Shape,
1120-
Shape->getGeneralizationSignature())
1121-
.getType();
1122-
if (!sig)
1123-
return BuiltType();
1124-
1125-
BuiltSubstitutionMap subst =
1126-
Builder.createSubstitutionMap(sig, builtArgs);
1127-
if (subst.empty())
1128-
return BuiltType();
1129-
1130-
builtProto = Builder.subst(builtProto, subst);
1131-
if (!builtProto)
1132-
return BuiltType();
1133-
1134-
// Read the type expression to build up any remaining layers of
1135-
// existential metatype.
1136-
if (Shape->Flags.hasTypeExpression()) {
1137-
Demangler dem;
1138-
1139-
// Read the mangled name.
1140-
auto mangledContextName = Shape->getTypeExpression();
1141-
auto mangledNameAddress =
1142-
resolveRelativeField(Shape, mangledContextName->name);
1143-
auto node = readMangledName(RemoteAddress(mangledNameAddress),
1144-
MangledNameKind::Type, dem);
1145-
if (!node)
1146-
return BuiltType();
1147-
1148-
while (node->getKind() == Demangle::Node::Kind::Type &&
1149-
node->getNumChildren() &&
1150-
node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype &&
1151-
node->getChild(0)->getNumChildren()) {
1152-
builtProto = Builder.createExistentialMetatypeType(builtProto);
1153-
node = node->getChild(0)->getChild(0);
1154-
}
1155-
}
11561157

1158+
// FIXME!
1159+
bool non_unique = false;
1160+
auto builtProto = readTypeFromShape(
1161+
RemoteAddress(shapeAddress), non_unique,
1162+
[&](unsigned shapeArgumentCount)
1163+
-> std::optional<std::vector<BuiltType>> {
1164+
// Pull out the arguments to the generalization signature.
1165+
std::vector<BuiltType> builtArgs;
1166+
for (unsigned i = 0; i < shapeArgumentCount; ++i) {
1167+
auto remoteArg = Exist->getGeneralizationArguments()[i];
1168+
auto builtArg =
1169+
readTypeFromMetadata(remoteArg, false, recursion_limit);
1170+
if (!builtArg)
1171+
return std::nullopt;
1172+
builtArgs.push_back(builtArg);
1173+
}
1174+
return builtArgs;
1175+
});
11571176
TypeCache[TypeCacheKey] = builtProto;
11581177
return builtProto;
11591178
}
@@ -1371,8 +1390,7 @@ class MetadataReader {
13711390
readContextDescriptor(address.getResolvedAddress().getAddressData()));
13721391
}
13731392

1374-
ShapeRef
1375-
readShape(StoredPointer address) {
1393+
ShapeRef readShape(StoredPointer address) {
13761394
if (address == 0)
13771395
return nullptr;
13781396

@@ -2148,6 +2166,7 @@ class MetadataReader {
21482166
return nullptr;
21492167
auto shapePtr = stripSignedPointer(signedShapePtr);
21502168

2169+
// FIXME: Apply non-unique +4 offset?
21512170
auto shape = readShape(shapePtr);
21522171
if (!shape)
21532172
return nullptr;

include/swift/RemoteInspection/TypeRef.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,64 @@ class ConstrainedExistentialTypeRef final : public TypeRef {
731731
}
732732
};
733733

734+
class SymbolicExtendedExistentialTypeRef final : public TypeRef {
735+
const ProtocolCompositionTypeRef *Protocol;
736+
std::vector<TypeRefRequirement> Requirements;
737+
std::vector<const TypeRef *> Arguments;
738+
ExtendedExistentialTypeShapeFlags Flags;
739+
740+
static TypeRefID Profile(const ProtocolCompositionTypeRef *Protocol,
741+
llvm::ArrayRef<TypeRefRequirement> Requirements,
742+
llvm::ArrayRef<const TypeRef *> Arguments,
743+
ExtendedExistentialTypeShapeFlags Flags) {
744+
TypeRefID ID;
745+
ID.addPointer(Protocol);
746+
for (auto reqt : Requirements) {
747+
ID.addPointer(reqt.getFirstType());
748+
if (reqt.getKind() != RequirementKind::Layout)
749+
ID.addPointer(reqt.getSecondType());
750+
else
751+
ID.addInteger(
752+
unsigned(0)); // FIXME: Layout constraints aren't implemented yet
753+
ID.addInteger(unsigned(reqt.getKind()));
754+
}
755+
756+
for (auto &Arg : Arguments)
757+
ID.addPointer(Arg);
758+
return ID;
759+
}
760+
761+
public:
762+
SymbolicExtendedExistentialTypeRef(
763+
const ProtocolCompositionTypeRef *Protocol,
764+
llvm::ArrayRef<TypeRefRequirement> Requirements,
765+
llvm::ArrayRef<const TypeRef *> Args,
766+
ExtendedExistentialTypeShapeFlags Flags)
767+
: TypeRef(TypeRefKind::SymbolicExtendedExistential), Protocol(Protocol),
768+
Requirements(Requirements), Arguments(Args), Flags(Flags) {}
769+
770+
template <typename Allocator>
771+
static const SymbolicExtendedExistentialTypeRef *
772+
create(Allocator &A, const ProtocolCompositionTypeRef *Protocol,
773+
llvm::ArrayRef<TypeRefRequirement> Requirements,
774+
llvm::ArrayRef<const TypeRef *> Args,
775+
ExtendedExistentialTypeShapeFlags Flags) {
776+
FIND_OR_CREATE_TYPEREF(A, SymbolicExtendedExistentialTypeRef, Protocol,
777+
Requirements, Args, Flags);
778+
}
779+
780+
const ProtocolCompositionTypeRef *getProtocol() const { return Protocol; }
781+
llvm::ArrayRef<TypeRefRequirement> getRequirements() const {
782+
return Requirements;
783+
}
784+
llvm::ArrayRef<const TypeRef *> getArguments() const { return Arguments; }
785+
ExtendedExistentialTypeShapeFlags getFlags() const { return Flags; }
786+
787+
static bool classof(const TypeRef *TR) {
788+
return TR->getKind() == TypeRefKind::SymbolicExtendedExistential;
789+
}
790+
};
791+
734792
class MetatypeTypeRef final : public TypeRef {
735793
const TypeRef *InstanceType;
736794
bool WasAbstract;

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,8 +1283,20 @@ class TypeRefBuilder {
12831283
const TypeRef *
12841284
createSymbolicExtendedExistentialType(NodePointer shapeNode,
12851285
llvm::ArrayRef<const TypeRef *> args) {
1286-
// Can't handle this here.
1287-
return nullptr;
1286+
remote::RemoteAddress shape(shapeNode->getIndex());
1287+
return OpaqueShapeReader(
1288+
shape,
1289+
shapeNode->getKind() ==
1290+
Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference,
1291+
[&](unsigned shapeArgumentCount)
1292+
-> std::optional<std::vector<const TypeRef *>> {
1293+
if (args.size() != shapeArgumentCount)
1294+
return std::nullopt;
1295+
if (llvm::any_of(
1296+
args, [](const TypeRef *arg) { return !arg->isConcrete(); }))
1297+
return std::nullopt;
1298+
return args;
1299+
});
12881300
}
12891301

12901302
const ExistentialMetatypeTypeRef *createExistentialMetatypeType(
@@ -1312,8 +1324,7 @@ class TypeRefBuilder {
13121324

13131325
const DependentMemberTypeRef *
13141326
createDependentMemberType(const std::string &member, const TypeRef *base) {
1315-
// Should not have unresolved dependent member types here.
1316-
return nullptr;
1327+
return DependentMemberTypeRef::create(*this, member, base, "");
13171328
}
13181329

13191330
const DependentMemberTypeRef *
@@ -1479,6 +1490,13 @@ class TypeRefBuilder {
14791490
using PointerReader =
14801491
std::function<std::optional<remote::RemoteAbsolutePointer>(
14811492
remote::RemoteAddress, unsigned)>;
1493+
using ShapeReader = std::function<const TypeRef *(
1494+
remote::RemoteAbsolutePointer, bool,
1495+
std::function<std::optional<std::vector<const TypeRef *>>(unsigned)>)>;
1496+
1497+
using PointerSymbolResolver =
1498+
std::function<std::optional<remote::RemoteAbsolutePointer>(
1499+
remote::RemoteAddress)>;
14821500
using DynamicSymbolResolver =
14831501
std::function<std::optional<remote::RemoteAbsolutePointer>(
14841502
remote::RemoteAddress)>;
@@ -1511,6 +1529,8 @@ class TypeRefBuilder {
15111529
ByteReader OpaqueByteReader;
15121530
StringReader OpaqueStringReader;
15131531
PointerReader OpaquePointerReader;
1532+
ShapeReader OpaqueShapeReader;
1533+
PointerSymbolResolver OpaquePointerSymbolResolver;
15141534
DynamicSymbolResolver OpaqueDynamicSymbolResolver;
15151535
IntVariableReader OpaqueIntVariableReader;
15161536

@@ -1549,6 +1569,18 @@ class TypeRefBuilder {
15491569
-> std::optional<remote::RemoteAbsolutePointer> {
15501570
return reader.Reader->readPointer(address, size);
15511571
}),
1572+
OpaqueShapeReader(
1573+
[&reader](remote::RemoteAbsolutePointer pointer, bool non_unique,
1574+
std::function<std::optional<std::vector<const TypeRef *>>(
1575+
unsigned)>
1576+
getArgs) -> const TypeRef * {
1577+
return reader.readTypeFromShape(pointer, non_unique, getArgs);
1578+
}),
1579+
OpaquePointerSymbolResolver(
1580+
[&reader](remote::RemoteAddress address)
1581+
-> std::optional<remote::RemoteAbsolutePointer> {
1582+
return reader.Reader->resolvePointerAsSymbol(address);
1583+
}),
15521584
OpaqueDynamicSymbolResolver(
15531585
[&reader](remote::RemoteAddress address)
15541586
-> std::optional<remote::RemoteAbsolutePointer> {

include/swift/RemoteInspection/TypeRefs.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ TYPEREF(Tuple, TypeRef)
2323
TYPEREF(Function, TypeRef)
2424
TYPEREF(ProtocolComposition, TypeRef)
2525
TYPEREF(ConstrainedExistential, TypeRef)
26+
TYPEREF(SymbolicExtendedExistential, TypeRef)
2627
TYPEREF(Metatype, TypeRef)
2728
TYPEREF(ExistentialMetatype, TypeRef)
2829
TYPEREF(GenericTypeParameter, TypeRef)

0 commit comments

Comments
 (0)