Skip to content

Commit 268f780

Browse files
committed
SIL: Type lowering propagates recursive properties in all cases
We were calling isResilent() to check if a type's layout contained a type that was resilient in some resilience domain. This was used to determine if we should re-lower the type when the desired resilience expansion does not match the given resilence expansion. However this bit was only getting set on address only types. This means if a resilient type was lowered with maximal expansion first, and this produced a non-address only type lowering, we would not lower it again when minimal expansion was requested. This can't be triggered with the existing tests, but upcoming changes result in regressions from this.
1 parent 0cd9eb2 commit 268f780

File tree

2 files changed

+106
-55
lines changed

2 files changed

+106
-55
lines changed

include/swift/SIL/TypeLowering.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,16 @@ class TypeLowering {
175175
constexpr RecursiveProperties(IsTrivial_t isTrivial,
176176
IsFixedABI_t isFixedABI,
177177
IsAddressOnly_t isAddressOnly,
178-
IsResilient_t isResilient = IsNotResilient)
178+
IsResilient_t isResilient)
179179
: Flags((isTrivial ? 0U : NonTrivialFlag) |
180-
(isAddressOnly ? AddressOnlyFlag : 0U) |
181180
(isFixedABI ? 0U : NonFixedABIFlag) |
181+
(isAddressOnly ? AddressOnlyFlag : 0U) |
182182
(isResilient ? ResilientFlag : 0U)) {}
183183

184+
static constexpr RecursiveProperties forTrivial() {
185+
return {IsTrivial, IsFixedABI, IsNotAddressOnly, IsNotResilient};
186+
}
187+
184188
static constexpr RecursiveProperties forReference() {
185189
return {IsNotTrivial, IsFixedABI, IsNotAddressOnly, IsNotResilient };
186190
}
@@ -190,7 +194,7 @@ class TypeLowering {
190194
}
191195

192196
static constexpr RecursiveProperties forResilient() {
193-
return {IsNotTrivial, IsNotFixedABI, IsAddressOnly, IsResilient};
197+
return {IsTrivial, IsFixedABI, IsNotAddressOnly, IsResilient};
194198
}
195199

196200
void addSubobject(RecursiveProperties other) {

lib/SIL/TypeLowering.cpp

Lines changed: 99 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -154,24 +154,21 @@ namespace {
154154
// The subclass should implement:
155155
// // Trivial, fixed-layout, and non-address-only.
156156
// RetTy handleTrivial(CanType);
157+
// RetTy handleTrivial(CanType. RecursiveProperties properties);
157158
// // A reference type.
158159
// RetTy handleReference(CanType);
159160
// // Non-trivial and address-only.
160161
// RetTy handleAddressOnly(CanType, RecursiveProperties properties);
161162
// and, if it doesn't override handleTupleType,
162163
// // An aggregate type that's non-trivial.
163-
// RetTy handleNonTrivialAggregate(CanType, IsFixedABI_t fixed);
164+
// RetTy handleNonTrivialAggregate(CanType, RecursiveProperties properties);
164165
//
165166
// Alternatively, it can just implement:
166167
// RetTy handle(CanType, RecursiveProperties properties);
167168

168169
/// Handle a trivial, fixed-size, loadable type.
169-
RetTy handleTrivial(CanType type) {
170-
return asImpl().handle(type, RecursiveProperties());
171-
}
172-
173-
RetTy handleReference(CanType type) {
174-
return asImpl().handle(type, RecursiveProperties::forReference());
170+
RetTy handleTrivial(CanType type, RecursiveProperties properties) {
171+
return asImpl().handle(type, properties);
175172
}
176173

177174
RetTy handleAddressOnly(CanType type, RecursiveProperties properties) {
@@ -183,6 +180,13 @@ namespace {
183180
return asImpl().handle(type, properties);
184181
}
185182

183+
RetTy handleTrivial(CanType type) {
184+
return asImpl().handleTrivial(type, RecursiveProperties::forTrivial());
185+
}
186+
RetTy handleReference(CanType type) {
187+
return asImpl().handle(type, RecursiveProperties::forReference());
188+
}
189+
186190
#define IMPL(TYPE, LOWERING) \
187191
RetTy visit##TYPE##Type(Can##TYPE##Type type) { \
188192
return asImpl().handle##LOWERING(type); \
@@ -207,7 +211,7 @@ namespace {
207211
RetTy visitBuiltinUnsafeValueBufferType(
208212
CanBuiltinUnsafeValueBufferType type) {
209213
return asImpl().handleAddressOnly(type, {IsNotTrivial, IsFixedABI,
210-
IsAddressOnly});
214+
IsAddressOnly, IsNotResilient});
211215
}
212216

213217
RetTy visitAnyFunctionType(CanAnyFunctionType type) {
@@ -305,7 +309,8 @@ namespace {
305309
RetTy visit##Name##StorageType(Can##Name##StorageType type) { \
306310
return asImpl().handleAddressOnly(type, {IsNotTrivial, \
307311
IsFixedABI, \
308-
IsAddressOnly}); \
312+
IsAddressOnly, \
313+
IsNotResilient}); \
309314
}
310315
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
311316
RetTy visit##Name##StorageType(Can##Name##StorageType type) { \
@@ -318,7 +323,8 @@ namespace {
318323
RetTy visitAddressOnly##Name##StorageType(Can##Name##StorageType type) { \
319324
return asImpl().handleAddressOnly(type, {IsNotTrivial, \
320325
IsFixedABI, \
321-
IsAddressOnly}); \
326+
IsAddressOnly, \
327+
IsNotResilient}); \
322328
} \
323329
RetTy visit##Name##StorageType(Can##Name##StorageType type) { \
324330
auto referentType = type->getReferentType(); \
@@ -349,8 +355,9 @@ namespace {
349355
}
350356

