Skip to content

Commit 4944de0

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 87b0ca4 commit 4944de0

File tree

8 files changed

+329
-84
lines changed

8 files changed

+329
-84
lines changed

include/swift/Demangling/TypeDecoder.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,43 @@ void decodeRequirement(
573573
}
574574
}
575575

576+
/// Extract the protocol and requirement nodes from a shape symbol.
577+
static inline std::pair<NodePointer, NodePointer>
578+
decodeShape(NodePointer Node) {
579+
if (!Node || Node->getKind() != Node::Kind::Global ||
580+
Node->getNumChildren() != 1)
581+
return {nullptr, nullptr};
582+
Node = Node->getChild(0);
583+
if (Node && (Node->getKind() == Node::Kind::Uniquable) &&
584+
Node->getNumChildren() == 1)
585+
Node = Node->getChild(0);
586+
if (!Node || Node->getKind() != Node::Kind::ExtendedExistentialTypeShape ||
587+
Node->getNumChildren() != 2)
588+
return {nullptr, nullptr};
589+
Node = Node->getChild(1);
590+
if (!Node || Node->getKind() != Node::Kind::Type ||
591+
Node->getNumChildren() != 1)
592+
return {nullptr, nullptr};
593+
Node = Node->getChild(0);
594+
if (!Node || Node->getKind() != Node::Kind::ConstrainedExistential ||
595+
Node->getNumChildren() != 2)
596+
return {nullptr, nullptr};
597+
NodePointer Requirements = Node->getChild(1);
598+
if (!Requirements || Requirements->getKind() !=
599+
Node::Kind::ConstrainedExistentialRequirementList)
600+
return {nullptr, nullptr};
601+
602+
Node = Node->getChild(0);
603+
if (!Node || Node->getKind() != Node::Kind::Type ||
604+
Node->getNumChildren() != 1)
605+
return {nullptr, nullptr};
606+
NodePointer Protocol = Node;
607+
if (!Protocol)
608+
return {nullptr, nullptr};
609+
610+
return {Protocol, Requirements};
611+
}
612+
576613
#define MAKE_NODE_TYPE_ERROR(Node, Fmt, ...) \
577614
TYPE_LOOKUP_ERROR_FMT("TypeDecoder.h:%u: Node kind %u \"%.*s\" - " Fmt, \
578615
__LINE__, (unsigned)Node->getKind(), \

include/swift/Remote/MetadataReader.h

Lines changed: 90 additions & 75 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,74 @@ class MetadataReader {
886886
return resolver.swiftProtocol(Demangled);
887887
}
888888

889+
BuiltType readTypeFromShape(
890+
RemoteAbsolutePointer shapeAddress,
891+
std::function<std::optional<std::vector<BuiltType>>(unsigned)> getArgs) {
892+
StoredPointer addr = shapeAddress.getResolvedAddress().getAddressData();
893+
ShapeRef Shape = readShape(addr);
894+
if (!Shape)
895+
return BuiltType();
896+
897+
assert(Shape->hasGeneralizationSignature());
898+
auto builtArgs = getArgs(Shape->getGenSigArgumentLayoutSizeInWords());
899+
900+
// Pull out the existential type from the mangled type name.
901+
Demangler dem;
902+
auto mangledExistentialAddr =
903+
resolveRelativeField(Shape, Shape->ExistentialType);
904+
auto node = readMangledName(RemoteAddress(mangledExistentialAddr),
905+
MangledNameKind::Type, dem);
906+
if (!node)
907+
return BuiltType();
908+
909+
BuiltType builtProto = decodeMangledType(node).getType();
910+
if (!builtProto)
911+
return BuiltType();
912+
913+
if (builtArgs) {
914+
// Build up a substitution map for the generalized signature.
915+
BuiltGenericSignature sig =
916+
decodeRuntimeGenericSignature(Shape,
917+
Shape->getGeneralizationSignature())
918+
.getType();
919+
if (!sig)
920+
return BuiltType();
921+
922+
BuiltSubstitutionMap subst =
923+
Builder.createSubstitutionMap(sig, *builtArgs);
924+
if (subst.empty())
925+
return BuiltType();
926+
927+
builtProto = Builder.subst(builtProto, subst);
928+
if (!builtProto)
929+
return BuiltType();
930+
}
931+
932+
// Read the type expression to build up any remaining layers of
933+
// existential metatype.
934+
if (Shape->Flags.hasTypeExpression()) {
935+
Demangler dem;
936+
937+
// Read the mangled name.
938+
auto mangledContextName = Shape->getTypeExpression();
939+
auto mangledNameAddress =
940+
resolveRelativeField(Shape, mangledContextName->name);
941+
auto node = readMangledName(RemoteAddress(mangledNameAddress),
942+
MangledNameKind::Type, dem);
943+
if (!node)
944+
return BuiltType();
945+
946+
while (node->getKind() == Demangle::Node::Kind::Type &&
947+
node->getNumChildren() &&
948+
node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype &&
949+
node->getChild(0)->getNumChildren()) {
950+
builtProto = Builder.createExistentialMetatypeType(builtProto);
951+
node = node->getChild(0)->getChild(0);
952+
}
953+
}
954+
return builtProto;
955+
}
956+
889957
/// Given a remote pointer to metadata, attempt to turn it into a type.
890958
BuiltType
891959
readTypeFromMetadata(StoredPointer MetadataAddress,
@@ -1081,79 +1149,25 @@ class MetadataReader {
10811149
}
10821150
case MetadataKind::ExtendedExistential: {
10831151
auto Exist = cast<TargetExtendedExistentialTypeMetadata<Runtime>>(Meta);
1084-
10851152
// Read the shape for this existential.
10861153
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-
}
11561154

1155+
auto builtProto = readTypeFromShape(
1156+
RemoteAddress(shapeAddress),
1157+
[&](unsigned shapeArgumentCount)
1158+
-> std::optional<std::vector<BuiltType>> {
1159+
// Pull out the arguments to the generalization signature.
1160+
std::vector<BuiltType> builtArgs;
1161+
for (unsigned i = 0; i < shapeArgumentCount; ++i) {
1162+
auto remoteArg = Exist->getGeneralizationArguments()[i];
1163+
auto builtArg =
1164+
readTypeFromMetadata(remoteArg, false, recursion_limit);
1165+
if (!builtArg)
1166+
return std::nullopt;
1167+
builtArgs.push_back(builtArg);
1168+
}
1169+
return builtArgs;
1170+
});
11571171
TypeCache[TypeCacheKey] = builtProto;
11581172
return builtProto;
11591173
}
@@ -1371,8 +1385,7 @@ class MetadataReader {
13711385
readContextDescriptor(address.getResolvedAddress().getAddressData()));
13721386
}
13731387

