Skip to content

Commit ef6c0d7

Browse files
rjmccalltkremenek
authored andcommitted
Explicitly represent "pseudo-generic" functions in SIL, which do (#2821)
not have access to their type arguments at runtime. Use this to fix the emission of native thunks for imported ObjC-generic initializers, since they may need to perform bridging. For now, pseudo-genericity is all-or-nothing, but we may want to make it apply only to certain type arguments. Also, clean up some code that was using dead mangling nodes.
1 parent 30dbf22 commit ef6c0d7

26 files changed

+207
-246
lines changed

docs/ABI.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,7 @@ mangled in to disambiguate.
10161016
impl-function-attribute ::= 'Cw' // compatible with protocol witness
10171017
impl-function-attribute ::= 'N' // noreturn
10181018
impl-function-attribute ::= 'G' // generic
1019+
impl-function-attribute ::= 'g' // pseudogeneric
10191020
impl-parameter ::= impl-convention type
10201021
impl-result ::= impl-convention type
10211022

@@ -1025,7 +1026,8 @@ implementation details of a function type.
10251026

10261027
Any ``<impl-function-attribute>`` productions must appear in the order
10271028
in which they are specified above: e.g. a noreturn C function is
1028-
mangled with ``CcN``.
1029+
mangled with ``CcN``. ``g`` and ``G`` are exclusive and mark the presence
1030+
of a generic signature immediately following.
10291031

10301032
Note that the convention and function-attribute productions do not
10311033
need to be disambiguated from the start of a ``<type>``.

include/swift/AST/Attr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ TYPE_ATTR(callee_guaranteed)
5757
TYPE_ATTR(objc_metatype)
5858
TYPE_ATTR(opened)
5959
TYPE_ATTR(deallocating)
60+
TYPE_ATTR(pseudogeneric)
6061

6162
// SIL metatype attributes.
6263
TYPE_ATTR(thin)

include/swift/AST/Types.h

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2880,11 +2880,12 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
28802880
// you'll need to adjust both the Bits field below and
28812881
// BaseType::AnyFunctionTypeBits.
28822882

2883-
// |representation|noReturn|
2884-
// | 0 .. 3 | 4 |
2883+
// |representation|noReturn|pseudogeneric|
2884+
// | 0 .. 3 | 4 | 5 |
28852885
//
28862886
enum : uint16_t { RepresentationMask = 0x00F };
28872887
enum : uint16_t { NoReturnMask = 0x010 };
2888+
enum : uint16_t { PseudogenericMask = 0x020 };
28882889

28892890
uint16_t Bits;
28902891

@@ -2897,12 +2898,20 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
28972898
ExtInfo() : Bits(0) { }
28982899

28992900
// Constructor for polymorphic type.
2900-
ExtInfo(Representation Rep, bool IsNoReturn) {
2901-
Bits = ((unsigned) Rep) |
2902-
(IsNoReturn ? NoReturnMask : 0);
2901+
ExtInfo(Representation rep, bool isNoReturn, bool isPseudogeneric) {
2902+
Bits = ((unsigned) rep) |
2903+
(isNoReturn ? NoReturnMask : 0) |
2904+
(isPseudogeneric ? PseudogenericMask : 0);
29032905
}
29042906

2907+
/// Is this function pseudo-generic? A pseudo-generic function
2908+
/// is not permitted to dynamically depend on its type arguments.
2909+
bool isPseudogeneric() const { return Bits & PseudogenericMask; }
2910+
2911+
/// Do functions of this type return normally?
29052912
bool isNoReturn() const { return Bits & NoReturnMask; }
2913+
2914+
/// What is the abstract representation of this function value?
29062915
Representation getRepresentation() const {
29072916
return Representation(Bits & RepresentationMask);
29082917
}
@@ -2965,6 +2974,12 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
29652974
else
29662975
return ExtInfo(Bits & ~NoReturnMask);
29672976
}
2977+
ExtInfo withIsPseudogeneric(bool isPseudogeneric = true) const {
2978+
if (isPseudogeneric)
2979+
return ExtInfo(Bits | PseudogenericMask);
2980+
else
2981+
return ExtInfo(Bits & ~PseudogenericMask);
2982+
}
29682983

29692984
uint16_t getFuncAttrKey() const {
29702985
return Bits;
@@ -3208,6 +3223,10 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
32083223
return getExtInfo().isNoReturn();
32093224
}
32103225

3226+
bool isPseudogeneric() const {
3227+
return getExtInfo().isPseudogeneric();
3228+
}
3229+
32113230
CanSILFunctionType substGenericArgs(SILModule &silModule,
32123231
ModuleDecl *astModule,
32133232
ArrayRef<Substitution> subs);

include/swift/Basic/DemangleNodes.def

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@ CONTEXT_NODE(Deallocator)
4444
NODE(DeclContext)
4545
CONTEXT_NODE(DefaultArgumentInitializer)
4646
NODE(DependentAssociatedTypeRef)
47-
NODE(DependentGenericSignature)
48-
NODE(DependentGenericParamCount)
4947
NODE(DependentGenericConformanceRequirement)
48+
NODE(DependentGenericParamCount)
49+
NODE(DependentGenericParamType)
5050
NODE(DependentGenericSameTypeRequirement)
51+
NODE(DependentGenericSignature)
5152
NODE(DependentGenericType)
5253
NODE(DependentMemberType)
53-
NODE(DependentGenericParamType)
54+
NODE(DependentPseudogenericSignature)
5455
CONTEXT_NODE(Destructor)
5556
CONTEXT_NODE(DidSet)
5657
NODE(Directness)
@@ -70,13 +71,11 @@ NODE(FunctionSignatureSpecializationParam)
7071
NODE(FunctionSignatureSpecializationParamKind)
7172
NODE(FunctionSignatureSpecializationParamPayload)
7273
NODE(FunctionType)
73-
NODE(Generics)
7474
NODE(GenericProtocolWitnessTable)
7575
NODE(GenericProtocolWitnessTableInstantiationFunction)
7676
NODE(GenericSpecialization)
7777
NODE(GenericSpecializationNotReAbstracted)
7878
NODE(GenericSpecializationParam)
79-
NODE(GenericType)
8079
NODE(GenericTypeMetadataPattern)
8180
CONTEXT_NODE(Getter)
8281
NODE(Global)

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
5353
/// in source control, you should also update the comment to briefly
5454
/// describe what change you made. The content of this comment isn't important;
5555
/// it just ensures a conflict if two people change the module format.
56-
const uint16_t VERSION_MINOR = 249; // Last change: SIL clang decls
56+
const uint16_t VERSION_MINOR = 250; // Last change: SILFunctionType::isPseudogeneric
5757

5858
using DeclID = PointerEmbeddedInt<unsigned, 31>;
5959
using DeclIDField = BCFixed<31>;
@@ -702,6 +702,7 @@ namespace decls_block {
702702
ParameterConventionField, // callee convention
703703
SILFunctionTypeRepresentationField, // representation
704704
BCFixed<1>, // noreturn?
705+
BCFixed<1>, // pseudogeneric?
705706
BCFixed<1>, // error result?
706707
BCFixed<30>, // number of parameters
707708
BCFixed<30>, // number of results

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3721,6 +3721,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
37213721
}
37223722
}
37233723

