Skip to content

Commit f7a4c6d

Browse files
committed
Implement reflection support for Symbolic Extended Existential types.
1 parent 31a9b79 commit f7a4c6d

File tree

7 files changed

+263
-10
lines changed

7 files changed

+263
-10
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/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,32 @@ 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+
auto symbol = OpaquePointerSymbolResolver(shape);
1288+
if (!symbol)
1289+
return nullptr;
1290+
auto bytes = OpaqueByteReader(shape, 4);
1291+
if (!bytes)
1292+
return nullptr;
1293+
ExtendedExistentialTypeShapeFlags flags(*(const uint32_t *)bytes.get());
1294+
1295+
Demangler Dem;
1296+
NodePointer node = Dem.demangleSymbol(symbol->getSymbol());
1297+
auto [protocolNode, requirementNode] = decodeShape(node);
1298+
if (!protocolNode || !requirementNode)
1299+
return nullptr;
1300+
1301+
auto *protocol = llvm::dyn_cast_or_null<ProtocolCompositionTypeRef>(
1302+
decodeMangledType(protocolNode));
1303+
1304+
llvm::SmallVector<BuiltRequirement, 8> requirements;
1305+
llvm::SmallVector<BuiltInverseRequirement, 8> inverseRequirements;
1306+
decodeRequirement<BuiltType, BuiltRequirement, BuiltInverseRequirement,
1307+
BuiltLayoutConstraint, TypeRefBuilder>(
1308+
requirementNode, requirements, inverseRequirements, *this);
1309+
1310+
return SymbolicExtendedExistentialTypeRef::create(
1311+
*this, protocol, requirements, args, flags);
12881312
}
12891313

