Skip to content

Commit de16c9a

Browse files
authored
Merge pull request #59808 from rjmccall/extended-existential-symbolic-mangling
Implement symbolic demangling for extended existential metadata
2 parents fc24be2 + 175f74d commit de16c9a

27 files changed

+627
-146
lines changed

docs/ABI/Mangling.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ The following symbolic reference kinds are currently implemented:
102102
metadata-access-function ::= '\x09' .{4} // Reference points directly to metadata access function that can be invoked to produce referenced object
103103
#endif
104104

105+
#if SWIFT_RUNTIME_VERISON >= 5.7
106+
symbolic-extended-existential-type-shape ::= '\x0A' .{4} // Reference points directly to an ExtendedExistentialTypeShape
107+
symbolic-extended-existential-type-shape ::= '\x0B' .{4} // Reference points directly to a NonUniqueExtendedExistentialTypeShape
108+
#endif
109+
105110
A mangled name may also include ``\xFF`` bytes, which are only used for
106111
alignment padding. They do not affect what the mangled name references and can
107112
be skipped over and ignored.
@@ -654,6 +659,10 @@ Types
654659
type ::= type assoc-type-list 'QX' // associated type relative to base `type`
655660
#endif
656661

662+
#if SWIFT_RUNTIME_VERSION >= 5.7
663+
type ::= symbolic-extended-existential-type-shape type* retroactive-conformance* 'Xj'
664+
#endif
665+
657666
protocol-list ::= protocol '_' protocol*
658667
protocol-list ::= empty-list
659668

