Skip to content

Commit 970457b

Browse files
authored
Merge pull request #59845 from rjmccall/rjmccall/extended-existential-symbolic-mangling-5.7
[5.7] Implement symbolic demangling for extended existential metadata
2 parents 0abda20 + 75f2ea5 commit 970457b

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.
@@ -653,6 +658,10 @@ Types
653658
type ::= type assoc-type-list 'QX' // associated type relative to base `type`
654659
#endif
655660

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

include/swift/AST/ASTDemangler.h

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

125+
Type createSymbolicExtendedExistentialType(NodePointer shapeNode,
126+
ArrayRef<Type> genArgs);
127+
125128
Type createExistentialMetatypeType(Type instance,
126129
Optional<Demangle::ImplMetatypeRepresentation> repr=None);
127130

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
@@ -6529,6 +6529,8 @@ inline bool TypeBase::isClassExistentialType() {
65296529
return pt->requiresClass();
65306530
if (auto pct = dyn_cast<ProtocolCompositionType>(T))
65316531
return pct->requiresClass();
6532+
if (auto ppt = dyn_cast<ParameterizedProtocolType>(T))
6533+
return ppt->requiresClass();
65326534
if (auto existential = dyn_cast<ExistentialType>(T))
65336535
return existential->requiresClass();
65346536
return false;

include/swift/Demangling/DemangleNodes.def

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

343346
#undef CONTEXT_NODE
344347
#undef NODE

include/swift/Demangling/Demangler.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ enum class SymbolicReferenceKind : uint8_t {
343343
/// A symbolic reference to an accessor function, which can be executed in
344344
/// the process to get a pointer to the referenced entity.
345345
AccessorFunctionReference,
346+
/// A symbolic reference to a unique extended existential type shape.
347+
UniqueExtendedExistentialTypeShape,
348+
/// A symbolic reference to a non-unique extended existential type shape.
349+
NonUniqueExtendedExistentialTypeShape,
346350
};
347351

348352
using SymbolicReferenceResolver_t = NodePointer (SymbolicReferenceKind,
@@ -516,6 +520,7 @@ class Demangler : public NodeFactory {
516520
const Vector<NodePointer> &TypeLists,
517521
size_t TypeListIdx);
518522
NodePointer popAnyProtocolConformanceList();
523+
NodePointer popRetroactiveConformances();
519524
NodePointer demangleRetroactiveConformance();
520525
NodePointer demangleInitializer();
521526
NodePointer demangleImplParamConvention(Node::Kind ConvKind);
@@ -530,6 +535,7 @@ class Demangler : public NodeFactory {
530535
NodePointer demangleAssociatedTypeSimple(NodePointer GenericParamIdx);
531536
NodePointer demangleAssociatedTypeCompound(NodePointer GenericParamIdx);
532537
NodePointer demangleExtendedExistentialShape(char kind);
538+
NodePointer demangleSymbolicExtendedExistentialType();
533539

534540
NodePointer popAssocTypeName();
535541
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
@@ -658,6 +658,13 @@ class TypeRefBuilder {
658658
return ConstrainedExistentialTypeRef::create(*this, baseProto, constraints);
659659
}
660660

661+
const TypeRef *
662+
createSymbolicExtendedExistentialType(NodePointer shapeNode,
663+
llvm::ArrayRef<const TypeRef *> args) {
664+
// Can't handle this here.
665+
return nullptr;
666+
}
667+
661668
const ExistentialMetatypeTypeRef *createExistentialMetatypeType(
662669
const TypeRef *instance,
663670
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
@@ -458,6 +458,20 @@ class MetadataReader {
458458
// execute code in the target process to resolve it from here.
459459
return nullptr;
460460
}
461+
case Demangle::SymbolicReferenceKind::UniqueExtendedExistentialTypeShape: {
462+
// The symbolic reference points at a unique extended
463+
// existential type shape.
464+
return dem.createNode(
465+
Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference,
466+
resolved.getResolvedAddress().getAddressData());
467+
}
468+
case Demangle::SymbolicReferenceKind::NonUniqueExtendedExistentialTypeShape: {
469+
// The symbolic reference points at a non-unique extended
470+
// existential type shape.
471+
return dem.createNode(
472+
Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference,
473+
resolved.getResolvedAddress().getAddressData());
474+
}
461475
}
462476

463477
return nullptr;
@@ -1974,8 +1988,25 @@ class MetadataReader {
19741988
}
19751989
case MetadataKind::ExistentialMetatype:
19761990
return _readMetadata<TargetExistentialMetatypeMetadata>(address);
1977-
case MetadataKind::ExtendedExistential:
1978-
return _readMetadata<TargetExtendedExistentialTypeMetadata>(address);
1991+
case MetadataKind::ExtendedExistential: {
1992+
// We need to read the shape in order to figure out how large
1993+
// the generalization arguments are.
1994+
StoredPointer shapeAddress = address + sizeof(StoredPointer);
1995+
StoredSignedPointer signedShapePtr;
1996+
if (!Reader->readInteger(RemoteAddress(shapeAddress), &signedShapePtr))
1997+
return nullptr;
1998+
auto shapePtr = stripSignedPointer(signedShapePtr);
1999+
2000+
auto shape = readShape(shapePtr);
2001+
if (!shape)
2002+
return nullptr;
2003+
2004+
auto totalSize =
2005+
sizeof(TargetExtendedExistentialTypeMetadata<Runtime>)
2006+
+ shape->getGeneralizationSignature().getArgumentLayoutSizeInWords()
2007+
* sizeof(StoredPointer);
2008+
return _readMetadata(address, totalSize);
2009+
}
19792010
case MetadataKind::ForeignClass:
19802011
return _readMetadata<TargetForeignClassMetadata>(address);
19812012
case MetadataKind::Function: {
@@ -1996,12 +2027,12 @@ class MetadataReader {
19962027
totalSize += flags.getNumParameters() * sizeof(uint32_t);
19972028

19982029
if (flags.isDifferentiable())
1999-
totalSize = roundUpToAlignment(totalSize, sizeof(void *)) +
2030+
totalSize = roundUpToAlignment(totalSize, sizeof(StoredPointer)) +
20002031
sizeof(TargetFunctionMetadataDifferentiabilityKind<
20012032
typename Runtime::StoredSize>);
20022033

20032034
return _readMetadata(address,
2004-
roundUpToAlignment(totalSize, sizeof(void *)));
2035+
roundUpToAlignment(totalSize, sizeof(StoredPointer)));
20052036
}
20062037
case MetadataKind::HeapGenericLocalVariable:
20072038
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
}
@@ -1751,6 +1769,36 @@ void ASTMangler::appendRetroactiveConformances(Type type, GenericSignature sig)
17511769
appendRetroactiveConformances(subMap, sig, module);
17521770
}
17531771

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

lib/AST/ExistentialGeneralization.cpp

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

267267
ExistentialTypeGeneralization
268268
ExistentialTypeGeneralization::get(Type rawType) {
269-
assert(rawType->isExistentialType());
269+
assert(rawType->isAnyExistentialType());
270270
assert(!rawType->hasTypeParameter());
271271

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

0 commit comments

Comments
 (0)