Skip to content

Commit daa85e1

Browse files
authored
Merge pull request #34986 from eeckstein/fix-generic-spec
GenericSpecializer: use an alternative mangling if the function has re-abstracted resilient type parameters.
2 parents 57b10ac + 9e43f49 commit daa85e1

18 files changed

+263
-128
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,8 @@ Function Specializations
10081008
::
10091009

10101010
specialization ::= type '_' type* 'Tg' SPEC-INFO // Generic re-abstracted specialization
1011+
specialization ::= type '_' type* 'TB' SPEC-INFO // Alternative mangling for generic re-abstracted specializations,
1012+
// used for functions with re-abstracted resilient parameter types.
10111013
specialization ::= type '_' type* 'Ts' SPEC-INFO // Generic re-abstracted prespecialization
10121014
specialization ::= type '_' type* 'TG' SPEC-INFO // Generic not re-abstracted specialization
10131015
specialization ::= type '_' type* 'Ti' SPEC-INFO // Inlined function with generic substitutions.

include/swift/AST/TypeExpansionContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ class TypeExpansionContext {
8989
other.expansion == this->expansion;
9090
}
9191

92+
bool operator!=(const TypeExpansionContext &other) const {
93+
return !operator==(other);
94+
}
95+
9296
bool operator<(const TypeExpansionContext other) const {
9397
assert(other.inContext != this->inContext ||
9498
other.isContextWholeModule == this->isContextWholeModule);

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ NODE(GenericProtocolWitnessTableInstantiationFunction)
104104
NODE(ResilientProtocolWitnessTable)
105105
NODE(GenericSpecialization)
106106
NODE(GenericSpecializationNotReAbstracted)
107+
NODE(GenericSpecializationInResilienceDomain)
107108
NODE(GenericSpecializationParam)
108109
NODE(GenericSpecializationPrespecialized)
109110
NODE(InlinedGenericFunction)

include/swift/SIL/GenericSpecializationMangler.h

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,31 +69,36 @@ class SpecializationMangler : public Mangle::ASTMangler {
6969
// The mangler for specialized generic functions.
7070
class GenericSpecializationMangler : public SpecializationMangler {
7171

72-
SubstitutionMap SubMap;
73-
bool isReAbstracted;
74-
bool isInlined;
75-
bool isPrespecializaton;
72+
GenericSpecializationMangler(std::string origFuncName)
73+
: SpecializationMangler(SpecializationPass::GenericSpecializer,
74+
IsNotSerialized, origFuncName) {}
75+
76+
GenericSignature getGenericSignature() {
77+
assert(Function && "Need a SIL function to get a generic signature");
78+
return Function->getLoweredFunctionType()->getInvocationGenericSignature();
79+
}
80+
81+
void appendSubstitutions(GenericSignature sig, SubstitutionMap subs);
82+
83+
std::string manglePrespecialized(GenericSignature sig,
84+
SubstitutionMap subs);
7685

7786
public:
78-
GenericSpecializationMangler(SILFunction *F, SubstitutionMap SubMap,
79-
IsSerialized_t Serialized, bool isReAbstracted,
80-
bool isInlined = false,
81-
bool isPrespecializaton = false)
87+
GenericSpecializationMangler(SILFunction *F, IsSerialized_t Serialized)
8288
: SpecializationMangler(SpecializationPass::GenericSpecializer,
83-
Serialized, F),
84-
SubMap(SubMap), isReAbstracted(isReAbstracted), isInlined(isInlined),
85-
isPrespecializaton(isPrespecializaton) {}
89+
Serialized, F) {}
8690

87-
GenericSpecializationMangler(std::string origFuncName, SubstitutionMap SubMap)
88-
: SpecializationMangler(SpecializationPass::GenericSpecializer,
89-
IsNotSerialized, origFuncName),
90-
SubMap(SubMap), isReAbstracted(true), isInlined(false),
91-
isPrespecializaton(true) {}
91+
std::string mangleNotReabstracted(SubstitutionMap subs);
9292

93-
std::string mangle(GenericSignature Sig = GenericSignature());
93+
std::string mangleReabstracted(SubstitutionMap subs, bool alternativeMangling);
9494

95-
// TODO: This utility should move from the libswiftSILOptimizer to
96-
// libswiftSIL.
95+
std::string mangleForDebugInfo(GenericSignature sig, SubstitutionMap subs,
96+
bool forInlining);
97+
98+
std::string manglePrespecialized(SubstitutionMap subs) {
99+
return manglePrespecialized(getGenericSignature(), subs);
100+
}
101+
97102
static std::string manglePrespecialization(std::string unspecializedName,
98103
GenericSignature genericSig,
99104
GenericSignature specializedSig);

include/swift/SIL/TypeSubstCloner.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,10 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
428428
return ParentFunction;
429429

430430
// Clone the function with the substituted type for the debug info.
431-
Mangle::GenericSpecializationMangler Mangler(
432-
ParentFunction, SubsMap, IsNotSerialized, false, ForInlining);
433-
std::string MangledName = Mangler.mangle(RemappedSig);
431+
Mangle::GenericSpecializationMangler Mangler(ParentFunction,
432+
IsNotSerialized);
433+
std::string MangledName =
434+
Mangler.mangleForDebugInfo(RemappedSig, SubsMap, ForInlining);
434435

435436
if (ParentFunction->getName() == MangledName)
436437
return ParentFunction;

include/swift/SILOptimizer/Utils/Generics.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ class ReabstractionInfo {
6161
/// argument has a trivial type.
6262
SmallBitVector TrivialArgs;
6363

64+
/// Set to true if the function has a re-abstracted (= converted from
65+
/// indirect to direct) resilient argument or return type. This can happen if
66+
/// the function is compiled within the type's resilience domain, i.e. in
67+
/// its module (where the type is loadable).
68+
/// In this case we need to generate a different mangled name for the
69+
/// function to distinguish it from functions in other modules, which cannot
70+
/// re-abstract this resilient type.
71+
/// Fortunately, a flag is sufficient to describe this: either a function has
72+
/// re-abstracted resilient types or not. It cannot happen that two
73+
/// functions have two different subsets of re-abstracted resilient parameter
74+
/// types.
75+
bool hasConvertedResilientParams = false;
76+
6477
/// If set, indirect to direct conversions should be performed by the generic
6578
/// specializer.
6679
bool ConvertIndirectToDirect;
@@ -128,6 +141,12 @@ class ReabstractionInfo {
128141
// Is the generated specialization going to be serialized?
129142
IsSerialized_t Serialized;
130143

144+
enum TypeCategory {
145+
NotLoadable,
146+
Loadable,
147+
LoadableAndTrivial
148+
};
149+
131150
unsigned param2ArgIndex(unsigned ParamIdx) const {
132151
return ParamIdx + NumFormalIndirectResults;
133152
}
@@ -138,6 +157,15 @@ class ReabstractionInfo {
138157
bool HasUnboundGenericParams);
139158

140159
void createSubstitutedAndSpecializedTypes();
160+
161+
TypeCategory getReturnTypeCategory(const SILResultInfo &RI,
162+
const SILFunctionConventions &substConv,
163+
TypeExpansionContext typeExpansion);
164+
165+
TypeCategory getParamTypeCategory(const SILParameterInfo &PI,
166+
const SILFunctionConventions &substConv,
167+
TypeExpansionContext typeExpansion);
168+
141169
bool prepareAndCheck(ApplySite Apply, SILFunction *Callee,
142170
SubstitutionMap ParamSubs,
143171
OptRemark::Emitter *ORE = nullptr);
@@ -175,6 +203,12 @@ class ReabstractionInfo {
175203
IsSerialized_t isSerialized() const {
176204
return Serialized;
177205
}
206+
207+
/// Returns true if the specialized function needs an alternative mangling.
208+
/// See hasConvertedResilientParams.
209+
bool needAlternativeMangling() const {
210+
return hasConvertedResilientParams;
211+
}
178212

179213
TypeExpansionContext getResilienceExpansion() const {
180214
auto resilience = (Serialized ? ResilienceExpansion::Minimal

lib/Demangling/Demangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ bool swift::Demangle::isFunctionAttr(Node::Kind kind) {
108108
case Node::Kind::GenericSpecializationNotReAbstracted:
109109
case Node::Kind::GenericPartialSpecialization:
110110
case Node::Kind::GenericPartialSpecializationNotReAbstracted:
111+
case Node::Kind::GenericSpecializationInResilienceDomain:
111112
case Node::Kind::ObjCAttribute:
112113
case Node::Kind::NonObjCAttribute:
113114
case Node::Kind::DynamicAttribute:
@@ -2317,6 +2318,9 @@ NodePointer Demangler::popProtocolConformance() {
23172318
case 'G':
23182319
return demangleGenericSpecialization(Node::Kind::
23192320
GenericSpecializationNotReAbstracted);
2321+
case 'B':
2322+
return demangleGenericSpecialization(Node::Kind::
2323+
GenericSpecializationInResilienceDomain);
23202324
case 's':
23212325
return demangleGenericSpecialization(
23222326
Node::Kind::GenericSpecializationPrespecialized);

lib/Demangling/NodePrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ class NodePrinter {
388388
case Node::Kind::GenericPartialSpecializationNotReAbstracted:
389389
case Node::Kind::GenericSpecialization:
390390
case Node::Kind::GenericSpecializationNotReAbstracted:
391+
case Node::Kind::GenericSpecializationInResilienceDomain:
391392
case Node::Kind::GenericSpecializationParam:
392393
case Node::Kind::GenericSpecializationPrespecialized:
393394
case Node::Kind::InlinedGenericFunction:
@@ -1415,6 +1416,7 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
14151416
"generic not-reabstracted partial specialization", "Signature = ");
14161417
return nullptr;
14171418
case Node::Kind::GenericSpecialization:
1419+
case Node::Kind::GenericSpecializationInResilienceDomain:
14181420
printSpecializationPrefix(Node, "generic specialization");
14191421
return nullptr;
14201422
case Node::Kind::GenericSpecializationPrespecialized:

lib/Demangling/OldRemangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ void Remangler::mangleGenericSpecializationPrespecialized(Node *node) {
369369
void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) {
370370
unreachable("unsupported");
371371
}
372+
void Remangler::mangleGenericSpecializationInResilienceDomain(Node *node) {
373+
unreachable("unsupported");
374+
}
372375

373376
void Remangler::mangleInlinedGenericFunction(Node *node) {
374377
unreachable("unsupported");

lib/Demangling/Remangler.cpp

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ class Remangler : public RemanglerBase {
300300
mangleChildNodesReversed(FuncType);
301301
}
302302

303+
void mangleGenericSpecializationNode(Node *node, const char *operatorStr);
303304
void mangleAnyNominalType(Node *node);
304305
void mangleAnyGenericType(Node *node, StringRef TypeOp);
305306
void mangleGenericArgs(Node *node, char &Separator,
@@ -1298,7 +1299,8 @@ void Remangler::mangleGenericPartialSpecializationNotReAbstracted(Node *node) {
12981299
mangleGenericPartialSpecialization(node);
12991300
}
13001301

1301-
void Remangler::mangleGenericSpecialization(Node *node) {
1302+
void Remangler::
1303+
mangleGenericSpecializationNode(Node *node, const char *operatorStr) {
13021304
bool FirstParam = true;
13031305
for (NodePointer Child : *node) {
13041306
if (Child->getKind() == Node::Kind::GenericSpecializationParam) {
@@ -1308,39 +1310,32 @@ void Remangler::mangleGenericSpecialization(Node *node) {
13081310
}
13091311
assert(!FirstParam && "generic specialization with no substitutions");
13101312

1311-
switch (node->getKind()) {
1312-
case Node::Kind::GenericSpecialization:
1313-
Buffer << "Tg";
1314-
break;
1315-
case Node::Kind::GenericSpecializationPrespecialized:
1316-
Buffer << "Ts";
1317-
break;
1318-
case Node::Kind::GenericSpecializationNotReAbstracted:
1319-
Buffer << "TG";
1320-
break;
1321-
case Node::Kind::InlinedGenericFunction:
1322-
Buffer << "Ti";
1323-
break;
1324-
default:
1325-
unreachable("unsupported node");
1326-
}
1313+
Buffer << operatorStr;
13271314

13281315
for (NodePointer Child : *node) {
13291316
if (Child->getKind() != Node::Kind::GenericSpecializationParam)
13301317
mangle(Child);
13311318
}
13321319
}
13331320

1321+
void Remangler::mangleGenericSpecialization(Node *node) {
1322+
mangleGenericSpecializationNode(node, "Tg");
1323+
}
1324+
13341325
void Remangler::mangleGenericSpecializationPrespecialized(Node *node) {
1335-
mangleGenericSpecialization(node);
1326+
mangleGenericSpecializationNode(node, "Ts");
13361327
}
13371328

13381329
void Remangler::mangleGenericSpecializationNotReAbstracted(Node *node) {
1339-
mangleGenericSpecialization(node);
1330+
mangleGenericSpecializationNode(node, "TG");
1331+
}
1332+
1333+
void Remangler::mangleGenericSpecializationInResilienceDomain(Node *node) {
1334+
mangleGenericSpecializationNode(node, "TB");
13401335
}
13411336

13421337
void Remangler::mangleInlinedGenericFunction(Node *node) {
1343-
mangleGenericSpecialization(node);
1338+
mangleGenericSpecializationNode(node, "Ti");
13441339
}
13451340

13461341

@@ -1372,6 +1367,7 @@ void Remangler::mangleGlobal(Node *node) {
13721367
case Node::Kind::GenericSpecialization:
13731368
case Node::Kind::GenericSpecializationPrespecialized:
13741369
case Node::Kind::GenericSpecializationNotReAbstracted:
1370+
case Node::Kind::GenericSpecializationInResilienceDomain:
13751371
case Node::Kind::InlinedGenericFunction:
13761372
case Node::Kind::GenericPartialSpecialization:
13771373
case Node::Kind::GenericPartialSpecializationNotReAbstracted:

lib/SIL/Utils/GenericSpecializationMangler.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -74,32 +74,53 @@ std::string SpecializationMangler::finalize() {
7474
// Generic Specialization
7575
//===----------------------------------------------------------------------===//
7676

77-
std::string GenericSpecializationMangler::mangle(GenericSignature Sig) {
78-
beginMangling();
79-
80-
if (!Sig) {
81-
assert(Function &&
82-
"Need a SIL function if no generic signature is provided");
83-
SILFunctionType *FTy = Function->getLoweredFunctionType();
84-
Sig = FTy->getInvocationGenericSignature();
85-
}
86-
77+
void GenericSpecializationMangler::
78+
appendSubstitutions(GenericSignature sig, SubstitutionMap subs) {
8779
bool First = true;
88-
Sig->forEachParam([&](GenericTypeParamType *ParamType, bool Canonical) {
80+
sig->forEachParam([&](GenericTypeParamType *ParamType, bool Canonical) {
8981
if (Canonical) {
90-
appendType(Type(ParamType).subst(SubMap)->getCanonicalType());
82+
appendType(Type(ParamType).subst(subs)->getCanonicalType());
9183
appendListSeparator(First);
9284
}
9385
});
9486
assert(!First && "no generic substitutions");
87+
}
9588

96-
if (isInlined)
97-
appendSpecializationOperator("Ti");
98-
else
99-
appendSpecializationOperator(
100-
isPrespecializaton ? "Ts" : (isReAbstracted ? "Tg" : "TG"));
89+
std::string GenericSpecializationMangler::
90+
manglePrespecialized(GenericSignature sig, SubstitutionMap subs) {
91+
beginMangling();
92+
appendSubstitutions(sig, subs);
93+
appendSpecializationOperator("Ts");
94+
return finalize();
95+
}
96+
97+
std::string GenericSpecializationMangler::
98+
mangleNotReabstracted(SubstitutionMap subs) {
99+
beginMangling();
100+
appendSubstitutions(getGenericSignature(), subs);
101+
appendSpecializationOperator("TG");
101102
return finalize();
102103
}
104+
105+
std::string GenericSpecializationMangler::
106+
mangleReabstracted(SubstitutionMap subs, bool alternativeMangling) {
107+
beginMangling();
108+
appendSubstitutions(getGenericSignature(), subs);
109+
110+
// See ReabstractionInfo::hasConvertedResilientParams for why and when to use
111+
// the alternative mangling.
112+
appendSpecializationOperator(alternativeMangling ? "TB" : "Tg");
113+
return finalize();
114+
}
115+
116+
std::string GenericSpecializationMangler::
117+
mangleForDebugInfo(GenericSignature sig, SubstitutionMap subs, bool forInlining) {
118+
beginMangling();
119+
appendSubstitutions(sig, subs);
120+
appendSpecializationOperator(forInlining ? "Ti" : "TG");
121+
return finalize();
122+
}
123+
103124

104125
static SubstitutionMap
105126
getSubstitutionMapForPrespecialization(GenericSignature genericSig,
@@ -132,6 +153,6 @@ std::string GenericSpecializationMangler::manglePrespecialization(
132153
GenericSignature specializedSig) {
133154
auto subs =
134155
getSubstitutionMapForPrespecialization(genericSig, specializedSig);
135-
GenericSpecializationMangler mangler(unspecializedName, subs);
136-
return mangler.mangle(genericSig);
156+
GenericSpecializationMangler mangler(unspecializedName);
157+
return mangler.manglePrespecialized(genericSig, subs);
137158
}

lib/SILOptimizer/IPO/UsePrespecialized.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ bool UsePrespecialized::replaceByPrespecialized(SILFunction &F) {
105105
// Create a name of the specialization. All external pre-specializations
106106
// are serialized without bodies. Thus use IsNotSerialized here.
107107
Mangle::GenericSpecializationMangler NewGenericMangler(ReferencedF,
108-
Subs, IsNotSerialized,
109-
/*isReAbstracted*/ true);
110-
std::string ClonedName = NewGenericMangler.mangle();
108+
IsNotSerialized);
109+
std::string ClonedName = NewGenericMangler.mangleReabstracted(Subs,
110+
ReInfo.needAlternativeMangling());
111111

112112
SILFunction *NewF = nullptr;
113113
// If we already have this specialization, reuse it.

0 commit comments

Comments
 (0)