Skip to content

Commit a08d141

Browse files
committed
SIL: Store captured environments in SILFunction
1 parent 02caf18 commit a08d141

File tree

6 files changed

+82
-15
lines changed

6 files changed

+82
-15
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 42 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;
@@ -1276,8 +1279,22 @@ class SILFunction
12761279
GenericEnvironment *getGenericEnvironment() const {
12771280
return GenericEnv;
12781281
}
1279-
void setGenericEnvironment(GenericEnvironment *env) {
1282+
1283+
/// Return any captured local generic environments, currently used for pack
1284+
/// element environments only. After SILGen, these are rewritten into
1285+
/// primary archetypes.
1286+
ArrayRef<GenericEnvironment *> getCapturedEnvironments() const {
1287+
return CapturedEnvs;
1288+
}
1289+
1290+
void setGenericEnvironment(GenericEnvironment *env);
1291+
1292+
void setGenericEnvironment(GenericEnvironment *env,
1293+
ArrayRef<GenericEnvironment *> capturedEnvs,
1294+
SubstitutionMap forwardingSubs) {
12801295
GenericEnv = env;
1296+
CapturedEnvs = capturedEnvs;
1297+
ForwardingSubMap = forwardingSubs;
12811298
}
12821299

12831300
/// Retrieve the generic signature from the generic environment of this
@@ -1306,9 +1323,30 @@ class SILFunction
13061323
/// responsibility of the caller.
13071324
void eraseAllBlocks();
13081325

1309-
/// Return the identity substitutions necessary to forward this call if it is
1310-
/// generic.
1311-
SubstitutionMap getForwardingSubstitutionMap();
1326+
/// A substitution map that sends the generic parameters of the invocation
1327+
/// generic signature to some combination of primar and local archetypes.
1328+
///
1329+
/// CAUTION: If this is a SILFunction that captures pack element environments,
1330+
/// then at SILGen time, this is not actually the forwarding substitution map
1331+
/// of the SILFunction's generic environment. This is because:
1332+
///
1333+
/// 1) The SILFunction's generic signature includes extra generic parameters,
1334+
/// to model captured pack elements;
1335+
/// 2) The SILFunction's generic environment is the AST generic environment,
1336+
/// so it's based on the original generic signature;
1337+
/// 3) SILGen uses this AST generic environment together with local archetypes
1338+
/// for lowering SIL instructions.
1339+
///
1340+
/// Therefore, the SILFunction's forwarding substitution map takes the extended
1341+
/// generic signature (1). It maps the original generic parameters to the
1342+
/// archetypes of (2), and the extended generic parameters to the local archetypes
1343+
/// of (3).
1344+
///
1345+
/// After SILGen, all archetypes are re-instantiated inside the SIL function,
1346+
/// and the forwarding substitution map and generic environment then align.
1347+
SubstitutionMap getForwardingSubstitutionMap() const {
1348+
return ForwardingSubMap;
1349+
}
13121350

13131351
/// Returns true if this SILFunction must be a defer statement.
13141352
///

include/swift/SIL/TypeLowering.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,13 @@ class TypeConverter {
10761076
/// Get the generic environment for a constant.
10771077
GenericEnvironment *getConstantGenericEnvironment(SILDeclRef constant);
10781078

1079+
/// Get the generic environment for SILGen to use. The substitution map
1080+
/// sends the generic parameters of the function's interface type into
1081+
/// archetypes, which will either be primary archetypes from this
1082+
/// environment, or local archetypes captured by this function.
1083+
std::tuple<GenericEnvironment *, ArrayRef<GenericEnvironment *>, SubstitutionMap>
1084+
getForwardingSubstitutionsForLowering(SILDeclRef constant);
1085+
10791086
/// Returns the SIL type of a constant reference.
10801087
SILType getConstantType(TypeExpansionContext context, SILDeclRef constant) {
10811088
return getConstantInfo(context, constant).getSILType();

lib/SIL/IR/SILFunction.cpp

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

246246
this->LoweredType = LoweredType;
247-
this->GenericEnv = genericEnv;
248247
this->SpecializationInfo = nullptr;
249248
this->EntryCount = entryCount;
250249
this->Availability = AvailabilityContext::alwaysAvailable();
@@ -280,6 +279,7 @@ void SILFunction::init(
280279
assert(!Transparent || !IsDynamicReplaceable);
281280
validateSubclassScope(classSubclassScope, isThunk, nullptr);
282281
setDebugScope(DebugScope);
282+
setGenericEnvironment(genericEnv);
283283
}
284284

285285
SILFunction::~SILFunction() {
@@ -993,14 +993,10 @@ void SILFunction::eraseAllBlocks() {
993993
BlockList.clear();
994994
}
995995

996-
SubstitutionMap SILFunction::getForwardingSubstitutionMap() {
997-
if (ForwardingSubMap)
998-
return ForwardingSubMap;
999-
1000-
if (auto *env = getGenericEnvironment())
1001-
ForwardingSubMap = env->getForwardingSubstitutionMap();
1002-
1003-
return ForwardingSubMap;
996+
void SILFunction::setGenericEnvironment(GenericEnvironment *env) {
997+
setGenericEnvironment(env, ArrayRef<GenericEnvironment *>(),
998+
env ? env->getForwardingSubstitutionMap()
999+
: SubstitutionMap());
10041000
}
10051001

10061002
bool SILFunction::shouldVerifyOwnership() const {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4094,6 +4094,26 @@ TypeConverter::getConstantGenericEnvironment(SILDeclRef c) {
40944094
.genericSig.getGenericEnvironment();
40954095
}
40964096

4097+
std::tuple<GenericEnvironment *, ArrayRef<GenericEnvironment *>, SubstitutionMap>
4098+
TypeConverter::getForwardingSubstitutionsForLowering(SILDeclRef constant) {
4099+
auto sig = getGenericSignatureWithCapturedEnvironments(constant);
4100+
4101+
auto *genericEnv = sig.baseGenericSig.getGenericEnvironment();
4102+
SubstitutionMap forwardingSubs;
4103+
4104+
if (sig.baseGenericSig)
4105+
forwardingSubs = genericEnv->getForwardingSubstitutionMap();
4106+
4107+
if (!sig.capturedEnvs.empty()) {
4108+
assert(sig.genericSig && !sig.genericSig->isEqual(sig.baseGenericSig));
4109+
4110+
forwardingSubs = buildSubstitutionMapWithCapturedEnvironments(
4111+
forwardingSubs, sig.genericSig, sig.capturedEnvs);
4112+
}
4113+
4114+
return std::make_tuple(genericEnv, sig.capturedEnvs, forwardingSubs);
4115+
}
4116+
40974117
SILType TypeConverter::getSubstitutedStorageType(TypeExpansionContext context,
40984118
AbstractStorageDecl *value,
40994119
Type lvalueType) {

lib/SILGen/SILGen.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,8 +1223,11 @@ void SILGenModule::preEmitFunction(SILDeclRef constant, SILFunction *F,
12231223
SILLocation Loc) {
12241224
assert(F->empty() && "already emitted function?!");
12251225

1226-
if (F->getLoweredFunctionType()->isPolymorphic())
1227-
F->setGenericEnvironment(Types.getConstantGenericEnvironment(constant));
1226+
if (F->getLoweredFunctionType()->isPolymorphic()) {
1227+
auto [genericEnv, capturedEnvs, forwardingSubs]
1228+
= Types.getForwardingSubstitutionsForLowering(constant);
1229+
F->setGenericEnvironment(genericEnv, capturedEnvs, forwardingSubs);
1230+
}
12281231

12291232
// If we have global actor isolation for our constant, put the isolation onto
12301233
// the function.

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)