include/swift/AST/ASTDemangler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class ASTBuilder {
124124
Type createConstrainedExistentialType(Type base,
125125
ArrayRef<BuiltRequirement> constraints);
126126

127+
Type createSymbolicExtendedExistentialType(NodePointer shapeNode,
128+
ArrayRef<Type> genArgs);
129+
127130
Type createExistentialMetatypeType(Type instance,
128131
Optional<Demangle::ImplMetatypeRepresentation> repr=None);
129132

include/swift/AST/ASTMangler.h

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/Basic/Mangler.h"
1717
#include "swift/AST/Types.h"
1818
#include "swift/AST/Decl.h"
19+
#include "swift/Basic/TaggedUnion.h"
1920

2021
namespace clang {
2122
class NamedDecl;
@@ -79,8 +80,50 @@ class ASTMangler : public Mangler {
7980
bool RespectOriginallyDefinedIn = true;
8081

8182
public:
82-
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
83-
const OpaqueTypeDecl *>;
83+
class SymbolicReferent {
84+
public:
85+
enum Kind {
86+
NominalType,
87+
OpaqueType,
88+
ExtendedExistentialTypeShape,
89+
};
90+
private:
91+
// TODO: make a TaggedUnion variant that works with an explicit
92+
// kind instead of requiring this redundant kind storage.
93+
TaggedUnion<const NominalTypeDecl *,
94+
const OpaqueTypeDecl *,
95+
Type>
96+
storage;
97+
Kind kind;
98+
99+
SymbolicReferent(Kind kind, Type type) : storage(type), kind(kind) {}
100+
public:
101+
SymbolicReferent(const NominalTypeDecl *decl)
102+
: storage(decl), kind(NominalType) {}
103+
SymbolicReferent(const OpaqueTypeDecl *decl)
104+
: storage(decl), kind(OpaqueType) {}
105+
static SymbolicReferent forExtendedExistentialTypeShape(Type type) {
106+
return SymbolicReferent(ExtendedExistentialTypeShape, type);
107+
}
108+
109+
Kind getKind() const { return kind; }
110+
111+
bool isNominalType() const { return kind == NominalType; }
112+
const NominalTypeDecl *getNominalType() const {
113+
assert(kind == NominalType);
114+
return storage.get<const NominalTypeDecl *>();
115+
}
116+
117+
const OpaqueTypeDecl *getOpaqueType() const {
118+
assert(kind == OpaqueType);
119+
return storage.get<const OpaqueTypeDecl *>();
120+
}
121+
122+
Type getType() const {
123+
assert(kind == ExtendedExistentialTypeShape);
124+
return storage.get<Type>();
125+
}
126+
};
84127
protected:
85128

86129
/// If set, the mangler calls this function to determine whether to symbolic
@@ -90,8 +133,8 @@ class ASTMangler : public Mangler {
90133

91134
bool canSymbolicReference(SymbolicReferent referent) {
92135
// Marker protocols cannot ever be symbolically referenced.
93-
if (auto nominal = referent.dyn_cast<const NominalTypeDecl *>()) {
94-
if (auto proto = dyn_cast<ProtocolDecl>(nominal)) {
136+
if (referent.isNominalType()) {
137+
if (auto proto = dyn_cast<ProtocolDecl>(referent.getNominalType())) {
95138
if (proto->isMarkerProtocol())
96139
return false;
97140
}
@@ -521,6 +564,10 @@ class ASTMangler : public Mangler {
521564
GenericSignature sig);
522565
void appendOpParamForLayoutConstraint(LayoutConstraint Layout);
523566

567+
void appendSymbolicExtendedExistentialType(SymbolicReferent shapeReferent,
568+
Type type,
569+
GenericSignature sig,
570+
const ValueDecl *forDecl);
524571
void appendSymbolicReference(SymbolicReferent referent);
525572

526573
void appendOpaqueDeclName(const OpaqueTypeDecl *opaqueDecl);

include/swift/AST/Types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6584,6 +6584,8 @@ inline bool TypeBase::isClassExistentialType() {
65846584
return pt->requiresClass();
65856585
if (auto pct = dyn_cast<ProtocolCompositionType>(T))
65866586
return pct->requiresClass();
6587+
if (auto ppt = dyn_cast<ParameterizedProtocolType>(T))
6588+
return ppt->requiresClass();
65876589
if (auto existential = dyn_cast<ExistentialType>(T))
65886590
return existential->requiresClass();
65896591
return false;

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ NODE(BackDeploymentThunk)
340340
NODE(BackDeploymentFallback)
341341
NODE(ExtendedExistentialTypeShape)
342342
NODE(Uniquable)
343+
NODE(UniqueExtendedExistentialTypeShapeSymbolicReference)
344+
NODE(NonUniqueExtendedExistentialTypeShapeSymbolicReference)
345+
NODE(SymbolicExtendedExistentialType)
343346

344347
#undef CONTEXT_NODE
345348
#undef NODE

include/swift/Demangling/Demangler.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,10 @@ enum class SymbolicReferenceKind : uint8_t {
347347
/// A symbolic reference to an accessor function, which can be executed in
348348
/// the process to get a pointer to the referenced entity.
349349
AccessorFunctionReference,
350+
/// A symbolic reference to a unique extended existential type shape.
351+
UniqueExtendedExistentialTypeShape,
352+
/// A symbolic reference to a non-unique extended existential type shape.
353+
NonUniqueExtendedExistentialTypeShape,
350354
};
351355

352356
using SymbolicReferenceResolver_t = NodePointer (SymbolicReferenceKind,
@@ -520,6 +524,7 @@ class Demangler : public NodeFactory {
520524
const Vector<NodePointer> &TypeLists,
521525
size_t TypeListIdx);
522526
NodePointer popAnyProtocolConformanceList();
527+
NodePointer popRetroactiveConformances();
523528
NodePointer demangleRetroactiveConformance();
524529
NodePointer demangleInitializer();
525530
NodePointer demangleImplParamConvention(Node::Kind ConvKind);
@@ -534,6 +539,7 @@ class Demangler : public NodeFactory {
534539
NodePointer demangleAssociatedTypeSimple(NodePointer GenericParamIdx);
535540
NodePointer demangleAssociatedTypeCompound(NodePointer GenericParamIdx);
536541
NodePointer demangleExtendedExistentialShape(char kind);
542+
NodePointer demangleSymbolicExtendedExistentialType();
537543

538544
NodePointer popAssocTypeName();
539545
NodePointer popAssocTypePath();

include/swift/Demangling/TypeDecoder.h

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -547,18 +547,8 @@ class TypeDecoder {
547547
Node->getNumChildren());
548548

549549
llvm::SmallVector<BuiltType, 8> args;
550-
551-
const auto &genericArgs = Node->getChild(1);
552-
if (genericArgs->getKind() != NodeKind::TypeList)
553-
return MAKE_NODE_TYPE_ERROR0(genericArgs, "is not TypeList");
554-
555-
for (auto genericArg : *genericArgs) {
556-
auto paramType = decodeMangledType(genericArg, depth + 1,
557-
/*forRequirement=*/false);
558-
if (paramType.isError())
559-
return paramType;
560-
args.push_back(paramType.getType());
561-
}
550+
if (auto error = decodeGenericArgs(Node->getChild(1), depth+1, args))
551+
return *error;
562552

563553
auto ChildNode = Node->getChild(0);
564554
if (ChildNode->getKind() == NodeKind::Type &&
@@ -665,6 +655,18 @@ class TypeDecoder {
665655
"had a different kind when re-checked");
666656
}
667657
}
658+
case NodeKind::SymbolicExtendedExistentialType: {
659+
if (Node->getNumChildren() < 2)
660+
return MAKE_NODE_TYPE_ERROR0(Node, "not enough children");
661+
662+
auto shapeNode = Node->getChild(0);
663+
llvm::SmallVector<BuiltType, 8> args;
664+
if (auto error = decodeGenericArgs(Node->getChild(1), depth + 1, args))
665+
return *error;
666+
667+
return Builder.createSymbolicExtendedExistentialType(shapeNode, args);
668+
}
669+
668670
case NodeKind::ProtocolList:
669671
case NodeKind::ProtocolListWithAnyObject:
670672
case NodeKind::ProtocolListWithClass: {
@@ -1380,6 +1382,22 @@ return {}; // Not Implemented!
13801382
return false;
13811383
}
13821384

1385+
llvm::Optional<TypeLookupError>
1386+
decodeGenericArgs(Demangle::NodePointer node, unsigned depth,
1387+
llvm::SmallVectorImpl<BuiltType> &args) {
1388+
if (node->getKind() != NodeKind::TypeList)
1389+
return MAKE_NODE_TYPE_ERROR0(node, "is not TypeList");
1390+
1391+
for (auto genericArg : *node) {
1392+
auto paramType = decodeMangledType(genericArg, depth,
1393+
/*forRequirement=*/false);
1394+
if (paramType.isError())
1395+
return *paramType.getError();
1396+
args.push_back(paramType.getType());
1397+
}
1398+
return llvm::None;
1399+
}
1400+
13831401
llvm::Optional<TypeLookupError>
13841402
decodeMangledTypeDecl(Demangle::NodePointer node, unsigned depth,
13851403
BuiltTypeDecl &typeDecl, BuiltType &parent,

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,13 @@ class TypeRefBuilder {
750750
return ConstrainedExistentialTypeRef::create(*this, baseProto, constraints);
751751
}
752752

753+
const TypeRef *
754+
createSymbolicExtendedExistentialType(NodePointer shapeNode,
755+
llvm::ArrayRef<const TypeRef *> args) {
756+
// Can't handle this here.
757+
return nullptr;
758+
}
759+
753760
const ExistentialMetatypeTypeRef *createExistentialMetatypeType(
754761
const TypeRef *instance,
755762
llvm::Optional<Demangle::ImplMetatypeRepresentation> repr = None) {

include/swift/Remote/MetadataReader.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,20 @@ class MetadataReader {
459459
// execute code in the target process to resolve it from here.
460460
return nullptr;
461461
}
462+
case Demangle::SymbolicReferenceKind::UniqueExtendedExistentialTypeShape: {
463+
// The symbolic reference points at a unique extended
464+
// existential type shape.
465+
return dem.createNode(
466+
Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference,
467+
resolved.getResolvedAddress().getAddressData());
468+
}
469+
case Demangle::SymbolicReferenceKind::NonUniqueExtendedExistentialTypeShape: {
470+
// The symbolic reference points at a non-unique extended
471+
// existential type shape.
472+
return dem.createNode(
473+
Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference,
474+
resolved.getResolvedAddress().getAddressData());
475+
}
462476
}
463477

464478
return nullptr;
@@ -1976,8 +1990,25 @@ class MetadataReader {
19761990
}
19771991
case MetadataKind::ExistentialMetatype:
19781992
return _readMetadata<TargetExistentialMetatypeMetadata>(address);
1979-
case MetadataKind::ExtendedExistential:
1980-
return _readMetadata<TargetExtendedExistentialTypeMetadata>(address);
1993+
case MetadataKind::ExtendedExistential: {
1994+
// We need to read the shape in order to figure out how large
1995+
// the generalization arguments are.
1996+
StoredPointer shapeAddress = address + sizeof(StoredPointer);
1997+
StoredSignedPointer signedShapePtr;
1998+
if (!Reader->readInteger(RemoteAddress(shapeAddress), &signedShapePtr))
1999+
return nullptr;
2000+
auto shapePtr = stripSignedPointer(signedShapePtr);
2001+
2002+
auto shape = readShape(shapePtr);
2003+
if (!shape)
2004+
return nullptr;
2005+
2006+
auto totalSize =
2007+
sizeof(TargetExtendedExistentialTypeMetadata<Runtime>)
2008+
+ shape->getGeneralizationSignature().getArgumentLayoutSizeInWords()
2009+
* sizeof(StoredPointer);
2010+
return _readMetadata(address, totalSize);
2011+
}
19812012
case MetadataKind::ForeignClass:
19822013
return _readMetadata<TargetForeignClassMetadata>(address);
19832014
case MetadataKind::ForeignReferenceType:
@@ -2000,12 +2031,12 @@ class MetadataReader {
20002031
totalSize += flags.getNumParameters() * sizeof(uint32_t);
20012032

20022033
if (flags.isDifferentiable())
2003-
totalSize = roundUpToAlignment(totalSize, sizeof(void *)) +
2034+
totalSize = roundUpToAlignment(totalSize, sizeof(StoredPointer)) +
20042035
sizeof(TargetFunctionMetadataDifferentiabilityKind<
20052036
typename Runtime::StoredSize>);
20062037

20072038
return _readMetadata(address,
2008-
roundUpToAlignment(totalSize, sizeof(void *)));
2039+
roundUpToAlignment(totalSize, sizeof(StoredPointer)));
20092040
}
20102041
case MetadataKind::HeapGenericLocalVariable:
20112042
return _readMetadata<TargetGenericBoxHeapMetadata>(address);

lib/AST/ASTDemangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,11 @@ Type ASTBuilder::createConstrainedExistentialType(
659659
return ExistentialType::get(constrainedBase);
660660
}
661661

662+
Type ASTBuilder::createSymbolicExtendedExistentialType(NodePointer shapeNode,
663+
ArrayRef<Type> genArgs) {
664+
return Type();
665+
}
666+
662667
Type ASTBuilder::createMetatypeType(Type instance,
663668
Optional<Demangle::ImplMetatypeRepresentation> repr) {
664669
if (!repr)

lib/AST/ASTMangler.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,18 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
12331233

12341234
case TypeKind::ExistentialMetatype: {
12351235
ExistentialMetatypeType *EMT = cast<ExistentialMetatypeType>(tybase);
1236+
1237+
// ExtendedExistentialTypeShapes consider existential metatypes to
1238+
// be part of the existential, so if we're symbolically referencing
1239+
// shapes, we need to handle that at this level.
1240+
if (EMT->hasParameterizedExistential()) {
1241+
auto referent = SymbolicReferent::forExtendedExistentialTypeShape(EMT);
1242+
if (canSymbolicReference(referent)) {
1243+
appendSymbolicExtendedExistentialType(referent, EMT, sig, forDecl);
1244+
return;
1245+
}
1246+
}
1247+
12361248
if (EMT->getInstanceType()->isExistentialType() &&
12371249
EMT->hasParameterizedExistential())
12381250
appendConstrainedExistential(EMT->getInstanceType(), sig, forDecl);
@@ -1293,7 +1305,13 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
12931305

12941306
case TypeKind::Existential: {
12951307
auto *ET = cast<ExistentialType>(tybase);
1296-
if (tybase->hasParameterizedExistential()) {
1308+
if (ET->hasParameterizedExistential()) {
1309+
auto referent = SymbolicReferent::forExtendedExistentialTypeShape(ET);
1310+
if (canSymbolicReference(referent)) {
1311+
appendSymbolicExtendedExistentialType(referent, ET, sig, forDecl);
1312+
return;
1313+
}
1314+
12971315
return appendConstrainedExistential(ET->getConstraintType(), sig,
12981316
forDecl);
12991317
}
@@ -1753,6 +1771,36 @@ void ASTMangler::appendRetroactiveConformances(Type type, GenericSignature sig)
17531771
appendRetroactiveConformances(subMap, sig, module);
17541772
}
17551773

1774+
void ASTMangler::appendSymbolicExtendedExistentialType(
1775+
SymbolicReferent shapeReferent,
1776+
Type type,
1777+
GenericSignature sig,
1778+
const ValueDecl *forDecl) {
1779+
assert(shapeReferent.getKind() ==
1780+
SymbolicReferent::ExtendedExistentialTypeShape);
1781+
assert(canSymbolicReference(shapeReferent));
1782+
assert(type->isAnyExistentialType());
1783+
1784+
// type ::= symbolic-extended-existential-type-shape
1785+
// type* retroactive-conformance* 'Xj'
1786+
1787+
appendSymbolicReference(shapeReferent);
1788+
1789+
auto genInfo = ExistentialTypeGeneralization::get(type);
1790+
if (genInfo.Generalization) {
1791+
for (auto argType : genInfo.Generalization.getReplacementTypes())
1792+
appendType(argType, sig, forDecl);
1793+
1794+
// What module should be used here? The existential isn't anchored
1795+
// to any given module; we should just treat conformances as
1796+
// retroactive if they're "objectively" retroactive.
1797+
appendRetroactiveConformances(genInfo.Generalization, sig,
1798+
/*from module*/ nullptr);
1799+
}
1800+
1801+
appendOperator("Xj");
1802+
}
1803+
17561804
static char getParamConvention(ParameterConvention conv) {
17571805
// @in and @out are mangled the same because they're put in
17581806
// different places.

lib/AST/ExistentialGeneralization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
267267

268268
ExistentialTypeGeneralization
269269
ExistentialTypeGeneralization::get(Type rawType) {
270-
assert(rawType->isExistentialType());
270+
assert(rawType->isAnyExistentialType());
271271
assert(!rawType->hasTypeParameter());
272272

273273
// Canonicalize. We need to generalize the canonical shape of the

0 commit comments

Comments
 (0)