Skip to content

Commit f6cb10b

Browse files
committed
SIL: Plumb ResilienceExpansion through TypeLowering more carefully
The basic theory here is as follows: - The resilience expansion never changes the lowered type, only the SIL type category (object or address). This means that function types always pass resilient values indirectly regardless of expansion, etc. - The getTypeLowering() methods all take an optional 'forExpansion' parameter. Soon, these will become non-optional and I'll audit all call sites to pass the right expansion; for convenience, the entry points on SILFunction will pass the right expansion. Places I need to revisit and pass the right expansion in are marked as 'FIXME: Expansion'. For now, this just fixes a SILCombiner bug. After some more plumbing this will enable SILGen to produce better code. Progress on <rdar://problem/24057844>, <https://bugs.swift.org/browse/SR-261>.
1 parent 4d5a691 commit f6cb10b

File tree

3 files changed

+80
-29
lines changed

3 files changed

+80
-29
lines changed

include/swift/SIL/TypeLowering.h

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -676,8 +676,16 @@ class TypeConverter {
676676
#include "swift/SIL/BridgedTypes.def"
677677

678678
const TypeLowering &
679-
getTypeLoweringForLoweredType(TypeKey key, ResilienceExpansion forExpansion);
680-
const TypeLowering &getTypeLoweringForUncachedLoweredType(TypeKey key);
679+
getTypeLoweringForLoweredType(TypeKey key,
680+
ResilienceExpansion forExpansion);
681+
const TypeLowering &
682+
getTypeLoweringForUncachedLoweredType(TypeKey key,
683+
ResilienceExpansion forExpansion);
684+
685+
const TypeLowering &
686+
getTypeLoweringForExpansion(TypeKey key,
687+
ResilienceExpansion forExpansion,
688+
const TypeLowering *lowering);
681689

682690
public:
683691
SILModule &M;
@@ -739,15 +747,19 @@ class TypeConverter {
739747

740748
/// Lowers a Swift type to a SILType, and returns the SIL TypeLowering
741749
/// for that type.
742-
const TypeLowering &getTypeLowering(Type t) {
750+
const TypeLowering &
751+
getTypeLowering(Type t, ResilienceExpansion forExpansion =
752+
ResilienceExpansion::Minimal) {
743753
AbstractionPattern pattern(getCurGenericContext(), t->getCanonicalType());
744-
return getTypeLowering(pattern, t);
754+
return getTypeLowering(pattern, t, forExpansion);
745755
}
746756

747757
/// Lowers a Swift type to a SILType according to the abstraction
748758
/// patterns of the given original type.
749759
const TypeLowering &getTypeLowering(AbstractionPattern origType,
750-
Type substType);
760+
Type substType,
761+
ResilienceExpansion forExpansion =
762+
ResilienceExpansion::Minimal);
751763

752764
/// Returns the SIL TypeLowering for an already lowered SILType. If the
753765
/// SILType is an address, returns the TypeLowering for the pointed-to
@@ -758,16 +770,19 @@ class TypeConverter {
758770

759771
// Returns the lowered SIL type for a Swift type.
760772
SILType getLoweredType(Type t) {
761-
return getTypeLowering(t).getLoweredType();
773+
return getTypeLowering(t, ResilienceExpansion::Minimal).getLoweredType();
762774
}
763775

764776
// Returns the lowered SIL type for a Swift type.
765777
SILType getLoweredType(AbstractionPattern origType, Type substType) {
766-
return getTypeLowering(origType, substType).getLoweredType();
778+
return getTypeLowering(origType, substType, ResilienceExpansion::Minimal)
779+
.getLoweredType();
767780
}
768781

769-
SILType getLoweredLoadableType(Type t) {
770-
const TypeLowering &ti = getTypeLowering(t);
782+
SILType getLoweredLoadableType(Type t,
783+
ResilienceExpansion forExpansion =
784+
ResilienceExpansion::Minimal) {
785+
const TypeLowering &ti = getTypeLowering(t, forExpansion);
771786
assert(
772787
(ti.isLoadable() || !SILModuleConventions(M).useLoweredAddresses()) &&
773788
"unexpected address-only type");

lib/SIL/TypeLowering.cpp

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture) {
9797
// by its address (like a var) instead.
9898
if (var->isImmutable() &&
9999
(!SILModuleConventions(M).useLoweredAddresses() ||
100+
// FIXME: Expansion
100101
!getTypeLowering(var->getType()).isAddressOnly()))
101102
return CaptureKind::Constant;
102103

@@ -323,7 +324,7 @@ namespace {
323324
auto concreteType = getConcreteReferenceStorageReferent(referentType); \
324325
auto &ctx = M.getASTContext(); \
325326
if (Name##StorageType::get(concreteType, ctx) \
326-
->isLoadable(ResilienceExpansion::Maximal)) { \
327+
->isLoadable(Expansion)) { \
327328
return asImpl().visitLoadable##Name##StorageType(type); \
328329
} else { \
329330
return asImpl().visitAddressOnly##Name##StorageType(type); \
@@ -458,14 +459,14 @@ namespace {
458459

459460
// Consult the type lowering.
460461
type = getSubstitutedTypeForTypeLowering(type);
461-
auto &lowering = M.Types.getTypeLowering(type);
462+
auto &lowering = M.Types.getTypeLowering(type, Expansion);
462463
return handleClassificationFromLowering(type, lowering);
463464
}
464465

465466
RecursiveProperties visitAnyStructType(CanType type, StructDecl *D) {
466467
// Consult the type lowering.
467468
type = getSubstitutedTypeForTypeLowering(type);
468-
auto &lowering = M.Types.getTypeLowering(type);
469+
auto &lowering = M.Types.getTypeLowering(type, Expansion);
469470
return handleClassificationFromLowering(type, lowering);
470471
}
471472

@@ -850,6 +851,7 @@ namespace {
850851
unsigned index = 0;
851852
for (auto elt : tupleTy.getElementTypes()) {
852853
auto silElt = SILType::getPrimitiveType(elt, silTy.getCategory());
854+
// FIXME: Expansion
853855
children.push_back(Child{index, M.Types.getTypeLowering(silElt)});
854856
++index;
855857
}
@@ -884,6 +886,7 @@ namespace {
884886

885887
for (auto prop : structDecl->getStoredProperties()) {
886888
SILType propTy = silTy.getFieldType(prop, M);
889+
// FIXME: Expansion
887890
children.push_back(Child{prop, M.Types.getTypeLowering(propTy)});
888891
}
889892
}
@@ -1161,7 +1164,7 @@ namespace {
11611164
}
11621165

11631166
TypeLowering *handleAddressOnly(CanType type,
1164-
RecursiveProperties properties) {
1167+
RecursiveProperties properties) {
11651168
if (SILModuleConventions(M).useLoweredAddresses()) {
11661169
auto silType = SILType::getPrimitiveAddressType(type);
11671170
return new (TC, Dependent) AddressOnlyTypeLowering(silType, properties);
@@ -1187,7 +1190,7 @@ namespace {
11871190
TypeLowering *visitTupleType(CanTupleType tupleType) {
11881191
RecursiveProperties properties;
11891192
for (auto eltType : tupleType.getElementTypes()) {
1190-
auto &lowering = TC.getTypeLowering(eltType);
1193+
auto &lowering = TC.getTypeLowering(eltType, Expansion);
11911194
properties.addSubobject(lowering.getRecursiveProperties());
11921195
}
11931196

@@ -1258,7 +1261,7 @@ namespace {
12581261

12591262
template <class LoadableLoweringClass>
12601263
TypeLowering *handleAggregateByProperties(CanType type,
1261-
RecursiveProperties props) {
1264+
RecursiveProperties props) {
12621265
if (props.isAddressOnly()) {
12631266
return handleAddressOnly(type, props);
12641267
}
@@ -1422,7 +1425,8 @@ TypeConverter::getSILFunctionType(AbstractionPattern origType,
14221425

14231426
const TypeLowering &
14241427
TypeConverter::getTypeLowering(AbstractionPattern origType,
1425-
Type origSubstType) {
1428+
Type origSubstType,
1429+
ResilienceExpansion forExpansion) {
14261430
CanType substType = origSubstType->getCanonicalType();
14271431
auto key = getTypeKey(origType, substType);
14281432

@@ -1431,7 +1435,7 @@ TypeConverter::getTypeLowering(AbstractionPattern origType,
14311435
assert(!substType->is<InOutType>());
14321436

14331437
if (auto existing = find(key))
1434-
return *existing;
1438+
return getTypeLoweringForExpansion(key, forExpansion, existing);
14351439

14361440
// Lower the type.
14371441
CanType loweredSubstType =
@@ -1441,7 +1445,7 @@ TypeConverter::getTypeLowering(AbstractionPattern origType,
14411445
// point in re-checking the table, so just construct a type lowering
14421446
// and cache it.
14431447
if (loweredSubstType == substType && key.isCacheable()) {
1444-
return getTypeLoweringForUncachedLoweredType(key);
1448+
return getTypeLoweringForUncachedLoweredType(key, forExpansion);
14451449
}
14461450

14471451
// Otherwise, check the table at a key that would be used by the
@@ -1452,7 +1456,7 @@ TypeConverter::getTypeLowering(AbstractionPattern origType,
14521456
auto loweredKey = getTypeKey(origTypeForCaching, loweredSubstType);
14531457

14541458
auto &lowering = getTypeLoweringForLoweredType(loweredKey,
1455-
ResilienceExpansion::Minimal);
1459+
forExpansion);
14561460
insert(key, &lowering);
14571461
return lowering;
14581462
}
@@ -1583,13 +1587,21 @@ TypeConverter::getTypeLoweringForLoweredType(TypeKey key,
15831587
(void)type;
15841588

15851589
const TypeLowering *lowering = find(key);
1586-
if (!lowering) {
1587-
lowering = &getTypeLoweringForUncachedLoweredType(key);
1588-
}
1589-
assert(lowering->forExpansion == ResilienceExpansion::Minimal &&
1590-
"the first lowering in the list must be for minimal expansion");
1590+
if (!lowering)
1591+
lowering = &getTypeLoweringForUncachedLoweredType(key, forExpansion);
1592+
1593+
return getTypeLoweringForExpansion(key, forExpansion, lowering);
1594+
}
15911595

1592-
if (key.isDependent() || !lowering->isResilient()) {
1596+
/// When we've found a type lowering for one resilience expansion,
1597+
/// check if its the one we want; if not, walk the list until we
1598+
/// find the right one, or create a new lowering and add it to
1599+
/// the end of the list.
1600+
const TypeLowering & TypeConverter::
1601+
getTypeLoweringForExpansion(TypeKey key,
1602+
ResilienceExpansion forExpansion,
1603+
const TypeLowering *lowering) {
1604+
if (!lowering->isResilient()) {
15931605
// Don't try to refine the lowering for other resilience expansions if
15941606
// we don't expect to get a different lowering anyway.
15951607
return *lowering;
@@ -1619,8 +1631,9 @@ TypeConverter::getTypeLoweringForLoweredType(TypeKey key,
16191631

16201632
/// Do type-lowering for a lowered type which is not already in the cache,
16211633
/// then insert it into the cache.
1622-
const TypeLowering &
1623-
TypeConverter::getTypeLoweringForUncachedLoweredType(TypeKey key) {
1634+
const TypeLowering & TypeConverter::
1635+
getTypeLoweringForUncachedLoweredType(TypeKey key,
1636+
ResilienceExpansion forExpansion) {
16241637
assert(!find(key) && "re-entrant or already cached");
16251638
assert(key.SubstType->isLegalSILType() && "type is not already lowered");
16261639

@@ -1629,12 +1642,13 @@ TypeConverter::getTypeLoweringForUncachedLoweredType(TypeKey key) {
16291642
insert(key, nullptr);
16301643
#endif
16311644

1632-
// FIXME: Get expansion from SILFunction
16331645
auto *theInfo = LowerType(*this,
16341646
CanGenericSignature(),
1635-
ResilienceExpansion::Minimal,
1647+
forExpansion,
16361648
key.isDependent()).visit(key.SubstType);
16371649

1650+
theInfo->forExpansion = forExpansion;
1651+
16381652
if (key.OrigType.isForeign()) {
16391653
assert(theInfo->isLoadable() && "Cannot lower address-only type with "
16401654
"foreign abstraction pattern");
@@ -2489,6 +2503,7 @@ CanSILBoxType TypeConverter::getBoxTypeForEnumElement(SILType enumType,
24892503
static void countNumberOfInnerFields(unsigned &fieldsCount, SILModule &Module,
24902504
SILType Ty) {
24912505
if (auto *structDecl = Ty.getStructOrBoundGenericStruct()) {
2506+
// FIXME: Expansion
24922507
assert(!structDecl->isResilient(Module.getSwiftModule(),
24932508
ResilienceExpansion::Minimal) &&
24942509
" FSO should not be trying to explode resilient (ie address-only) "
@@ -2516,6 +2531,7 @@ static void countNumberOfInnerFields(unsigned &fieldsCount, SILModule &Module,
25162531
if (enumDecl->isIndirect()) {
25172532
return;
25182533
}
2534+
// FIXME: Expansion
25192535
assert(!enumDecl->isResilient(Module.getSwiftModule(),
25202536
ResilienceExpansion::Minimal) &&
25212537
" FSO should not be trying to explode resilient (ie address-only) "

test/SILOptimizer/globalopt_resilience.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,23 @@ public func cannotConvertToValueUse() {
3232
// CHECK: apply [[METHOD]]([[ADDR]]) : $@convention(method) (@in_guaranteed ResilientStruct) -> ()
3333
// CHECK: [[RESULT:%.*]] = tuple ()
3434
// CHECK: return [[RESULT]] : $()
35+
36+
internal struct WrapperStruct {
37+
var inner: ResilientStruct = .staticVal
38+
39+
init() {}
40+
}
41+
42+
func returnWrapperStruct() -> WrapperStruct {
43+
return WrapperStruct()
44+
}
45+
46+
// CHECK-LABEL: sil hidden @$s4test19returnWrapperStructAA0cD0VyF : $@convention(thin) () -> @out WrapperStruct
47+
// CHECK: bb0(%0 : $*WrapperStruct):
48+
// CHECK: [[INT:%.*]] = integer_literal $Builtin.Int{{32|64}}, 27
49+
// CHECK: [[S1:%.*]] = struct $Int ([[INT]] : $Builtin.Int{{32|64}})
50+
// CHECK: [[S2:%.*]] = struct $ResilientStruct ([[S1]] : $Int)
51+
// CHECK: [[S3:%.*]] = struct $WrapperStruct ([[S2]] : $ResilientStruct)
52+
// CHECK: store [[S3]] to %0 : $*WrapperStruct
53+
// CHECK: [[RESULT:%.*]] = tuple ()
54+
// CHECK: return [[RESULT]] : $()

0 commit comments

Comments
 (0)