12901314
const ExistentialMetatypeTypeRef *createExistentialMetatypeType(
@@ -1312,8 +1336,7 @@ class TypeRefBuilder {
13121336

13131337
const DependentMemberTypeRef *
13141338
createDependentMemberType(const std::string &member, const TypeRef *base) {
1315-
// Should not have unresolved dependent member types here.
1316-
return nullptr;
1339+
return DependentMemberTypeRef::create(*this, member, base, "");
13171340
}
13181341

13191342
const DependentMemberTypeRef *
@@ -1479,6 +1502,9 @@ class TypeRefBuilder {
14791502
using PointerReader =
14801503
std::function<std::optional<remote::RemoteAbsolutePointer>(
14811504
remote::RemoteAddress, unsigned)>;
1505+
using PointerSymbolResolver =
1506+
std::function<std::optional<remote::RemoteAbsolutePointer>(
1507+
remote::RemoteAddress)>;
14821508
using DynamicSymbolResolver =
14831509
std::function<std::optional<remote::RemoteAbsolutePointer>(
14841510
remote::RemoteAddress)>;
@@ -1511,6 +1537,7 @@ class TypeRefBuilder {
15111537
ByteReader OpaqueByteReader;
15121538
StringReader OpaqueStringReader;
15131539
PointerReader OpaquePointerReader;
1540+
PointerSymbolResolver OpaquePointerSymbolResolver;
15141541
DynamicSymbolResolver OpaqueDynamicSymbolResolver;
15151542
IntVariableReader OpaqueIntVariableReader;
15161543

@@ -1549,6 +1576,11 @@ class TypeRefBuilder {
15491576
-> std::optional<remote::RemoteAbsolutePointer> {
15501577
return reader.Reader->readPointer(address, size);
15511578
}),
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)

lib/AST/ASTDemangler.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -767,8 +767,12 @@ Type ASTBuilder::createExistentialMetatypeType(
767767
Type ASTBuilder::createConstrainedExistentialType(
768768
Type base, ArrayRef<BuiltRequirement> constraints,
769769
ArrayRef<BuiltInverseRequirement> inverseRequirements) {
770+
llvm::SmallDenseMap<Identifier, Type> primaryAssociatedTypeNames;
770771
llvm::SmallDenseMap<AssociatedTypeDecl *, Type> primaryAssociatedTypes;
771772
llvm::SmallDenseSet<AssociatedTypeDecl *> claimed;
773+
llvm::SmallDenseSet<Identifier> claimedNames;
774+
unsigned duplicates = 0;
775+
bool ambiguousName = false;
772776

773777
for (const auto &req : constraints) {
774778
switch (req.getKind()) {
@@ -782,7 +786,18 @@ Type ASTBuilder::createConstrainedExistentialType(
782786
if (auto *memberTy = req.getFirstType()->getAs<DependentMemberType>()) {
783787
if (memberTy->getBase()->is<GenericTypeParamType>()) {
784788
// This is the only case we understand so far.
785-
primaryAssociatedTypes[memberTy->getAssocType()] = req.getSecondType();
789+
if (auto *assocTy = memberTy->getAssocType())
790+
primaryAssociatedTypes[assocTy] = req.getSecondType();
791+
else {
792+
auto &ty = primaryAssociatedTypeNames[memberTy->getName()];
793+
if (!ty)
794+
ty = req.getSecondType();
795+
else if (ty.getPointer() == req.getSecondType().getPointer())
796+
++duplicates;
797+
else
798+
ambiguousName = true;
799+
}
800+
786801
continue;
787802
}
788803
}
@@ -799,11 +814,24 @@ Type ASTBuilder::createConstrainedExistentialType(
799814

800815
llvm::SmallVector<Type, 4> args;
801816
for (auto *assocTy : proto->getPrimaryAssociatedTypes()) {
802-
auto found = primaryAssociatedTypes.find(assocTy);
803-
if (found == primaryAssociatedTypes.end())
804-
return protoTy;
805-
args.push_back(found->second);
806-
claimed.insert(found->first);
817+
{
818+
auto found = primaryAssociatedTypes.find(assocTy);
819+
if (found != primaryAssociatedTypes.end()) {
820+
args.push_back(found->second);
821+
claimed.insert(found->first);
822+
continue;
823+
}
824+
}
825+
{
826+
if (ambiguousName)
827+
return protoTy;
828+
auto found = primaryAssociatedTypeNames.find(assocTy->getName());
829+
if (found != primaryAssociatedTypeNames.end()) {
830+
args.push_back(found->second);
831+
claimedNames.insert(found->first);
832+
continue;
833+
}
834+
}
807835
}
808836

809837
// We may not have any arguments because the constrained existential is a
@@ -839,6 +867,7 @@ Type ASTBuilder::createConstrainedExistentialType(
839867

840868
// Make sure that all arguments were actually used.
841869
ASSERT(claimed.size() == primaryAssociatedTypes.size());
870+
ASSERT(claimedNames.size() + duplicates == primaryAssociatedTypeNames.size());
842871

843872
// Handle inverse requirements.
844873
if (!inverseRequirements.empty()) {

stdlib/public/RemoteInspection/TypeLowering.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,7 @@ class ExistentialTypeInfoBuilder {
11541154
TypeConverter &TC;
11551155
std::vector<const TypeRef *> Protocols;
11561156
const TypeRef *Superclass = nullptr;
1157+
remote::RemoteAbsolutePointer Shape;
11571158
ExistentialTypeRepresentation Representation;
11581159
ReferenceCounting Refcounting;
11591160
bool ObjC;
@@ -1258,6 +1259,8 @@ class ExistentialTypeInfoBuilder {
12581259
}
12591260
}
12601261

1262+
void examineShape() {}
1263+
12611264
public:
12621265
ExistentialTypeInfoBuilder(TypeConverter &TC)
12631266
: TC(TC), Representation(ExistentialTypeRepresentation::Opaque),
@@ -1321,8 +1324,27 @@ class ExistentialTypeInfoBuilder {
13211324
Representation = ExistentialTypeRepresentation::Class;
13221325
}
13231326

1327+
void addShape(const ProtocolCompositionTypeRef *Protocol,
1328+
ExtendedExistentialTypeShapeFlags Flags) {
1329+
switch (Flags.getSpecialKind()) {
1330+
case ExtendedExistentialTypeShapeFlags::SpecialKind::Class:
1331+
Representation = ExistentialTypeRepresentation::Class;
1332+
break;
1333+
case ExtendedExistentialTypeShapeFlags::SpecialKind::Metatype:
1334+
case ExtendedExistentialTypeShapeFlags::SpecialKind::ExplicitLayout:
1335+
case ExtendedExistentialTypeShapeFlags::SpecialKind::None:
1336+
Representation = ExistentialTypeRepresentation::Opaque;
1337+
break;
1338+
}
1339+
1340+
if (Protocol)
1341+
for (auto *Protocol : Protocol->getProtocols())
1342+
addProtocol(Protocol);
1343+
}
1344+
13241345
const TypeInfo *build(remote::TypeInfoProvider *ExternalTypeInfo) {
13251346
examineProtocols();
1347+
examineShape();
13261348

13271349
if (Invalid)
13281350
return nullptr;
@@ -1780,6 +1802,11 @@ class HasFixedSize
17801802
return true;
17811803
}
17821804

1805+
bool visitSymbolicExtendedExistentialTypeRef(
1806+
const SymbolicExtendedExistentialTypeRef *SEET) {
1807+
return true;
1808+
}
1809+
17831810
bool
17841811
visitSILBoxTypeRef(const SILBoxTypeRef *SB) {
17851812
return true;
@@ -1923,6 +1950,11 @@ class HasSingletonMetatype
19231950
return MetatypeRepresentation::Thin;
19241951
}
19251952

1953+
MetatypeRepresentation visitSymbolicExtendedExistentialTypeRef(
1954+
const SymbolicExtendedExistentialTypeRef *SEET) {
1955+
return MetatypeRepresentation::Thin;
1956+
}
1957+
19261958
MetatypeRepresentation visitMetatypeTypeRef(const MetatypeTypeRef *M) {
19271959
if (M->wasAbstract())
19281960
return MetatypeRepresentation::Thick;
@@ -2520,6 +2552,13 @@ class LowerType
25202552
return builder.buildMetatype(ExternalTypeInfo);
25212553
}
25222554

2555+
const TypeInfo *visitSymbolicExtendedExistentialTypeRef(
2556+
const SymbolicExtendedExistentialTypeRef *SEET) {
2557+
ExistentialTypeInfoBuilder builder(TC);
2558+
builder.addShape(SEET->getProtocol(), SEET->getFlags());
2559+
return builder.build(ExternalTypeInfo);
2560+
}
2561+
25232562
const TypeInfo *
25242563
visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) {
25252564
DEBUG_LOG(fprintf(stderr, "Unresolved generic TypeRef: "); GTP->dump());

0 commit comments

Comments
 (0)