Skip to content

Commit 937adaf

Browse files
committed
[PackageCMO] Don't allow modifying AST
This PR prevents `@usableFromInline` attribute from being added to a decl, which modifies AST and should not be allowed in PackageCMO. Ensures that the generated interfaces with PackageCMO enabled are not affected by the optimization and do not contain modified AST. rdar://130292190
1 parent 5172b72 commit 937adaf

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,11 @@ void CrossModuleOptimization::makeFunctionUsableFromInline(SILFunction *function
815815

816816
/// Make a nominal type, including it's context, usable from inline.
817817
void CrossModuleOptimization::makeDeclUsableFromInline(ValueDecl *decl) {
818+
// In resilient Package CMO (conservative) mode, AST should
819+
// not be modified by adding @usableFromInline to types.
820+
if (isPackageCMOEnabled(M.getSwiftModule()))
821+
return;
822+
818823
if (decl->getEffectiveAccess() >= AccessLevel::Package)
819824
return;
820825

@@ -824,6 +829,13 @@ void CrossModuleOptimization::makeDeclUsableFromInline(ValueDecl *decl) {
824829

825830
if (!isPackageOrPublic(decl->getFormalAccess()) &&
826831
!decl->isUsableFromInline()) {
832+
// FIXME: In the default (conservative) mode, below should not be
833+
// called, as adding @usableFromInline modifies the AST. However,
834+
// some existing apps might already rely on this code path even in
835+
// default mode, in which case linker errors might get thrown without
836+
// it. Should probably audit before restricting this path to only
837+
// non-conservative modes.
838+
827839
// Mark the nominal type as "usableFromInline".
828840
// TODO: find a way to do this without modifying the AST. The AST should be
829841
// immutable at this point.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %empty-directory(%t)
2+
3+
/// First Test: Check `@_usableFromInline` is not added to types in PackageCMO mode.
4+
// RUN: %target-swift-frontend -parse-as-library %s -O -wmo -cross-module-optimization -module-name=Lib -package-name pkg -emit-module -o %t/Lib-cmo.swiftmodule
5+
// RUN: %target-sil-opt -module-name Lib -enable-sil-verify-all %t/Lib-cmo.swiftmodule -o %t/Lib-cmo.sil
6+
7+
// RUN: %target-swift-frontend -parse-as-library %s -O -wmo -enable-library-evolution -experimental-allow-non-resilient-access -experimental-package-cmo -module-name=Lib -package-name pkg -emit-module -o %t/Lib-package-cmo.swiftmodule
8+
// RUN: %target-sil-opt -module-name Lib -enable-sil-verify-all %t/Lib-package-cmo.swiftmodule -o %t/Lib-package-cmo.sil
9+
10+
// RUN: %FileCheck %s --check-prefix=CHECK-CMO < %t/Lib-cmo.sil
11+
// RUN: %FileCheck %s --check-prefix=CHECK-PACKAGE-CMO < %t/Lib-package-cmo.sil
12+
13+
/// Second Test: Check .swiftinterface files with and without PackageCMO have the same decl signatures without `@_usableFromInline`.
14+
// RUN: %target-swift-frontend -emit-module %s -I %t \
15+
// RUN: -module-name Lib -package-name pkg \
16+
// RUN: -enable-library-evolution -swift-version 6 \
17+
// RUN: -emit-module-path %t/Lib.swiftmodule \
18+
// RUN: -emit-module-interface-path %t/Lib.swiftinterface \
19+
// RUN: -emit-private-module-interface-path %t/Lib.private.swiftinterface \
20+
// RUN: -emit-package-module-interface-path %t/Lib.package.swiftinterface
21+
// RUN: %FileCheck %s --check-prefixes=CHECK-PKG-INTERFACE,CHECK-INTERFACE < %t/Lib.package.swiftinterface
22+
// RUN: %FileCheck %s --check-prefix=CHECK-INTERFACE < %t/Lib.swiftinterface
23+
24+
// RUN: rm -rf %t/Lib.swiftinterface
25+
// RUN: rm -rf %t/Lib.private.swiftinterface
26+
// RUN: rm -rf %t/Lib.package.swiftinterface
27+
28+
// RUN: %target-swift-frontend -emit-module %s -I %t \
29+
// RUN: -module-name Lib -package-name pkg \
30+
// RUN: -enable-library-evolution -swift-version 6 \
31+
// RUN: -O -wmo \
32+
// RUN: -experimental-allow-non-resilient-access -experimental-package-cmo \
33+
// RUN: -emit-module-path %t/Lib.swiftmodule \
34+
// RUN: -emit-module-interface-path %t/Lib.swiftinterface \
35+
// RUN: -emit-private-module-interface-path %t/Lib.private.swiftinterface \
36+
// RUN: -emit-package-module-interface-path %t/Lib.package.swiftinterface
37+
// RUN: %FileCheck %s --check-prefixes=CHECK-PKG-INTERFACE,CHECK-INTERFACE < %t/Lib.package.swiftinterface
38+
// RUN: %FileCheck %s --check-prefix=CHECK-INTERFACE < %t/Lib.swiftinterface
39+
40+
// REQUIRES: swift_in_compiler
41+
42+
// CHECK-PACKAGE-CMO-NOT: @usableFromInline
43+
// CHECK-PKG-INTERFACE-NOT: @usableFromInline
44+
// CHECK-INTERFACE-NOT: @usableFromInline
45+
46+
// CHECK-PKG-INTERFACE: final package class PkgKlass {
47+
// CHECK-PKG-INTERFACE: @inline(never) package func createKlass() -> Lib.PkgKlass
48+
// CHECK-INTERFACE: @inline(never) public func classWithPublicProperty<T>(_ t: T) -> Swift.Int
49+
// CHECK-INTERFACE: @inline(never) public func run()
50+
51+
// CHECK-CMO: @usableFromInline
52+
// CHECK-CMO-NEXT: final class InternalKlass
53+
final class InternalKlass {
54+
var myVar: Int = 11
55+
init() {}
56+
}
57+
58+
final package class PkgKlass {
59+
var internalVar: InternalKlass = InternalKlass()
60+
package init() {}
61+
}
62+
63+
@inline(never)
64+
package func createKlass() -> PkgKlass {
65+
return PkgKlass()
66+
}
67+
68+
// CHECK-CMO: sil [serialized] [noinline] [canonical] @$s3Lib23classWithPublicPropertyySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
69+
@inline(never)
70+
public func classWithPublicProperty<T>(_ t: T) -> Int {
71+
// CHECK-CMO: ref_element_addr {{.*}} : $InternalKlass, #InternalKlass.myVar
72+
return createKlass().internalVar.myVar
73+
}
74+
75+
@inline(never)
76+
public func run() {
77+
print(classWithPublicProperty(33))
78+
}

0 commit comments

Comments
 (0)