Skip to content

Commit c1ce0d7

Browse files
committed
SIL: Store captured environments in SILFunction
1 parent ffba38d commit c1ce0d7

File tree

6 files changed

+56
-22
lines changed

6 files changed

+56
-22
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ class SILFunction
237237
/// The context archetypes of the function.
238238
GenericEnvironment *GenericEnv = nullptr;
239239

240+
/// Captured local generic environments.
241+
ArrayRef<GenericEnvironment *> CapturedEnvs;
242+
240243
/// The information about specialization.
241244
/// Only set if this function is a specialization of another function.
242245
const GenericSpecializationInformation *SpecializationInfo = nullptr;
@@ -1292,9 +1295,21 @@ class SILFunction
12921295
GenericEnvironment *getGenericEnvironment() const {
12931296
return GenericEnv;
12941297
}
1298+
1299+
/// Return any captured local generic environments, currently used for pack
1300+
/// element environments only. After SILGen, these are rewritten into
1301+
/// primary archetypes.
1302+
ArrayRef<GenericEnvironment *> getCapturedEnvironments() const {
1303+
return CapturedEnvs;
1304+
}
1305+
1306+
void setGenericEnvironment(GenericEnvironment *env);
1307+
12951308
void setGenericEnvironment(GenericEnvironment *env,
1296-
SubstitutionMap forwardingSubs=SubstitutionMap()) {
1309+
ArrayRef<GenericEnvironment *> capturedEnvs,
1310+
SubstitutionMap forwardingSubs) {
12971311
GenericEnv = env;
1312+
CapturedEnvs = capturedEnvs;
12981313
ForwardingSubMap = forwardingSubs;
12991314
}
13001315

@@ -1324,9 +1339,30 @@ class SILFunction
13241339
/// responsibility of the caller.
13251340
void eraseAllBlocks();
13261341

1327-
/// Return the identity substitutions necessary to forward this call if it is
1328-
/// generic.
1329-
SubstitutionMap getForwardingSubstitutionMap();
1342+
/// A substitution map that sends the generic parameters of the invocation
1343+
/// generic signature to some combination of primar and local archetypes.
1344+
///
1345+
/// CAUTION: If this is a SILFunction that captures pack element environments,
1346+
/// then at SILGen time, this is not actually the forwarding substitution map
1347+
/// of the SILFunction's generic environment. This is because:
1348+
///
1349+
/// 1) The SILFunction's generic signature includes extra generic parameters,
1350+
/// to model captured pack elements;
1351+
/// 2) The SILFunction's generic environment is the AST generic environment,
1352+
/// so it's based on the original generic signature;
1353+
/// 3) SILGen uses this AST generic environment together with local archetypes
1354+
/// for lowering SIL instructions.
1355+
///
1356+
/// Therefore, the SILFunction's forwarding substitution map takes the extended
1357+
/// generic signature (1). It maps the original generic parameters to the
1358+
/// archetypes of (2), and the extended generic parameters to the local archetypes
1359+
/// of (3).
1360+
///
1361+
/// After SILGen, all archetypes are re-instantiated inside the SIL function,
1362+
/// and the forwarding substitution map and generic environment then align.
1363+
SubstitutionMap getForwardingSubstitutionMap() const {
1364+
return ForwardingSubMap;
1365+
}
13301366

13311367
/// Returns true if this SILFunction must be a defer statement.
13321368
///

