Skip to content

Commit 484906a

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 484906a

File tree

8 files changed

+352
-105
lines changed

8 files changed

+352
-105
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: 113 additions & 96 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

@@ -1382,38 +1395,42 @@ class MetadataReader {
13821395
reinterpret_cast<const TargetExtendedExistentialTypeShape<Runtime> *>(
13831396
cached->second.get()));
13841397

1385-
ExtendedExistentialTypeShapeFlags flags;
1386-
if (!Reader->readBytes(RemoteAddress(address), (uint8_t*)&flags,
1387-
sizeof(flags)))
1388-
return nullptr;
13891398

1390-
// Read the size of the requirement signature.
1391-
uint64_t reqSigGenericSize = 0;
1392-
uint64_t genericHeaderSize = sizeof(GenericContextDescriptorHeader);
1399+
uint64_t descriptorSize;
13931400
{
1394-
GenericContextDescriptorHeader header;
1395-
auto headerAddr = address + sizeof(flags);
1396-
1397-
if (!Reader->readBytes(RemoteAddress(headerAddr),
1398-
(uint8_t*)&header, sizeof(header)))
1401+
using RelativeOffset = TargetRelativeDirectPointer<Runtime, const char,
1402+
/*nullable*/ false>;
1403+
constexpr size_t buffer_size = sizeof(ExtendedExistentialTypeShapeFlags) +
1404+
sizeof(RelativeOffset) +
1405+
sizeof(GenericContextDescriptorHeader);
1406+
uint8_t buffer[buffer_size];
1407+
if (!Reader->readBytes(RemoteAddress(address), buffer, sizeof(buffer)))
13991408
return nullptr;
14001409

1410+
// Read the size of the requirement signature.
1411+
uint64_t reqSigGenericSize = 0;
1412+
uint64_t genericHeaderSize = sizeof(GenericContextDescriptorHeader);
1413+
ExtendedExistentialTypeShapeFlags flags;
1414+
memcpy((uint8_t*)&flags, buffer, sizeof(flags));
1415+
GenericContextDescriptorHeader header;
1416+
memcpy((uint8_t *)&header,
1417+
buffer + sizeof(flags) + sizeof(RelativeOffset), sizeof(header));
14011418
reqSigGenericSize = reqSigGenericSize
14021419
+ (header.NumParams + 3u & ~3u)
14031420
+ header.NumRequirements
14041421
* sizeof(TargetGenericRequirementDescriptor<Runtime>);
1405-
}
1406-
uint64_t typeExprSize = flags.hasTypeExpression() ? sizeof(StoredPointer) : 0;
1407-
uint64_t suggestedVWSize = flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0;
1422+
uint64_t typeExprSize =
1423+
flags.hasTypeExpression() ? sizeof(StoredPointer) : 0;
1424+
uint64_t suggestedVWSize =
1425+
flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0;
14081426

1409-
uint64_t size = sizeof(ExtendedExistentialTypeShapeFlags) +
1410-
sizeof(TargetRelativeDirectPointer<Runtime, const char,
1411-
/*nullable*/ false>) +
1412-
genericHeaderSize + typeExprSize + suggestedVWSize +
1413-
reqSigGenericSize;
1414-
if (size > MaxMetadataSize)
1427+
descriptorSize = sizeof(flags) + sizeof(RelativeOffset) +
1428+
genericHeaderSize + typeExprSize + suggestedVWSize +
1429+
reqSigGenericSize;
1430+
}
1431+
if (descriptorSize > MaxMetadataSize)
14151432
return nullptr;
1416-
auto readResult = Reader->readBytes(RemoteAddress(address), size);
1433+
auto readResult = Reader->readBytes(RemoteAddress(address), descriptorSize);
14171434
if (!readResult)
14181435
return nullptr;
14191436

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;

0 commit comments

Comments
 (0)