3724+
if (info.isPseudogeneric())
3725+
Printer << "@pseudogeneric ";
3726+
37243727
if (info.isNoReturn())
37253728
Printer << "@noreturn ";
37263729
}

lib/AST/Mangle.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,7 @@ void Mangler::mangleType(Type type, unsigned uncurryLevel) {
11251125
// <impl-function-attribute> ::= 'Cm' // Swift method
11261126
// <impl-function-attribute> ::= 'CO' // ObjC method
11271127
// <impl-function-attribute> ::= 'N' // noreturn
1128+
// <impl-function-attribute> ::= 'g' // pseudogeneric
11281129
// <impl-function-attribute> ::= 'G' // generic
11291130
// <impl-parameter> ::= <impl-convention> <type>
11301131
// <impl-result> ::= <impl-convention> <type>
@@ -1188,7 +1189,7 @@ void Mangler::mangleType(Type type, unsigned uncurryLevel) {
11881189

11891190
if (fn->isNoReturn()) Buffer << 'N';
11901191
if (fn->isPolymorphic()) {
1191-
Buffer << 'G';
1192+
Buffer << (fn->isPseudogeneric() ? 'g' : 'G');
11921193
mangleGenericSignature(fn->getGenericSignature());
11931194
}
11941195
Buffer << '_';

lib/Basic/Demangle.cpp

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,8 +1514,11 @@ class Demangler {
15141514
return nodeType;
15151515
}
15161516

1517-
NodePointer demangleGenericSignature() {
1518-
auto sig = NodeFactory::create(Node::Kind::DependentGenericSignature);
1517+
NodePointer demangleGenericSignature(bool isPseudogeneric = false) {
1518+
auto sig =
1519+
NodeFactory::create(isPseudogeneric
1520+
? Node::Kind::DependentPseudogenericSignature
1521+
: Node::Kind::DependentGenericSignature);
15191522
// First read in the parameter counts at each depth.
15201523
Node::IndexType count = ~(Node::IndexType)0;
15211524

@@ -2106,8 +2109,10 @@ class Demangler {
21062109

21072110
// Enter a new generic context if this type is generic.
21082111
// FIXME: replace with std::optional, when we have it.
2109-
if (Mangled.nextIf('G')) {
2110-
NodePointer generics = demangleGenericSignature();
2112+
bool isPseudogeneric = false;
2113+
if (Mangled.nextIf('G') ||
2114+
(isPseudogeneric = Mangled.nextIf('g'))) {
2115+
NodePointer generics = demangleGenericSignature(isPseudogeneric);
21112116
if (!generics)
21122117
return nullptr;
21132118
type->addChild(generics);
@@ -2382,6 +2387,7 @@ class NodePrinter {
23822387
case Node::Kind::DependentGenericParamCount:
23832388
case Node::Kind::DependentGenericConformanceRequirement:
23842389
case Node::Kind::DependentGenericSameTypeRequirement:
2390+
case Node::Kind::DependentPseudogenericSignature:
23852391
case Node::Kind::Destructor:
23862392
case Node::Kind::DidSet:
23872393
case Node::Kind::DirectMethodReferenceAttribute:
@@ -2397,13 +2403,11 @@ class NodePrinter {
23972403
case Node::Kind::FunctionSignatureSpecializationParamKind:
23982404
case Node::Kind::FunctionSignatureSpecializationParamPayload:
23992405
case Node::Kind::FunctionType:
2400-
case Node::Kind::Generics:
24012406
case Node::Kind::GenericProtocolWitnessTable:
24022407
case Node::Kind::GenericProtocolWitnessTableInstantiationFunction:
24032408
case Node::Kind::GenericSpecialization:
24042409
case Node::Kind::GenericSpecializationNotReAbstracted:
24052410
case Node::Kind::GenericSpecializationParam:
2406-
case Node::Kind::GenericType:
24072411
case Node::Kind::GenericTypeMetadataPattern:
24082412
case Node::Kind::Getter:
24092413
case Node::Kind::Global:
@@ -2783,8 +2787,7 @@ static bool useColonForEntityType(NodePointer entity, NodePointer type) {
27832787
case Node::Kind::IVarDestroyer: {
27842788
// We expect to see a function type here, but if we don't, use the colon.
27852789
type = type->getChild(0);
2786-
while (type->getKind() == Node::Kind::GenericType ||
2787-
type->getKind() == Node::Kind::DependentGenericType)
2790+
while (type->getKind() == Node::Kind::DependentGenericType)
27882791
type = type->getChild(1)->getChild(0);
27892792
return (type->getKind() != Node::Kind::FunctionType &&
27902793
type->getKind() != Node::Kind::UncurriedFunctionType &&
@@ -2822,8 +2825,7 @@ void NodePrinter::printSimplifiedEntityType(NodePointer context,
28222825
type = type->getChild(0);
28232826

28242827
NodePointer generics;
2825-
if (type->getKind() == Node::Kind::GenericType ||
2826-
type->getKind() == Node::Kind::DependentGenericType) {
2828+
if (type->getKind() == Node::Kind::DependentGenericType) {
28272829
generics = type->getChild(0);
28282830
type = type->getChild(1)->getChild(0);
28292831
}
@@ -3430,20 +3432,6 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType)
34303432
Printer << ">";
34313433
return;
34323434
}
3433-
case Node::Kind::Generics: {
3434-
if (pointer->getNumChildren() == 0)
3435-
return;
3436-
Printer << "<";
3437-
print(pointer->getChild(0));
3438-
for (unsigned i = 1, e = pointer->getNumChildren(); i != e; ++i) {
3439-
auto child = pointer->getChild(i);
3440-
if (child->getKind() != Node::Kind::Archetype) break;
3441-
Printer << ", ";
3442-
print(child);
3443-
}
3444-
Printer << ">";
3445-
return;
3446-
}
34473435
case Node::Kind::Archetype: {
34483436
Printer << pointer->getText();
34493437
if (pointer->hasChildren()) {
@@ -3469,13 +3457,6 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType)
34693457
Printer << ")";
34703458
return;
34713459
}
3472-
case Node::Kind::GenericType: {
3473-
NodePointer atype_list = pointer->getChild(0);
3474-
NodePointer fct_type = pointer->getChild(1)->getChild(0);
3475-
print(atype_list);
3476-
print(fct_type);
3477-
return;
3478-
}
34793460
case Node::Kind::OwningAddressor:
34803461
printEntity(true, true, ".owningAddressor");
34813462
return;
@@ -3576,6 +3557,7 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType)
35763557
Printer << "<ERROR TYPE>";
35773558
return;
35783559

3560+
case Node::Kind::DependentPseudogenericSignature:
35793561
case Node::Kind::DependentGenericSignature: {
35803562
Printer << '<';
35813563

lib/Basic/Remangle.cpp

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ namespace {
305305
void mangleEntityContext(Node *node, EntityContext &ctx);
306306
void mangleEntityType(Node *node, EntityContext &ctx);
307307
void mangleEntityGenericType(Node *node, EntityContext &ctx);
308-
void mangleGenerics(Node *node, EntityContext &ctx);
309308

310309
bool trySubstitution(Node *node, SubstitutionEntry &entry);
311310
void addSubstitution(const SubstitutionEntry &entry);
@@ -955,9 +954,6 @@ void Remangler::mangleEntityType(Node *node, EntityContext &ctx) {
955954

956955
// Expand certain kinds of type within the entity context.
957956
switch (node->getKind()) {
958-
case Node::Kind::GenericType:
959-
mangleEntityGenericType(node, ctx);
960-
return;
961957
case Node::Kind::FunctionType:
962958
case Node::Kind::UncurriedFunctionType: {
963959
Out << (node->getKind() == Node::Kind::FunctionType ? 'F' : 'f');
@@ -1109,9 +1105,12 @@ void Remangler::mangleImplFunctionType(Node *node) {
11091105
i->get()->getKind() == Node::Kind::ImplFunctionAttribute; ++i) {
11101106
mangle(i->get()); // impl function attribute
11111107
}
1112-
EntityContext ctx(*this);
1113-
if (i != e && i->get()->getKind() == Node::Kind::Generics) {
1114-
mangleGenerics((i++)->get(), ctx);
1108+
if (i != e &&
1109+
(i->get()->getKind() == Node::Kind::DependentGenericSignature ||
1110+
i->get()->getKind() == Node::Kind::DependentPseudogenericSignature)) {
1111+
Out << (i->get()->getKind() == Node::Kind::DependentGenericSignature
1112+
? 'G' : 'g');
1113+
mangleDependentGenericSignature((i++)->get());
11151114
}
11161115
Out << '_';
11171116
for (; i != e && i->get()->getKind() == Node::Kind::ImplParameter; ++i) {
@@ -1294,19 +1293,8 @@ void Remangler::mangleDependentGenericType(Node *node) {
12941293
mangleChildNodes(node); // generic signature, type
12951294
}
12961295

1297-
void Remangler::mangleGenericType(Node *node) {
1298-
EntityContext ctx(*this);
1299-
mangleEntityGenericType(node, ctx);
1300-
}
1301-
1302-
void Remangler::mangleEntityGenericType(Node *node, EntityContext &ctx) {
1303-
assert(node->getKind() == Node::Kind::GenericType);
1304-
1305-
Out << 'U';
1306-
assert(node->getNumChildren() == 2);
1307-
1308-
mangleGenerics(node->begin()[0].get(), ctx);
1309-
mangleEntityType(node->begin()[1].get(), ctx);
1296+
void Remangler::mangleDependentPseudogenericSignature(Node *node) {
1297+
mangleDependentGenericSignature(node);
13101298
}
13111299

13121300
void Remangler::mangleDependentGenericSignature(Node *node) {
@@ -1378,31 +1366,6 @@ void Remangler::mangleConstrainedType(Node *node) {
13781366
}
13791367
}
13801368

1381-
void Remangler::mangleGenerics(Node *node) {
1382-
unreachable("found independent generics node?");
1383-
}
1384-
1385-
void Remangler::mangleGenerics(Node *node, EntityContext &ctx) {
1386-
assert(node->getKind() == Node::Kind::Generics);
1387-
1388-
unsigned absoluteDepth = ++AbsoluteArchetypeDepth;
1389-
1390-
auto i = node->begin(), e = node->end();
1391-
unsigned index = 0;
1392-
for (; i != e && i->get()->getKind() == Node::Kind::Archetype; ++i) {
1393-
auto child = i->get();
1394-
Archetypes[child->getText()] = ArchetypeInfo{index++, absoluteDepth};
1395-
mangle(child); // archetype
1396-
}
1397-
if (i != e) {
1398-
Out << 'U';
1399-
mangleNodes(i, e); // associated types
1400-
Out << '_';
1401-
} else {
1402-
Out << '_';
1403-
}
1404-
}
1405-
14061369
void Remangler::mangleArchetype(Node *node) {
14071370
if (node->hasChildren()) {
14081371
assert(node->getNumChildren() == 1);

0 commit comments

Comments
 (0)