Skip to content

Commit 0802ff5

Browse files
committed
Move bypassing resilience in package logic to
isResilient(ModuleDecl, ResilienceExpansion). isResilient() returns the decl's resilience by definition and should not be altered whether bypassing optimization is enabled or not. The overloaded isResilient(ModuleDecl..) is used for accessing a decl from a client module, which is the appropriate place to opt in for non-resilience in package. Resolves rdar://123031292
1 parent 2294d9f commit 0802ff5

File tree

7 files changed

+115
-40
lines changed

7 files changed

+115
-40
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2924,6 +2924,11 @@ class ValueDecl : public Decl {
29242924
/// if the base declaration is \c open, the override might have to be too.
29252925
bool hasOpenAccess(const DeclContext *useDC) const;
29262926

2927+
/// True if opted in for bypassing resilience within a package. Allowed only on
2928+
/// access from the \p accessingModule to a package decl in the defining
2929+
/// binary (not interface) module within the same package.
2930+
bool bypassResilienceInPackage(ModuleDecl *accessingModule) const;
2931+
29272932
/// FIXME: This is deprecated.
29282933
bool isRecursiveValidation() const;
29292934

lib/AST/Decl.cpp

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2514,9 +2514,9 @@ static bool isDirectToStorageAccess(const DeclContext *UseDC,
25142514

25152515
// If the storage is resilient, we cannot access it directly at all.
25162516
if (var->isResilient(UseDC->getParentModule(),
2517-
UseDC->getResilienceExpansion()))
2518-
return var->getModuleContext()->getBypassResilience();
2519-
2517+
UseDC->getResilienceExpansion())) {
2518+
return (var->getModuleContext()->getBypassResilience());
2519+
}
25202520
if (isa<ConstructorDecl>(AFD) || isa<DestructorDecl>(AFD)) {
25212521
// The access must also be a member access on 'self' in all language modes.
25222522
if (!isAccessOnSelf)
@@ -2969,13 +2969,7 @@ bool AbstractStorageDecl::isResilient() const {
29692969
if (!accessScope.isPublicOrPackage())
29702970
return false;
29712971

2972-
if (!getModuleContext()->isResilient())
2973-
return false;
2974-
2975-
// Allows bypassing resilience checks for package decls
2976-
// at use site within a package if opted in, whether the
2977-
// loaded module was built resiliently or not.
2978-
return !getDeclContext()->bypassResilienceInPackage(accessScope.isPackage());
2972+
return getModuleContext()->isResilient();
29792973
}
29802974

29812975
bool AbstractStorageDecl::isResilient(ModuleDecl *M,
@@ -2984,7 +2978,11 @@ bool AbstractStorageDecl::isResilient(ModuleDecl *M,
29842978
case ResilienceExpansion::Minimal:
29852979
return isResilient();
29862980
case ResilienceExpansion::Maximal:
2987-
return M != getModuleContext() && isResilient();
2981+
if (getModuleContext() == M)
2982+
return false;
2983+
if (bypassResilienceInPackage(M))
2984+
return false;
2985+
return isResilient();
29882986
}
29892987
llvm_unreachable("bad resilience expansion");
29902988
}
@@ -4206,6 +4204,14 @@ bool ValueDecl::hasOpenAccess(const DeclContext *useDC) const {
42064204
return access == AccessLevel::Open;
42074205
}
42084206

4207+
bool ValueDecl::bypassResilienceInPackage(ModuleDecl *accessingModule) const {
4208+
return getASTContext().LangOpts.EnableBypassResilienceInPackage &&
4209+
getModuleContext()->inSamePackage(accessingModule) &&
4210+
!getModuleContext()->isBuiltFromInterface() &&
4211+
getFormalAccessScope(/*useDC=*/nullptr,
4212+
/*treatUsableFromInlineAsPublic=*/true).isPackage();
4213+
}
4214+
42094215
/// Given the formal access level for using \p VD, compute the scope where
42104216
/// \p VD may be accessed, taking \@usableFromInline, \@testable imports,
42114217
/// \@_spi imports, and enclosing access levels into account.
@@ -5046,14 +5052,7 @@ bool NominalTypeDecl::isFormallyResilient() const {
50465052
bool NominalTypeDecl::isResilient() const {
50475053
if (!isFormallyResilient())
50485054
return false;
5049-
if (!getModuleContext()->isResilient())
5050-
return false;
5051-
// Allows bypassing resilience checks for package decls
5052-
// at use site within a package if opted in, whether the
5053-
// loaded module was built resiliently or not.
5054-
auto accessScope = getFormalAccessScope(/*useDC=*/nullptr,
5055-
/*treatUsableFromInlineAsPublic=*/true);
5056-
return !getDeclContext()->bypassResilienceInPackage(accessScope.isPackage());
5055+
return getModuleContext()->isResilient();
50575056
}
50585057

50595058
DestructorDecl *NominalTypeDecl::getValueTypeDestructor() {
@@ -5084,9 +5083,12 @@ bool NominalTypeDecl::isResilient(ModuleDecl *M,
50845083
case ResilienceExpansion::Maximal:
50855084
// We can access declarations from the same module
50865085
// non-resiliently in a maximal context.
5087-
if (M == getModuleContext()) {
5086+
if (getModuleContext() == M)
50885087
return false;
5089-
}
5088+
// Non-resilient if bypass optimization in package is enabled
5089+
if (bypassResilienceInPackage(M))
5090+
return false;
5091+
50905092
// If a protocol is originally declared in the current module, then we
50915093
// directly expose protocol witness tables and their contents for any
50925094
// conformances in the same module as symbols. If the protocol later
@@ -6377,7 +6379,7 @@ bool EnumDecl::isFormallyExhaustive(const DeclContext *useDC) const {
63776379
// package enum is optimized with bypassing resilience checks.
63786380
if (!accessScope.isPublicOrPackage())
63796381
return true;
6380-
if (useDC && useDC->bypassResilienceInPackage(accessScope.isPackage()))
6382+
if (useDC && bypassResilienceInPackage(useDC->getParentModule()))
63816383
return true;
63826384

63836385
// All other checks are use-site specific; with no further information, the

lib/IRGen/GenDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5979,6 +5979,7 @@ bool IRGenModule::isResilient(NominalTypeDecl *D,
59795979

59805980
if (D->getModuleContext()->getBypassResilience())
59815981
return false;
5982+
59825983
if (expansion == ResilienceExpansion::Maximal &&
59835984
Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
59845985
return false;

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ namespace {
122122
template <typename DeclType>
123123
bool checkResilience(DeclType *D, ModuleDecl *M,
124124
ResilienceExpansion expansion) {
125+
// auto acl = D->getFormalAccessScope(/*useDC=*/nullptr,
126+
// /*treatUsableFromInlineAsPublic=*/true);
127+
// if (D->getDeclContext()->bypassResilienceInPackage(acl.isPackage()))
128+
// return false;
129+
125130
return !D->getModuleContext()->getBypassResilience() &&
126131
D->isResilient(M, expansion);
127132
}

test/IRGen/Inputs/package_types/resilient_struct.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
package struct Star {
2+
package var planet: Int = 123
3+
package init() {}
4+
}
5+
16
package struct Point {
27
package var x: Int // read-write stored property
38
package let y: Int // read-only stored property

test/IRGen/package_resilience.swift

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,29 @@
1010
// RUN: %target-swift-frontend -package-name MyPkg -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/Inputs/package_types/resilient_struct.swift
1111
// RUN: %target-swift-frontend -package-name MyPkg -emit-module -enable-library-evolution -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/Inputs/package_types/resilient_enum.swift
1212
// RUN: %target-swift-frontend -package-name MyPkg -emit-module -enable-library-evolution -emit-module-path=%t/resilient_class.swiftmodule -module-name=resilient_class -I %t %S/Inputs/package_types/resilient_class.swift
13-
// RUN: %target-swift-frontend -package-name MyPkg -package-bypass-resilience-optimization -enable-objc-interop -I %t -emit-ir -enable-library-evolution %t/package_resilience.swift | %FileCheck %t/package_resilience.swift --check-prefixes=CHECK,CHECK-objc,CHECK-objc%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-%target-import-type-objc-STABLE-ABI-%target-mandates-stable-abi,CHECK-%target-sdk-name -DINT=i%target-ptrsize -D#MDWORDS=7 -D#MDSIZE32=52 -D#MDSIZE64=80 -D#WORDSIZE=%target-alignment
14-
// RUN: %target-swift-frontend -package-name MyPkg -package-bypass-resilience-optimization -disable-objc-interop -I %t -emit-ir -enable-library-evolution %t/package_resilience.swift | %FileCheck %t/package_resilience.swift --check-prefixes=CHECK,CHECK-native,CHECK-native%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-native-STABLE-ABI-%target-mandates-stable-abi,CHECK-%target-sdk-name -DINT=i%target-ptrsize -D#MDWORDS=4 -D#MDSIZE32=40 -D#MDSIZE64=56 -D#WORDSIZE=%target-alignment
15-
// RUN: %target-swift-frontend -package-name MyPkg -package-bypass-resilience-optimization -I %t -emit-ir -enable-library-evolution -O %t/package_resilience.swift -package-name MyPkg
13+
14+
// RUN: %target-swift-frontend -package-name MyPkg -module-name=package_resilience -package-bypass-resilience-optimization -enable-objc-interop -I %t -emit-ir -enable-library-evolution %t/package_resilience.swift | %FileCheck %t/package_resilience.swift --check-prefixes=CHECK,CHECK-objc,CHECK-objc%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-%target-import-type-objc-STABLE-ABI-%target-mandates-stable-abi,CHECK-%target-sdk-name -DINT=i%target-ptrsize -D#MDWORDS=7 -D#MDSIZE32=52 -D#MDSIZE64=80 -D#WORDSIZE=%target-alignment
15+
16+
// RUN: %target-swift-frontend -package-name MyPkg -module-name=package_resilience -package-bypass-resilience-optimization -disable-objc-interop -I %t -emit-ir -enable-library-evolution %t/package_resilience.swift | %FileCheck %t/package_resilience.swift --check-prefixes=CHECK,CHECK-native,CHECK-native%target-ptrsize,CHECK-%target-ptrsize,CHECK-%target-cpu,CHECK-native-STABLE-ABI-%target-mandates-stable-abi,CHECK-%target-sdk-name -DINT=i%target-ptrsize -D#MDWORDS=4 -D#MDSIZE32=40 -D#MDSIZE64=56 -D#WORDSIZE=%target-alignment
17+
18+
// RUN: %target-swift-frontend -package-name MyPkg -module-name=package_resilience -package-bypass-resilience-optimization -I %t -emit-ir -enable-library-evolution -O %t/package_resilience.swift -package-name MyPkg
19+
1620
// REQUIRES: objc_codegen
1721
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos
1822
// REQUIRES: CPU=x86_64 || CPU=arm64
1923

20-
// CHECK: @"$s18package_resilience26ClassWithResilientPropertyC1p16resilient_struct5PointVvpWvd" = constant [[INT]] {{8|16}}, align [[#WORDSIZE]]
21-
// CHECK: @"$s18package_resilience26ClassWithResilientPropertyC1s16resilient_struct4SizeVvpWvd" = constant [[INT]] {{32|16}}, align [[#WORDSIZE]]
24+
// CHECK: @"$s18package_resilience26ClassWithResilientPropertyC1p16resilient_struct5PointVvpWvd" = hidden constant [[INT]] {{8|16}}, align [[#WORDSIZE]]
25+
// CHECK: @"$s18package_resilience26ClassWithResilientPropertyC1s16resilient_struct4SizeVvpWvd" = hidden constant [[INT]] {{32|16}}, align [[#WORDSIZE]]
2226

23-
// CHECK: @"$s18package_resilience33ClassWithResilientlySizedPropertyC1r16resilient_struct9RectangleVvpWvd" = constant [[INT]] {{8|16}}, align [[#WORDSIZE]]
24-
// CHECK: @"$s18package_resilience33ClassWithResilientlySizedPropertyC5colors5Int32VvpWvd" = constant [[INT]] 56, align [[#WORDSIZE]]
27+
// CHECK: @"$s18package_resilience33ClassWithResilientlySizedPropertyC1r16resilient_struct9RectangleVvpWvd" = hidden constant [[INT]] {{8|16}}, align [[#WORDSIZE]]
28+
// CHECK: @"$s18package_resilience33ClassWithResilientlySizedPropertyC5colors5Int32VvpWvd" = hidden constant [[INT]] 56, align [[#WORDSIZE]]
2529

30+
// class metadata base offset for package_resilience.MyResilientParent
2631
// CHECK: @"$s18package_resilience17MyResilientParentCMo" = constant [[BOUNDS:{ (i32|i64), i32, i32 }]]
2732
// CHECK-32-SAME: { [[INT]] [[#MDSIZE32]], i32 3, i32 [[#MDWORDS + 6 + 2]] }, align [[#WORDSIZE]]
2833
// CHECK-64-SAME: { [[INT]] [[#MDSIZE64]], i32 3, i32 [[#MDWORDS + 3 + 2]] }, align [[#WORDSIZE]]
2934

30-
// CHECK: @"$s18package_resilience16MyResilientChildC5fields5Int32VvpWvd" = constant [[INT]] [[#WORDSIZE + WORDSIZE + 4]], align [[#WORDSIZE]]
35+
// CHECK: @"$s18package_resilience16MyResilientChildC5fields5Int32VvpWvd" = hidden constant [[INT]] [[#WORDSIZE + WORDSIZE + 4]], align [[#WORDSIZE]]
3136

3237
// CHECK: @"$s18package_resilience16MyResilientChildCMo" = {{(protected )?}}{{(dllexport )?}}constant [[BOUNDS]]
3338
// CHECK-32-SAME: { [[INT]] [[#MDSIZE32 + WORDSIZE + WORDSIZE]], i32 3, i32 [[#MDWORDS + 6 + 3]] }
@@ -41,26 +46,31 @@
4146
// CHECK-32-SAME: { [[INT]] [[#MDSIZE32 + WORDSIZE + WORDSIZE + WORDSIZE]], i32 3, i32 [[#MDWORDS + 6 + 5]] }
4247
// CHECK-64-SAME: { [[INT]] [[#MDSIZE64 + WORDSIZE + WORDSIZE + WORDSIZE]], i32 3, i32 [[#MDWORDS + 3 + 5]] }
4348

44-
// CHECK: @"$s18package_resilience27ClassWithEmptyThenResilientC5emptyAA0E0VvpWvd" = constant [[INT]] 0,
45-
// CHECK: @"$s18package_resilience27ClassWithEmptyThenResilientC9resilient0H7_struct0G3IntVvpWvd" = constant [[INT]] [[#WORDSIZE + WORDSIZE]], align [[#WORDSIZE]]
46-
// CHECK: @"$s18package_resilience27ClassWithResilientThenEmptyC9resilient0H7_struct0E3IntVvpWvd" = constant [[INT]] [[#WORDSIZE + WORDSIZE]], align [[#WORDSIZE]]
47-
// CHECK: @"$s18package_resilience27ClassWithResilientThenEmptyC5emptyAA0G0VvpWvd" = constant [[INT]] 0,
49+
// CHECK: @"$s18package_resilience27ClassWithEmptyThenResilientC5emptyAA0E0VvpWvd" = hidden constant [[INT]] 0,
50+
// CHECK: @"$s18package_resilience27ClassWithEmptyThenResilientC9resilient0H7_struct0G3IntVvpWvd" = hidden constant [[INT]] [[#WORDSIZE + WORDSIZE]], align [[#WORDSIZE]]
51+
// CHECK: @"$s18package_resilience27ClassWithResilientThenEmptyC9resilient0H7_struct0E3IntVvpWvd" = hidden constant [[INT]] [[#WORDSIZE + WORDSIZE]], align [[#WORDSIZE]]
52+
// CHECK: @"$s18package_resilience27ClassWithResilientThenEmptyC5emptyAA0G0VvpWvd" = hidden constant [[INT]] 0,
4853

4954
import resilient_class
5055
import resilient_struct
5156
import resilient_enum
5257

5358
// Concrete class with resilient stored property
54-
55-
package class ClassWithResilientProperty {
59+
package final class ClassWithResilientProperty {
5660
package let p: Point
5761
package let s: Size
5862
package let color: Int32
63+
package let px: Int
5964

6065
package init(p: Point, s: Size, color: Int32) {
6166
self.p = p
67+
self.px = p.x
6268
self.s = s
6369
self.color = color
70+
71+
}
72+
func foo(p: Point) -> Int {
73+
return p.x + 31
6474
}
6575
}
6676

@@ -230,15 +240,17 @@ public func memoryLayoutDotAlignmentWithResilientStruct() -> Int {
230240
return MemoryLayout<Size>.alignment
231241
}
232242

233-
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc [[BOUNDS:{ (i32|i64), (i32|i64), i8 }]] @"$s18package_resilience31constructResilientEnumNoPayload14resilient_enum6MediumOyF"
243+
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s18package_resilience31constructResilientEnumNoPayload14resilient_enum6MediumOyF"
234244
package func constructResilientEnumNoPayload() -> Medium {
235-
// CHECK: ret [[BOUNDS]] { {{i32|i64}} 0, {{i32|i64}} 0, i8 2 }
245+
// CHECK: [[FIELD_PTR:%.*]] = getelementptr inbounds %T14resilient_enum6MediumO, ptr %0, i32 0, i32 1
246+
// CHECK: ret void
236247
return Medium.Paper
237248
}
238249

239-
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc [[BOUNDS:{ (i32|i64), (i32|i64), i8 }]] @"$s18package_resilience39constructExhaustiveWithResilientMembers14resilient_enum11SimpleShapeOyF"() #0 {
250+
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s18package_resilience39constructExhaustiveWithResilientMembers14resilient_enum11SimpleShapeOyF"
240251
package func constructExhaustiveWithResilientMembers() -> SimpleShape {
241-
// CHECK: ret [[BOUNDS]] { {{i32|i64}} 0, {{i32|i64}} 0, i8 1 }
252+
// CHECK: [[FIELD_PTR:%.*]] = getelementptr inbounds %T14resilient_enum11SimpleShapeO, ptr %0, i32 0, i32 1
253+
// CHECK: ret void
242254
return .KleinBottle
243255
}
244256

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-frontend -emit-module %t/Utils.swift \
5+
// RUN: -module-name Utils -swift-version 5 -I %t \
6+
// RUN: -package-name mypkg \
7+
// RUN: -enable-library-evolution \
8+
// RUN: -emit-module -emit-module-path %t/Utils.swiftmodule
9+
10+
// RUN: %target-swift-frontend -emit-silgen %t/Client.swift -I %t -module-name Client -package-name mypkg | %FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT
11+
// RUN: %target-swift-frontend -emit-silgen %t/Client.swift -I %t -module-name Client -package-name mypkg -enable-library-evolution | %FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT
12+
13+
// RUN: %target-swift-frontend -emit-silgen %t/Client.swift -I %t -module-name Client -package-name mypkg -package-bypass-resilience-optimization | %FileCheck %s --check-prefixes=CHECK,CHECK-BYPASS
14+
// RUN: %target-swift-frontend -emit-silgen %t/Client.swift -I %t -module-name Client -package-name mypkg -package-bypass-resilience-optimization -enable-library-evolution | %FileCheck %s --check-prefixes=CHECK,CHECK-BYPASS
15+
16+
//--- Utils.swift
17+
package struct PkgStruct {
18+
package var pkgVar = 1
19+
package init() {}
20+
}
21+
22+
public struct PubStruct {
23+
public var pubVar = 1
24+
public init() {}
25+
}
26+
27+
//--- Client.swift
28+
import Utils
29+
30+
func foo() {
31+
print(PkgStruct().pkgVar)
32+
}
33+
34+
// CHECK: sil hidden [ossa] @$s6Client3fooyyF : $@convention(thin) () -> () {
35+
// CHECK-DEFAULT: [[F_REF:%.*]] = function_ref @$s5Utils9PkgStructV6pkgVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int
36+
// CHECK-DEFAULT: sil package_external @$s5Utils9PkgStructV6pkgVarSivg : $@convention(method) (@in_guaranteed PkgStruct) -> Int
37+
// CHECK-BYPASS: [[ADDR:%.*]] = struct_element_addr %7 : $*PkgStruct, #PkgStruct.pkgVar
38+
39+
func bar() {
40+
print(PubStruct().pubVar)
41+
}
42+
43+
// CHECK: sil hidden [ossa] @$s6Client3baryyF : $@convention(thin) () -> () {
44+
// CHECK: [[F_REF:%.*]] = function_ref @$s5Utils9PubStructV6pubVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int
45+
// CHECK: sil @$s5Utils9PubStructV6pubVarSivg : $@convention(method) (@in_guaranteed PubStruct) -> Int

0 commit comments

Comments
 (0)