Skip to content

Commit f8df84c

Browse files
committed
During Package CMO, types are serialized in minimal resilience
expansion and become address-only. They should however be treated as loadable during verification since the optimization happens post abstraction. This is done by adding a field to indicate if it's post abstraction phase in TypeExpansionContext and looking it up in isLoadable calls. Resolves rdar://127400743
1 parent ade04a7 commit f8df84c

File tree

6 files changed

+46
-37
lines changed

6 files changed

+46
-37
lines changed

include/swift/AST/TypeExpansionContext.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,20 @@ class TypeExpansionContext {
3333
const DeclContext *inContext;
3434
// Is the context in which we are expanding in the whole module.
3535
bool isContextWholeModule;
36+
// False (by default) if the context in which we are expanding is
37+
// for abstraction purposes, i.e. in SILGen to decide the ABI of
38+
// function signatures and so parameters need the right abstraction.
39+
// True if we are later in the pipeline, so post abstraction, where
40+
// we could allow more optimizations, e.g. during SIL cloning in
41+
// Package CMO (see CrossModuleOptimization).
42+
bool isContextPostAbstraction = false;
3643

3744
// The minimal expansion.
3845
TypeExpansionContext() {
3946
inContext = nullptr;
4047
expansion = ResilienceExpansion::Minimal;
4148
isContextWholeModule = false;
49+
isContextPostAbstraction = false;
4250
}
4351

4452
public:
@@ -47,16 +55,22 @@ class TypeExpansionContext {
4755
TypeExpansionContext(const SILFunction &f);
4856

4957
TypeExpansionContext(ResilienceExpansion expansion,
50-
const DeclContext *inContext, bool isWholeModuleContext)
58+
const DeclContext *inContext,
59+
bool isWholeModuleContext,
60+
bool isPostAbstraction = false)
5161
: expansion(expansion), inContext(inContext),
52-
isContextWholeModule(isWholeModuleContext) {}
62+
isContextWholeModule(isWholeModuleContext),
63+
isContextPostAbstraction(isPostAbstraction) {}
5364

5465
ResilienceExpansion getResilienceExpansion() const { return expansion; }
5566

5667
const DeclContext *getContext() const { return inContext; }
5768

5869
bool isWholeModuleContext() const { return isContextWholeModule; }
5970

71+
bool isPostAbstraction() const { return isContextPostAbstraction; }
72+
void setIsPostAbstraction(bool postAbstraction = true) { isContextPostAbstraction = postAbstraction; }
73+
6074
bool shouldLookThroughOpaqueTypeArchetypes() const {
6175
return inContext != nullptr;
6276
}
@@ -68,18 +82,19 @@ class TypeExpansionContext {
6882
}
6983

7084
static TypeExpansionContext maximal(const DeclContext *inContext,
71-
bool isContextWholeModule) {
85+
bool isContextWholeModule,
86+
bool isContextPostAbstraction = false) {
7287
return TypeExpansionContext(ResilienceExpansion::Maximal, inContext,
73-
isContextWholeModule);
88+
isContextWholeModule, isContextPostAbstraction);
7489
}
7590

7691
static TypeExpansionContext maximalResilienceExpansionOnly() {
77-
return maximal(nullptr, false);
92+
return maximal(nullptr, false, false);
7893
}
7994

8095
static TypeExpansionContext
8196
noOpaqueTypeArchetypesSubstitution(ResilienceExpansion expansion) {
82-
return TypeExpansionContext(expansion, nullptr, false);
97+
return TypeExpansionContext(expansion, nullptr, false, false);
8398
}
8499

