Skip to content

Commit a7f0fff

Browse files
authored
Merge pull request #42328 from rjmccall/build-constrained-existential-metadata-5.7
[5.7] IR generation for constrained existentials
2 parents d0691e3 + 5783b0c commit a7f0fff

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1678
-261
lines changed

docs/ABI/Mangling.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ Globals
189189
global ::= global 'MN' // noncanonical specialized generic type metadata for global
190190
global ::= global 'Mz' // canonical specialized generic type metadata caching token
191191

192+
global ::= global 'Mq' // global with a uniquing prefix
193+
192194
#if SWIFT_RUNTIME_VERSION >= 5.4
193195
global ::= context (decl-name '_')+ 'WZ' // global variable one-time initialization function
194196
global ::= context (decl-name '_')+ 'Wz' // global variable one-time initialization token
@@ -914,6 +916,23 @@ than the module of the conforming type or the conformed-to protocol), it is
914916
mangled with its offset into the set of conformance requirements, the
915917
root protocol conformance, and the suffix 'g'.
916918

919+
::
920+
921+
// No generalization signature, no type expression.
922+
extended-existential-shape ::= generic-signature 'Xg' extended-existential-value-storage
923+
924+
// Generalization signature (the second one), no type expression.
925+
extended-existential-shape ::= generic-signature generic-signature 'XG' extended-existential-value-storage
926+
927+
// No generalization signature, type expression.
928+
extended-existential-shape ::= generic-signature type 'Xh' extended-existential-value-storage
929+
930+
// Generalization signature (the second one), type expression.
931+
extended-existential-shape ::= generic-signature generic-signature type 'Xh' extended-existential-value-storage
932+
933+
extended-existential-value-storage ::= 'o' // opaque
934+
extended-existential-value-storage ::= 'c' // class
935+
extended-existential-value-storage ::= 'm' // metatype
917936

918937
Identifiers
919938
~~~~~~~~~~~