1374-
ShapeRef
1375-
readShape(StoredPointer address) {
1388+
ShapeRef readShape(StoredPointer address) {
13761389
if (address == 0)
13771390
return nullptr;
13781391

@@ -1392,7 +1405,9 @@ class MetadataReader {
13921405
uint64_t genericHeaderSize = sizeof(GenericContextDescriptorHeader);
13931406
{
13941407
GenericContextDescriptorHeader header;
1395-
auto headerAddr = address + sizeof(flags);
1408+
auto headerAddr = address + sizeof(flags) +
1409+
sizeof(TargetRelativeDirectPointer<Runtime, const char,
1410+
/*nullable*/ false>);
13961411

13971412
if (!Reader->readBytes(RemoteAddress(headerAddr),
13981413
(uint8_t*)&header, sizeof(header)))

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: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,8 +1283,26 @@ 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+
// Non-unique shape symbols start with an offset to a cache variable, right
1287+
// before the shape. Metadata pointers point directly to the shape, but when
1288+
// reading from a shape symbol, this needs to be corrected.
1289+
uint32_t offset = 0;
1290+
if (shapeNode->getKind() ==
1291+
Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference)
1292+
offset = sizeof(uint32_t);
1293+
remote::RemoteAddress shape(shapeNode->getIndex() + offset);
1294+
1295+
return OpaqueShapeReader(
1296+
shape,
1297+
[&](unsigned shapeArgumentCount)
1298+
-> std::optional<std::vector<const TypeRef *>> {
1299+
if (args.size() != shapeArgumentCount)
1300+
return std::nullopt;
1301+
if (llvm::any_of(
1302+
args, [](const TypeRef *arg) { return !arg->isConcrete(); }))
1303+
return std::nullopt;
1304+
return args;
1305+
});
12881306
}
12891307

12901308
const ExistentialMetatypeTypeRef *createExistentialMetatypeType(
@@ -1312,8 +1330,7 @@ class TypeRefBuilder {
13121330

13131331
const DependentMemberTypeRef *
13141332
createDependentMemberType(const std::string &member, const TypeRef *base) {
1315-
// Should not have unresolved dependent member types here.
1316-
return nullptr;
1333+
return DependentMemberTypeRef::create(*this, member, base, "");
13171334
}
13181335

13191336
const DependentMemberTypeRef *
@@ -1479,6 +1496,13 @@ class TypeRefBuilder {
14791496
using PointerReader =
14801497
std::function<std::optional<remote::RemoteAbsolutePointer>(
14811498
remote::RemoteAddress, unsigned)>;
1499+
using ShapeReader = std::function<const TypeRef *(
1500+
remote::RemoteAbsolutePointer,
1501+
std::function<std::optional<std::vector<const TypeRef *>>(unsigned)>)>;
1502+
1503+
using PointerSymbolResolver =
1504+
std::function<std::optional<remote::RemoteAbsolutePointer>(
1505+
remote::RemoteAddress)>;
14821506
using DynamicSymbolResolver =
14831507
std::function<std::optional<remote::RemoteAbsolutePointer>(
14841508
remote::RemoteAddress)>;
@@ -1511,6 +1535,8 @@ class TypeRefBuilder {
15111535
ByteReader OpaqueByteReader;
15121536
StringReader OpaqueStringReader;
15131537
PointerReader OpaquePointerReader;
1538+
ShapeReader OpaqueShapeReader;
1539+
PointerSymbolResolver OpaquePointerSymbolResolver;
15141540
DynamicSymbolResolver OpaqueDynamicSymbolResolver;
15151541
IntVariableReader OpaqueIntVariableReader;
15161542

@@ -1549,6 +1575,18 @@ class TypeRefBuilder {
15491575
-> std::optional<remote::RemoteAbsolutePointer> {
15501576
return reader.Reader->readPointer(address, size);
15511577
}),
1578+
OpaqueShapeReader(
1579+
[&reader](remote::RemoteAbsolutePointer pointer,
1580+
std::function<std::optional<std::vector<const TypeRef *>>(
1581+
unsigned)>
1582+
getArgs) -> const TypeRef * {
1583+
return reader.readTypeFromShape(pointer, getArgs);
1584+
}),
1585+
OpaquePointerSymbolResolver(
1586+
[&reader](remote::RemoteAddress address)
1587+
-> std::optional<remote::RemoteAbsolutePointer> {
1588+
return reader.Reader->resolvePointerAsSymbol(address);
1589+
}),
15521590
OpaqueDynamicSymbolResolver(
15531591
[&reader](remote::RemoteAddress address)
15541592
-> std::optional<remote::RemoteAbsolutePointer> {

0 commit comments

Comments
 (0)