include/swift/SIL/TypeLowering.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,7 @@ class TypeConverter {
10801080
/// sends the generic parameters of the function's interface type into
10811081
/// archetypes, which will either be primary archetypes from this
10821082
/// environment, or local archetypes captured by this function.
1083-
std::pair<GenericEnvironment *, SubstitutionMap>
1083+
std::tuple<GenericEnvironment *, ArrayRef<GenericEnvironment *>, SubstitutionMap>
10841084
getForwardingSubstitutionsForLowering(SILDeclRef constant);
10851085

10861086
/// Returns the SIL type of a constant reference.

lib/SIL/IR/SILFunction.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ void SILFunction::init(
245245
"function type has open type parameters");
246246

247247
this->LoweredType = LoweredType;
248-
this->GenericEnv = genericEnv;
249248
this->SpecializationInfo = nullptr;
250249
this->EntryCount = entryCount;
251250
this->Availability = AvailabilityContext::alwaysAvailable();
@@ -282,6 +281,7 @@ void SILFunction::init(
282281
assert(!Transparent || !IsDynamicReplaceable);
283282
validateSubclassScope(classSubclassScope, isThunk, nullptr);
284283
setDebugScope(DebugScope);
284+
setGenericEnvironment(genericEnv);
285285
}
286286

287287
SILFunction::~SILFunction() {
@@ -1033,14 +1033,10 @@ void SILFunction::eraseAllBlocks() {
10331033
BlockList.clear();
10341034
}
10351035

1036-
SubstitutionMap SILFunction::getForwardingSubstitutionMap() {
1037-
if (ForwardingSubMap)
1038-
return ForwardingSubMap;
1039-
1040-
if (auto *env = getGenericEnvironment())
1041-
ForwardingSubMap = env->getForwardingSubstitutionMap();
1042-
1043-
return ForwardingSubMap;
1036+
void SILFunction::setGenericEnvironment(GenericEnvironment *env) {
1037+
setGenericEnvironment(env, ArrayRef<GenericEnvironment *>(),
1038+
env ? env->getForwardingSubstitutionMap()
1039+
: SubstitutionMap());
10441040
}
10451041

10461042
bool SILFunction::shouldVerifyOwnership() const {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4116,17 +4116,15 @@ TypeConverter::getConstantGenericEnvironment(SILDeclRef c) {
41164116
.genericSig.getGenericEnvironment();
41174117
}
41184118

4119-
std::pair<GenericEnvironment *, SubstitutionMap>
4119+
std::tuple<GenericEnvironment *, ArrayRef<GenericEnvironment *>, SubstitutionMap>
41204120
TypeConverter::getForwardingSubstitutionsForLowering(SILDeclRef constant) {
41214121
auto sig = getGenericSignatureWithCapturedEnvironments(constant);
41224122

4123-
GenericEnvironment *genericEnv = nullptr;
4123+
auto *genericEnv = sig.baseGenericSig.getGenericEnvironment();
41244124
SubstitutionMap forwardingSubs;
41254125

4126-
if (sig.baseGenericSig) {
4127-
genericEnv = sig.baseGenericSig.getGenericEnvironment();
4126+
if (sig.baseGenericSig)
41284127
forwardingSubs = genericEnv->getForwardingSubstitutionMap();
4129-
}
41304128

41314129
if (!sig.capturedEnvs.empty()) {
41324130
assert(sig.genericSig && !sig.genericSig->isEqual(sig.baseGenericSig));
@@ -4135,7 +4133,7 @@ TypeConverter::getForwardingSubstitutionsForLowering(SILDeclRef constant) {
41354133
forwardingSubs, sig.genericSig, sig.capturedEnvs);
41364134
}
41374135

4138-
return std::make_pair(genericEnv, forwardingSubs);
4136+
return std::make_tuple(genericEnv, sig.capturedEnvs, forwardingSubs);
41394137
}
41404138

41414139
SILType TypeConverter::getSubstitutedStorageType(TypeExpansionContext context,

lib/SILGen/SILGen.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,8 +1224,9 @@ void SILGenModule::preEmitFunction(SILDeclRef constant, SILFunction *F,
12241224
assert(F->empty() && "already emitted function?!");
12251225

12261226
if (F->getLoweredFunctionType()->isPolymorphic()) {
1227-
auto pair = Types.getForwardingSubstitutionsForLowering(constant);
1228-
F->setGenericEnvironment(pair.first, pair.second);
1227+
auto [genericEnv, capturedEnvs, forwardingSubs]
1228+
= Types.getForwardingSubstitutionsForLowering(constant);
1229+
F->setGenericEnvironment(genericEnv, capturedEnvs, forwardingSubs);
12291230
}
12301231

12311232
// If we have global actor isolation for our constant, put the isolation onto

lib/Serialization/SerializeSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
460460
Linkage = addExternalToLinkage(Linkage);
461461
}
462462

463+
assert(F.getCapturedEnvironments().empty() &&
464+
"Captured local environments should not survive past SILGen");
465+
463466
// If we have a body, we might have a generic environment.
464467
GenericSignatureID genericSigID = 0;
465468
if (!NoBody)

0 commit comments

Comments
 (0)