85100
bool operator==(const TypeExpansionContext &other) const {

include/swift/SIL/SILBuilder.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3067,7 +3067,9 @@ class SILBuilder {
30673067
if (!SILModuleConventions(M).useLoweredAddresses())
30683068
return true;
30693069

3070-
return getTypeLowering(Ty).isLoadable();
3070+
const auto &lowering = getTypeLowering(Ty);
3071+
return lowering.isLoadable() ||
3072+
lowering.getExpansionContext().isPostAbstraction();
30713073
}
30723074

30733075
void appendOperandTypeName(SILType OpdTy, llvm::SmallString<16> &Name) {

include/swift/SIL/SILType.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,7 @@ class SILType {
351351

352352
/// True if the type, or the referenced type of an address type, is loadable.
353353
/// This is the opposite of isAddressOnly.
354-
bool isLoadable(const SILFunction &F) const {
355-
return !isAddressOnly(F);
356-
}
357-
354+
bool isLoadable(const SILFunction &F) const;
358355
bool isLoadable(const SILFunction *f) const { return isLoadable(*f); }
359356

360357
/// True if either:

lib/SIL/IR/SILType.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,10 @@ bool SILType::isLoadableOrOpaque(const SILFunction &F) const {
444444
return isLoadable(F) || !SILModuleConventions(M).useLoweredAddresses();
445445
}
446446

447+
bool SILType::isLoadable(const SILFunction &F) const {
448+
return !isAddressOnly(F) || F.getTypeExpansionContext().isPostAbstraction();
449+
}
450+
447451
bool SILType::isAddressOnly(const SILFunction &F) const {
448452
auto contextType = hasTypeParameter() ? F.mapTypeIntoContext(*this) : *this;
449453

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class CrossModuleOptimization {
8484

8585
bool canSerializeGlobal(SILGlobalVariable *global);
8686

87-
bool canSerializeType(SILType type, TypeExpansionContext typeExpCtx);
87+
bool canSerializeType(SILType type);
8888

8989
bool canUseFromInline(DeclContext *declCtxt);
9090

@@ -158,6 +158,7 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
158158

159159
static void makeTypesUsableFromInline(SILInstruction *I,
160160
CrossModuleOptimization &CMS) {
161+
I->getFunction()->getTypeExpansionContext().setIsPostAbstraction();
161162
InstructionVisitor visitor(I, CMS);
162163
visitor.visit(I);
163164
visitor.result->eraseFromParent();
@@ -331,14 +332,12 @@ bool CrossModuleOptimization::canSerializeFunction(
331332
bool CrossModuleOptimization::canSerializeInstruction(
332333
SILInstruction *inst, FunctionFlags &canSerializeFlags, int maxDepth) {
333334
// First check if any result or operand types prevent serialization.
334-
auto typeExpCtx = inst->getFunction()->getTypeExpansionContext();
335-
336335
for (SILValue result : inst->getResults()) {
337-
if (!canSerializeType(result->getType(), typeExpCtx))
336+
if (!canSerializeType(result->getType()))
338337
return false;
339338
}
340339
for (Operand &op : inst->getAllOperands()) {
341-
if (!canSerializeType(op.get()->getType(), typeExpCtx))
340+
if (!canSerializeType(op.get()->getType()))
342341
return false;
343342
}
344343

@@ -437,23 +436,11 @@ bool CrossModuleOptimization::canSerializeGlobal(SILGlobalVariable *global) {
437436
return true;
438437
}
439438

440-
bool CrossModuleOptimization::canSerializeType(SILType type,
441-
TypeExpansionContext typeExpCtx) {
439+
bool CrossModuleOptimization::canSerializeType(SILType type) {
442440
auto iter = typesChecked.find(type);
443441
if (iter != typesChecked.end())
444442
return iter->getSecond();
445443

446-
if (M.getSwiftModule()->isResilient()) {
447-
auto minResilientCtx = TypeExpansionContext(ResilienceExpansion::Minimal,
448-
typeExpCtx.getContext(),
449-
typeExpCtx.isWholeModuleContext());
450-
auto loadableInMinResilientCtx = M.Types.getTypeLowering(type, minResilientCtx).isLoadable();
451-
if (!loadableInMinResilientCtx) {
452-
typesChecked[type] = false;
453-
return false;
454-
}
455-
}
456-
457444
bool success = !type.getASTType().findIf(
458445
[this](Type rawSubType) {
459446
CanType subType = rawSubType->getCanonicalType();

test/SILOptimizer/package-cmo-resilient-mode.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,31 +172,29 @@ print(prevPkgData)
172172

173173
//--- Lib.swift
174174

175-
// FIXME: handle struct_element_addr %field in resilient mode; requires non-resilience in SIL verify.
176-
// CHECK-RES-NOT: s3Lib9PubStructV6fooVarSivg
177-
// CHECK-RES-NOT: s3Lib9PkgStructV6fooVarSivg
178-
179-
// FIXME: handle `struct $PubStruct` in resilient mode; PubStruct is by-address, so fails in IsLodableOrOpaque check.
180-
// CHECK-RES-NOT: s3Lib9PubStructV6fooVarSivs
181-
// CHECK-RES-NOT: s3Lib9PkgStructV6fooVarSivs
182-
183175
public struct PubStruct {
176+
// CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV6fooVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int {
184177
// CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV6fooVarSivg : $@convention(method) (PubStruct) -> Int
178+
// CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV6fooVarSivM : $@yield_once @convention(method) (@inout PubStruct) -> @yields @inout Int {
185179
// CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV6fooVarSivM : $@yield_once @convention(method) (@inout PubStruct) -> @yields @inout Int {
180+
// CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV6fooVarSivs : $@convention(method) (Int, @inout PubStruct) -> () {
186181
// CHECK-NONRES-DAG: sil [transparent] [serialized] [canonical] [ossa] @$s3Lib9PubStructV6fooVarSivs : $@convention(method) (Int, @inout PubStruct) -> () {
187182
public var fooVar: Int
188183

189184
public init(_ arg: Int) {
185+
// CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> @out PubStruct {
190186
// CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructVyACSicfC : $@convention(method) (Int, @thin PubStruct.Type) -> PubStruct {
191187
fooVar = arg
192188
}
193189
public func f() {
190+
// CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV1fyyF : $@convention(method) (@in_guaranteed PubStruct) -> () {
194191
// CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib9PubStructV1fyyF : $@convention(method) (PubStruct) -> () {
195192
print(fooVar)
196193
}
197194
}
198195

199196
public func runPub(_ arg: PubStruct) {
197+
// CHECK-RES-DAG: sil [serialized] [canonical] @$s3Lib6runPubyyAA0C6StructVF : $@convention(thin) (@in_guaranteed PubStruct) -> () {
200198
// CHECK-NONRES-DAG: sil [serialized] [canonical] @$s3Lib6runPubyyAA0C6StructVF : $@convention(thin) (PubStruct) -> () {
201199
print(arg)
202200
}
@@ -223,24 +221,30 @@ public func runFrPub(_ arg: FrPubStruct) {
223221

224222
package struct PkgStruct {
225223
// fooVar.getter
224+
// CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV6fooVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int {
226225
// CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib9PkgStructV6fooVarSivg : $@convention(method) (PkgStruct) -> Int {
227226
// fooVar.modify
227+
// CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV6fooVarSivM : $@yield_once @convention(method) (@inout PkgStruct) -> @yields @inout Int {
228228
// CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib9PkgStructV6fooVarSivM : $@yield_once @convention(method) (@inout PkgStruct) -> @yields @inout Int {
229229
// fooVar.setter
230+
// CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV6fooVarSivs : $@convention(method) (Int, @inout PkgStruct) -> () {
230231
// CHECK-NONRES-DAG: sil package [transparent] [serialized] [canonical] [ossa] @$s3Lib9PkgStructV6fooVarSivs : $@convention(method) (Int, @inout PkgStruct) -> () {
231232
package var fooVar: Int
232233

233234
package init(_ arg: Int) {
235+
// CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructVyACSicfC : $@convention(method) (Int, @thin PkgStruct.Type) -> @out PkgStruct {
234236
// CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructVyACSicfC : $@convention(method) (Int, @thin PkgStruct.Type) -> PkgStruct {
235237
fooVar = arg
236238
}
237239
package func f() {
240+
// CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV1fyyF : $@convention(method) (@in_guaranteed PkgStruct) -> () {
238241
// CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib9PkgStructV1fyyF : $@convention(method) (PkgStruct) -> () {
239242
print(fooVar)
240243
}
241244
}
242245

243246
package func runPkg(_ arg: PkgStruct) {
247+
// CHECK-RES-DAG: sil package [serialized] [canonical] @$s3Lib6runPkgyyAA0C6StructVF : $@convention(thin) (@in_guaranteed PkgStruct) -> () {
244248
// CHECK-NONRES-DAG: sil package [serialized] [canonical] @$s3Lib6runPkgyyAA0C6StructVF : $@convention(thin) (PkgStruct) -> () {
245249
print(arg)
246250
}

0 commit comments

Comments
 (0)