include/swift/ABI/MetadataValues.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ class ExtendedExistentialTypeShapeFlags {
865865
(Data & ~SpecialKindMask) | (int_type(kind) << SpecialKindShift));
866866
}
867867
constexpr ExtendedExistentialTypeShapeFlags
868-
withHasTypeExpresssion(bool hasTypeExpression) const {
868+
withHasTypeExpression(bool hasTypeExpression) const {
869869
return ExtendedExistentialTypeShapeFlags(
870870
hasTypeExpression ? (Data | HasTypeExpression)
871871
: (Data & ~HasTypeExpression));

include/swift/AST/ExistentialLayout.h

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include "swift/Basic/ArrayRefView.h"
2121
#include "swift/AST/ASTContext.h"
22-
#include "swift/AST/Type.h"
22+
#include "swift/AST/Types.h"
2323

2424
namespace swift {
2525
class ProtocolDecl;
@@ -32,12 +32,12 @@ struct ExistentialLayout {
3232
ExistentialLayout() {
3333
hasExplicitAnyObject = false;
3434
containsNonObjCProtocol = false;
35-
singleProtocol = nullptr;
35+
containsParameterized = false;
3636
}
3737

38-
ExistentialLayout(ProtocolType *type);
39-
ExistentialLayout(ProtocolCompositionType *type);
40-
ExistentialLayout(ParameterizedProtocolType *type);
38+
ExistentialLayout(CanProtocolType type);
39+
ExistentialLayout(CanProtocolCompositionType type);
40+
ExistentialLayout(CanParameterizedProtocolType type);
4141

4242
/// The explicit superclass constraint, if any.
4343
Type explicitSuperclass;
@@ -48,6 +48,9 @@ struct ExistentialLayout {
4848
/// Whether any protocol members are non-@objc.
4949
bool containsNonObjCProtocol : 1;
5050

51+
/// Whether any protocol members are parameterized.s
52+
bool containsParameterized : 1;
53+
5154
/// Return the kind of this existential (class/error/opaque).
5255
Kind getKind() {
5356
if (requiresClass())
@@ -87,28 +90,17 @@ struct ExistentialLayout {
8790
/// constraints?
8891
bool isErrorExistential() const;
8992

90-
static inline ProtocolType *getProtocolType(const Type &Ty) {
91-
return cast<ProtocolType>(Ty.getPointer());
92-
}
93-
typedef ArrayRefView<Type,ProtocolType*,getProtocolType> ProtocolTypeArrayRef;
94-
95-
ProtocolTypeArrayRef getProtocols() const & {
96-
if (singleProtocol)
97-
return llvm::makeArrayRef(&singleProtocol, 1);
93+
ArrayRef<ProtocolDecl*> getProtocols() const & {
9894
return protocols;
9995
}
100-
/// The returned ArrayRef may point directly to \c this->singleProtocol, so
96+
/// The returned ArrayRef points to internal storage, so
10197
/// calling this on a temporary is likely to be incorrect.
102-
ProtocolTypeArrayRef getProtocols() const && = delete;
98+
ArrayRef<ProtocolDecl*> getProtocols() const && = delete;
10399

104100
LayoutConstraint getLayoutConstraint() const;
105101

106102
private:
107-
// The protocol from a ProtocolType
108-
Type singleProtocol;
109-
110-
/// Zero or more protocol constraints from a ProtocolCompositionType
111-
ArrayRef<Type> protocols;
103+
SmallVector<ProtocolDecl *, 4> protocols;
112104

113105
/// Zero or more primary associated type requirements from a
114106
/// ParameterizedProtocolType

include/swift/AST/IRGenOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,12 @@ struct PointerAuthOptions : clang::PointerAuthOptions {
189189

190190
/// The swift async context entry in the extended frame info.
191191
PointerAuthSchema AsyncContextExtendedFrameEntry;
192+
193+
/// Extended existential type shapes in flight.
194+
PointerAuthSchema ExtendedExistentialTypeShape;
195+
196+
/// Non-unique extended existential type shapes in flight.
197+
PointerAuthSchema NonUniqueExtendedExistentialTypeShape;
192198
};
193199

194200
enum class JITDebugArtifact : unsigned {

include/swift/AST/Types.h

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2768,6 +2768,7 @@ BEGIN_CAN_TYPE_WRAPPER(ExistentialMetatypeType, AnyMetatypeType)
27682768
MetatypeRepresentation repr) {
27692769
return CanExistentialMetatypeType(ExistentialMetatypeType::get(type, repr));
27702770
}
2771+
PROXY_CAN_TYPE_SIMPLE_GETTER(getExistentialInstanceType)
27712772
END_CAN_TYPE_WRAPPER(ExistentialMetatypeType, AnyMetatypeType)
27722773

27732774
/// ModuleType - This is the type given to a module value, e.g. the "Builtin" in
@@ -5254,6 +5255,9 @@ class ProtocolCompositionType final : public TypeBase,
52545255
}
52555256
};
52565257
BEGIN_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)
5258+
CanTypeArrayRef getMembers() const {
5259+
return CanTypeArrayRef(getPointer()->getMembers());
5260+
}
52575261
END_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)
52585262

52595263
/// ParameterizedProtocolType - A type that constrains one or more primary
@@ -5291,11 +5295,19 @@ class ParameterizedProtocolType final : public TypeBase,
52915295
return Base;
52925296
}
52935297

5298+
ProtocolDecl *getProtocol() const {
5299+
return Base->getDecl();
5300+
}
5301+
52945302
ArrayRef<Type> getArgs() const {
52955303
return {getTrailingObjects<Type>(),
52965304
Bits.ParameterizedProtocolType.ArgCount};
52975305
}
52985306

5307+
bool requiresClass() const {
5308+
return getBaseType()->requiresClass();
5309+
}
5310+
52995311
void getRequirements(Type baseType, SmallVectorImpl<Requirement> &reqs) const;
53005312

53015313
void Profile(llvm::FoldingSetNodeID &ID) {
@@ -5317,12 +5329,36 @@ class ParameterizedProtocolType final : public TypeBase,
53175329
RecursiveTypeProperties properties);
53185330
};
53195331
BEGIN_CAN_TYPE_WRAPPER(ParameterizedProtocolType, Type)
5320-
PROXY_CAN_TYPE_SIMPLE_GETTER(getBaseType)
5332+
CanProtocolType getBaseType() const {
5333+
return CanProtocolType(getPointer()->getBaseType());
5334+
}
53215335
CanTypeArrayRef getArgs() const {
53225336
return CanTypeArrayRef(getPointer()->getArgs());
53235337
}
53245338
END_CAN_TYPE_WRAPPER(ParameterizedProtocolType, Type)
53255339

5340+
/// The generalized shape of an existential type.
5341+
struct ExistentialTypeGeneralization {
5342+
/// The generalized existential type. May refer to type parameters
5343+
/// from the generalization signature.
5344+
Type Shape;
5345+
5346+
/// The generalization signature and substitutions.
5347+
SubstitutionMap Generalization;
5348+
5349+
/// Retrieve the generalization for the given existential type.
5350+
///
5351+
/// Substituting the generalization substitutions into the shape
5352+
/// should produce the original existential type.
5353+
///
5354+
/// If there is a generic type substitution which can turn existential
5355+
/// type A into existential type B, then:
5356+
/// - the generalized shape types of A and B must be equal and
5357+
/// - the generic signatures of the generalization substitutions of
5358+
/// A and B must be equal.
5359+
static ExistentialTypeGeneralization get(Type existentialType);
5360+
};
5361+
53265362
/// An existential type, spelled with \c any .
53275363
///
53285364
/// In Swift 5 mode, a plain protocol name in type
@@ -5348,6 +5384,9 @@ class ExistentialType final : public TypeBase {
53485384
if (auto composition = ConstraintType->getAs<ProtocolCompositionType>())
53495385
return composition->requiresClass();
53505386

5387+
if (auto paramProtocol = ConstraintType->getAs<ParameterizedProtocolType>())
5388+
return paramProtocol->requiresClass();
5389+
53515390
return false;
53525391
}
53535392

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,9 @@ NODE(CompileTimeConst)
335335
NODE(OpaqueReturnTypeIndexed)
336336
NODE(BackDeploymentThunk)
337337
NODE(BackDeploymentFallback)
338+
NODE(ExtendedExistentialTypeShape)
339+
NODE(ExtendedExistentialValueStorage)
340+
NODE(Uniquable)
338341

339342
#undef CONTEXT_NODE
340343
#undef NODE

include/swift/Demangling/Demangler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ class Demangler : public NodeFactory {
529529
NodePointer demangleArchetype();
530530
NodePointer demangleAssociatedTypeSimple(NodePointer GenericParamIdx);
531531
NodePointer demangleAssociatedTypeCompound(NodePointer GenericParamIdx);
532+
NodePointer demangleExtendedExistentialShape(char kind);
532533

533534
NodePointer popAssocTypeName();
534535
NodePointer popAssocTypePath();

include/swift/IRGen/Linking.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ class LinkEntity {
119119
// This field appears in SILFunction.
120120
IsDynamicallyReplaceableImplShift = 8,
121121
IsDynamicallyReplaceableImplMask = ~KindMask,
122+
123+
// These fields appear in ExtendedExistentialTypeShape.
124+
ExtendedExistentialIsUniqueShift = 8,
125+
ExtendedExistentialIsUniqueMask = 0x100,
126+
ExtendedExistentialIsSharedShift = 9,
127+
ExtendedExistentialIsSharedMask = 0x200,
128+
ExtendedExistentialMetatypeDepthShift = 10,
129+
ExtendedExistentialMetatypeDepthMask =
130+
~(KindMask | ExtendedExistentialIsUniqueMask |
131+
ExtendedExistentialIsSharedMask),
122132
};
123133
#define LINKENTITY_SET_FIELD(field, value) (value << field##Shift)
124134
#define LINKENTITY_GET_FIELD(value, field) ((value & field##Mask) >> field##Shift)
@@ -493,6 +503,11 @@ class LinkEntity {
493503
/// Accessible function record, which describes a function that can be
494504
/// looked up by name by the runtime.
495505
AccessibleFunctionRecord,
506+
507+
/// Extended existential type shape.
508+
/// Pointer is the (generalized) existential type.
509+
/// SecondaryPointer is the GenericSignatureImpl*.
510+
ExtendedExistentialTypeShape,
496511
};
497512
friend struct llvm::DenseMapInfo<LinkEntity>;
498513

@@ -1352,6 +1367,24 @@ class LinkEntity {
13521367
return entity;
13531368
}
13541369

1370+
static LinkEntity forExtendedExistentialTypeShape(CanGenericSignature genSig,
1371+
CanExistentialType
1372+
existentialType,
1373+
unsigned metatypeDepth,
1374+
bool isUnique,
1375+
bool isShared) {
1376+
LinkEntity entity;
1377+
entity.Pointer = existentialType.getPointer();
1378+
entity.SecondaryPointer =
1379+
const_cast<GenericSignatureImpl*>(genSig.getPointer());
1380+
entity.Data =
1381+
LINKENTITY_SET_FIELD(Kind, unsigned(Kind::ExtendedExistentialTypeShape))
1382+
| LINKENTITY_SET_FIELD(ExtendedExistentialIsUnique, unsigned(isUnique))
1383+
| LINKENTITY_SET_FIELD(ExtendedExistentialIsShared, unsigned(isShared))
1384+
| LINKENTITY_SET_FIELD(ExtendedExistentialMetatypeDepth, metatypeDepth);
1385+
return entity;
1386+
}
1387+
13551388
void mangle(llvm::raw_ostream &out) const;
13561389
void mangle(SmallVectorImpl<char> &buffer) const;
13571390
std::string mangleAsString() const;
@@ -1445,6 +1478,32 @@ class LinkEntity {
14451478
SecondaryPointer);
14461479
}
14471480

1481+
CanGenericSignature getExtendedExistentialTypeShapeGenSig() const {
1482+
assert(getKind() == Kind::ExtendedExistentialTypeShape);
1483+
return CanGenericSignature(
1484+
reinterpret_cast<const GenericSignatureImpl*>(SecondaryPointer));
1485+
}
1486+
1487+
CanExistentialType getExtendedExistentialTypeShapeType() const {
1488+
assert(getKind() == Kind::ExtendedExistentialTypeShape);
1489+
return cast<ExistentialType>(CanType(reinterpret_cast<TypeBase*>(Pointer)));
1490+
}
1491+
1492+
bool isExtendedExistentialTypeShapeUnique() const {
1493+
assert(getKind() == Kind::ExtendedExistentialTypeShape);
1494+
return LINKENTITY_GET_FIELD(Data, ExtendedExistentialIsUnique);
1495+
}
1496+
1497+
bool isExtendedExistentialTypeShapeShared() const {
1498+
assert(getKind() == Kind::ExtendedExistentialTypeShape);
1499+
return LINKENTITY_GET_FIELD(Data, ExtendedExistentialIsShared);
1500+
}
1501+
1502+
unsigned getExtendedExistentialTypeShapeMetatypeDepth() const {
1503+
assert(getKind() == Kind::ExtendedExistentialTypeShape);
1504+
return LINKENTITY_GET_FIELD(Data, ExtendedExistentialMetatypeDepth);
1505+
}
1506+
14481507
bool isDynamicallyReplaceable() const {
14491508
assert(getKind() == Kind::SILFunction);
14501509
return LINKENTITY_GET_FIELD(Data, IsDynamicallyReplaceableImpl);

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,36 @@ FUNCTION(GetExistentialMetadata,
10761076
ATTRS(NoUnwind, ReadOnly, WillReturn),
10771077
EFFECT(MetaData)) // ?
10781078

1079+
// const ExtendedExistentialTypeShape *
1080+
// swift_getExtendedExistentialTypeShape(
1081+
// const NonUniqueExtendedExistentialTypeShape *nonUnique);
1082+
FUNCTION(GetExtendedExistentialTypeShape,
1083+
swift_getExtendedExistentialTypeShape, C_CC, AlwaysAvailable,
1084+
RETURNS(TypeMetadataPtrTy),
1085+
ARGS(Int8PtrTy, Int8PtrPtrTy),
1086+
ATTRS(NoUnwind, ArgMemOnly, WillReturn),
1087+
EFFECT(MetaData)) // ?
1088+
1089+
// Metadata *swift_getExtendedExistentialTypeMetadata(
1090+
// const NonUniqueExtendedExistentialTypeShape *shape,
1091+
// const void * const *generalizationArgs);
1092+
FUNCTION(GetExtendedExistentialTypeMetadata,
1093+
swift_getExtendedExistentialTypeMetadata, C_CC, AlwaysAvailable,
1094+
RETURNS(TypeMetadataPtrTy),
1095+
ARGS(Int8PtrTy, Int8PtrPtrTy),
1096+
ATTRS(NoUnwind, ArgMemOnly, WillReturn),
1097+
EFFECT(MetaData)) // ?
1098+
1099+
// Metadata *swift_getExtendedExistentialTypeMetadata_unique(
1100+
// const ExtendedExistentialTypeShape *shape,
1101+
// const void * const *generalizationArgs);
1102+
FUNCTION(GetExtendedExistentialTypeMetadataUnique,
1103+
swift_getExtendedExistentialTypeMetadata_unique, C_CC, AlwaysAvailable,
1104+
RETURNS(TypeMetadataPtrTy),
1105+
ARGS(Int8PtrTy, Int8PtrPtrTy),
1106+
ATTRS(NoUnwind, ArgMemOnly, WillReturn),
1107+
EFFECT(MetaData)) // ?
1108+
10791109
// Metadata *swift_relocateClassMetadata(TypeContextDescriptor *descriptor,
10801110
// const void *pattern);
10811111
FUNCTION(RelocateClassMetadata,

include/swift/SIL/FormalLinkage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
namespace swift {
1717

18+
class CanGenericSignature;
1819
class CanType;
1920
class RootProtocolConformance;
2021
class ValueDecl;
@@ -44,6 +45,8 @@ enum class FormalLinkage {
4445

4546
FormalLinkage getDeclLinkage(const ValueDecl *decl);
4647
FormalLinkage getTypeLinkage(CanType formalType);
48+
FormalLinkage getTypeLinkage_correct(CanType formalType);
49+
FormalLinkage getGenericSignatureLinkage(CanGenericSignature signature);
4750
SILLinkage getSILLinkage(FormalLinkage linkage,
4851
ForDefinition_t forDefinition);
4952
SILLinkage

lib/AST/ASTMangler.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,8 +1045,7 @@ void ASTMangler::appendExistentialLayout(
10451045
bool First = true;
10461046
bool DroppedRequiresClass = false;
10471047
bool SawRequiresClass = false;
1048-
for (Type protoTy : layout.getProtocols()) {
1049-
auto proto = protoTy->castTo<ProtocolType>()->getDecl();
1048+
for (auto proto : layout.getProtocols()) {
10501049
// If we aren't allowed to emit marker protocols, suppress them here.
10511050
if (!AllowMarkerProtocols && proto->isMarkerProtocol()) {
10521051
if (proto->requiresClass())
@@ -1058,7 +1057,7 @@ void ASTMangler::appendExistentialLayout(
10581057
if (proto->requiresClass())
10591058
SawRequiresClass = true;
10601059

1061-
appendProtocolName(protoTy->castTo<ProtocolType>()->getDecl());
1060+
appendProtocolName(proto);
10621061
appendListSeparator(First);
10631062
}
10641063
if (First)
@@ -1258,7 +1257,8 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
12581257

12591258
case TypeKind::Protocol: {
12601259
return appendExistentialLayout(
1261-
ExistentialLayout(cast<ProtocolType>(tybase)), sig, forDecl);
1260+
ExistentialLayout(CanProtocolType(cast<ProtocolType>(tybase))),
1261+
sig, forDecl);
12621262
}
12631263

12641264
case TypeKind::ProtocolComposition: {

0 commit comments

Comments
 (0)