351357
if (LayoutInfo->isAddressOnlyTrivial()) {
352-
return asImpl().handleAddressOnly(type,
353-
{IsTrivial, IsNotFixedABI, IsAddressOnly});
358+
auto properties = RecursiveProperties::forTrivial();
359+
properties.setAddressOnly();
360+
return asImpl().handleAddressOnly(type, properties);
354361
}
355362

356363
if (LayoutInfo->isRefCounted())
@@ -368,7 +375,8 @@ namespace {
368375
case ExistentialRepresentation::Opaque:
369376
return asImpl().handleAddressOnly(type, {IsNotTrivial,
370377
IsFixedABI,
371-
IsAddressOnly});
378+
IsAddressOnly,
379+
IsNotResilient});
372380
// Class-constrained and boxed existentials are refcounted.
373381
case ExistentialRepresentation::Class:
374382
case ExistentialRepresentation::Boxed:
@@ -418,8 +426,10 @@ namespace {
418426

419427
RetTy visitSILBlockStorageType(CanSILBlockStorageType type) {
420428
// Should not be loaded.
421-
return asImpl().handleAddressOnly(type, {IsNotTrivial, IsFixedABI,
422-
IsAddressOnly});
429+
return asImpl().handleAddressOnly(type, {IsNotTrivial,
430+
IsFixedABI,
431+
IsAddressOnly,
432+
IsNotResilient});
423433
}
424434

425435
RetTy visitSILBoxType(CanSILBoxType type) {
@@ -547,9 +557,14 @@ namespace {
547557
/// A class for trivial, fixed-layout, loadable types.
548558
class TrivialTypeLowering final : public LoadableTypeLowering {
549559
public:
550-
TrivialTypeLowering(SILType type, ResilienceExpansion forExpansion)
551-
: LoadableTypeLowering(type, {IsTrivial, IsFixedABI, IsNotAddressOnly},
552-
IsNotReferenceCounted, forExpansion) {}
560+
TrivialTypeLowering(SILType type, RecursiveProperties properties,
561+
ResilienceExpansion forExpansion)
562+
: LoadableTypeLowering(type, properties, IsNotReferenceCounted,
563+
forExpansion) {
564+
assert(properties.isFixedABI());
565+
assert(properties.isTrivial());
566+
assert(!properties.isAddressOnly());
567+
}
553568

554569
SILValue emitLoadOfCopy(SILBuilder &B, SILLocation loc, SILValue addr,
555570
IsTake_t isTake) const override {
@@ -610,14 +625,6 @@ namespace {
610625

611626
class NonTrivialLoadableTypeLowering : public LoadableTypeLowering {
612627
public:
613-
NonTrivialLoadableTypeLowering(SILType type,
614-
IsReferenceCounted_t isRefCounted,
615-
ResilienceExpansion forExpansion)
616-
: NonTrivialLoadableTypeLowering(type,
617-
{IsNotTrivial, IsFixedABI, IsNotAddressOnly},
618-
isRefCounted, forExpansion) {}
619-
620-
/// This constructor is necessary because of opaque-values.
621628
NonTrivialLoadableTypeLowering(SILType type,
622629
RecursiveProperties properties,
623630
IsReferenceCounted_t isRefCounted,
@@ -713,9 +720,11 @@ namespace {
713720
const = 0;
714721

715722
public:
716-
LoadableAggTypeLowering(CanType type, ResilienceExpansion forExpansion)
723+
LoadableAggTypeLowering(CanType type, RecursiveProperties properties,
724+
ResilienceExpansion forExpansion)
717725
: NonTrivialLoadableTypeLowering(SILType::getPrimitiveObjectType(type),
718-
IsNotReferenceCounted, forExpansion) {
726+
properties, IsNotReferenceCounted,
727+
forExpansion) {
719728
}
720729

721730
virtual SILValue rebuildAggregate(SILBuilder &B, SILLocation loc,
@@ -830,8 +839,9 @@ namespace {
830839
class LoadableTupleTypeLowering final
831840
: public LoadableAggTypeLowering<LoadableTupleTypeLowering, unsigned> {
832841
public:
833-
LoadableTupleTypeLowering(CanType type, ResilienceExpansion forExpansion)
834-
: LoadableAggTypeLowering(type, forExpansion) {}
842+
LoadableTupleTypeLowering(CanType type, RecursiveProperties properties,
843+
ResilienceExpansion forExpansion)
844+
: LoadableAggTypeLowering(type, properties, forExpansion) {}
835845

836846
SILValue emitRValueProject(SILBuilder &B, SILLocation loc,
837847
SILValue tupleValue, unsigned index,
@@ -866,8 +876,9 @@ namespace {
866876
class LoadableStructTypeLowering final
867877
: public LoadableAggTypeLowering<LoadableStructTypeLowering, VarDecl*> {
868878
public:
869-
LoadableStructTypeLowering(CanType type, ResilienceExpansion forExpansion)
870-
: LoadableAggTypeLowering(type, forExpansion) {}
879+
LoadableStructTypeLowering(CanType type, RecursiveProperties properties,
880+
ResilienceExpansion forExpansion)
881+
: LoadableAggTypeLowering(type, properties, forExpansion) {}
871882

872883
SILValue emitRValueProject(SILBuilder &B, SILLocation loc,
873884
SILValue structValue, VarDecl *field,
@@ -899,8 +910,10 @@ namespace {
899910
/// A lowering for loadable but non-trivial enum types.
900911
class LoadableEnumTypeLowering final : public NonTrivialLoadableTypeLowering {
901912
public:
902-
LoadableEnumTypeLowering(CanType type, ResilienceExpansion forExpansion)
913+
LoadableEnumTypeLowering(CanType type, RecursiveProperties properties,
914+
ResilienceExpansion forExpansion)
903915
: NonTrivialLoadableTypeLowering(SILType::getPrimitiveObjectType(type),
916+
properties,
904917
IsNotReferenceCounted,
905918
forExpansion) {}
906919

@@ -1021,8 +1034,9 @@ namespace {
10211034
AddressOnlyTypeLowering(SILType type, RecursiveProperties properties,
10221035
ResilienceExpansion forExpansion)
10231036
: TypeLowering(type, properties, IsNotReferenceCounted,
1024-
forExpansion)
1025-
{}
1037+
forExpansion) {
1038+
assert(properties.isAddressOnly());
1039+
}
10261040

10271041
void emitCopyInto(SILBuilder &B, SILLocation loc,
10281042
SILValue src, SILValue dest, IsTake_t isTake,
@@ -1092,7 +1106,8 @@ namespace {
10921106
UnsafeValueBufferTypeLowering(SILType type,
10931107
ResilienceExpansion forExpansion)
10941108
: AddressOnlyTypeLowering(type,
1095-
{IsNotTrivial, IsFixedABI, IsAddressOnly},
1109+
{IsNotTrivial, IsFixedABI,
1110+
IsAddressOnly, IsNotResilient},
10961111
forExpansion) {}
10971112

10981113
void emitCopyInto(SILBuilder &B, SILLocation loc,
@@ -1168,8 +1183,14 @@ namespace {
11681183
TC(TC), Dependent(Dependent) {}
11691184

11701185
TypeLowering *handleTrivial(CanType type) {
1186+
return handleTrivial(type, RecursiveProperties::forTrivial());
1187+
}
1188+
1189+
TypeLowering *handleTrivial(CanType type,
1190+
RecursiveProperties properties) {
11711191
auto silType = SILType::getPrimitiveObjectType(type);
1172-
return new (TC, Dependent) TrivialTypeLowering(silType, Expansion);
1192+
return new (TC, Dependent) TrivialTypeLowering(silType, properties,
1193+
Expansion);
11731194
}
11741195

11751196
TypeLowering *handleReference(CanType type) {
@@ -1223,16 +1244,37 @@ namespace {
12231244
properties);
12241245
}
12251246

1247+
bool handleResilience(CanType type, NominalTypeDecl *D,
1248+
RecursiveProperties &properties) {
1249+
if (D->isResilient()) {
1250+
// If the type is resilient and defined in our module, make a note of
1251+
// that, since our lowering now depends on the resilience expansion.
1252+
bool sameModule = (D->getModuleContext() == M.getSwiftModule());
1253+
if (sameModule)
1254+
properties.addSubobject(RecursiveProperties::forResilient());
1255+
1256+
// If the type is in a different module, or if we're using a minimal
1257+
// expansion, the type is address only and completely opaque to us.
1258+
//
1259+
// Note: if the type is in a different module, the lowering does
1260+
// not depend on the resilience expansion, so we do not need to set
1261+
// the isResilent() flag above.
1262+
if (!sameModule || Expansion == ResilienceExpansion::Minimal) {
1263+
properties.addSubobject(RecursiveProperties::forOpaque());
1264+
return true;
1265+
}
1266+
}
1267+
1268+
return false;
1269+
}
1270+
12261271
TypeLowering *visitAnyStructType(CanType structType, StructDecl *D) {
1272+
RecursiveProperties properties;
12271273

1228-
// For now, if the type does not have a fixed layout in all resilience
1229-
// domains, we will treat it as address-only in SIL.
1230-
if (D->isResilient(M.getSwiftModule(), Expansion))
1231-
return handleAddressOnly(structType,
1232-
RecursiveProperties::forResilient());
1274+
if (handleResilience(structType, D, properties))
1275+
return handleAddressOnly(structType, properties);
12331276

12341277
// Classify the type according to its stored properties.
1235-
RecursiveProperties properties;
12361278
for (auto field : D->getStoredProperties()) {
12371279
auto substFieldType =
12381280
structType->getTypeOfMember(D->getModuleContext(), field, nullptr);
@@ -1245,22 +1287,24 @@ namespace {
12451287
}
12461288

12471289
TypeLowering *visitAnyEnumType(CanType enumType, EnumDecl *D) {
1248-
// For now, if the type does not have a fixed layout in all resilience
1249-
// domains, we will treat it as address-only in SIL.
1250-
if (D->isResilient(M.getSwiftModule(), Expansion))
1251-
return handleAddressOnly(enumType, RecursiveProperties::forResilient());
1290+
RecursiveProperties properties;
1291+
1292+
if (handleResilience(enumType, D, properties))
1293+
return handleAddressOnly(enumType, properties);
12521294

12531295
// If the whole enum is indirect, we lower it as if all payload
12541296
// cases were indirect. This means a fixed-layout indirect enum
12551297
// is always loadable and nontrivial. A resilient indirect enum
12561298
// is still address only, because we don't know how many bits
1257-
// are used for the discriminator.
1299+
// are used for the discriminator, and new non-indirect cases
1300+
// may be added resiliently later.
12581301
if (D->isIndirect()) {
1259-
return new (TC, Dependent) LoadableEnumTypeLowering(enumType, Expansion);
1302+
properties.setNonTrivial();
1303+
return new (TC, Dependent) LoadableEnumTypeLowering(enumType, properties,
1304+
Expansion);
12601305
}
12611306

12621307
// Accumulate the properties of all direct payloads.
1263-
RecursiveProperties properties;
12641308
for (auto elt : D->getAllElements()) {
12651309
// No-payload elements do not affect any recursive properties.
12661310
if (!elt->hasAssociatedValues())
@@ -1292,9 +1336,9 @@ namespace {
12921336
}
12931337
assert(props.isFixedABI());
12941338
if (props.isTrivial()) {
1295-
return handleTrivial(type);
1339+
return handleTrivial(type, props);
12961340
}
1297-
return new (TC, Dependent) LoadableLoweringClass(type, Expansion);
1341+
return new (TC, Dependent) LoadableLoweringClass(type, props, Expansion);
12981342
}
12991343
};
13001344
} // end anonymous namespace
@@ -1664,6 +1708,9 @@ getTypeLoweringForExpansion(TypeKey key,
16641708
if (!lowering->isResilient()) {
16651709
// Don't try to refine the lowering for other resilience expansions if
16661710
// we don't expect to get a different lowering anyway.
1711+
//
1712+
// See LowerType::handleResilience() for the gory details; we only
1713+
// set this flag if the type is resilient *and* inside our module.
16671714
return lowering;
16681715
}
16691716

0 commit comments

Comments
 (0)