[Pacage CMO] Update and add more tests

This commit is contained in:
elsh
2024-10-11 21:26:43 -07:00
parent d3c6688067
commit 82a0549000
7 changed files with 355 additions and 232 deletions

View File

@@ -0,0 +1,30 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -o %t/IR-nonres.ir
// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution -o %t/IR-res.ir
// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution -wmo -Xfrontend -experimental-allow-non-resilient-access -Xfrontend -experimental-package-cmo -o %t/IR-res-package-cmo.ir
// RUN: %FileCheck %s --check-prefix=CHECK-IR-NONRES < %t/IR-nonres.ir
// RUN: %FileCheck %s --check-prefix=CHECK-IR-RES < %t/IR-res.ir
// RUN: %FileCheck %s --check-prefix=CHECK-IR-RES < %t/IR-res-package-cmo.ir
public struct S {
public static let x = "hello world"
package static let y = "dogs cats"
}
public struct R {
package static let a = "foo"
public static let b = "bar"
}
// CHECK-IR-NONRES: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @"$s4File1SV1xSSvau"()
// CHECK-IR-NONRES: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @"$s4File1SV1ySSvau"()
// CHECK-IR-NONRES: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @"$s4File1RV1aSSvau"()
// CHECK-IR-NONRES: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @"$s4File1RV1bSSvau"()
// CHECK-IR-RES: define hidden swiftcc ptr @"$s4File1SV1xSSvau"()
// CHECK-IR-RES: define hidden swiftcc ptr @"$s4File1SV1ySSvau"()
// CHECK-IR-RES: define hidden swiftcc ptr @"$s4File1RV1aSSvau"()
// CHECK-IR-RES: define hidden swiftcc ptr @"$s4File1RV1bSSvau"()

View File

@@ -0,0 +1,65 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -module-name=Lib -package-name libpkg -emit-silgen %s -enable-library-evolution -wmo -o %t/Lib-no-pcmo-silgen.sil
// RUN: %target-swift-frontend -module-name=Lib -package-name libpkg -emit-sil %s -enable-library-evolution -wmo -o %t/Lib-no-pcmo-sil.sil
// RUN: %target-swift-frontend -module-name=Lib -package-name libpkg -emit-ir %s -enable-library-evolution -wmo -o %t/Lib-no-pcmo-ir.ll -emit-tbd-path %t/Lib-no-pcmo-tbd.tbd -tbd-install_name Lib
// RUN: %target-swift-frontend -module-name=Lib -package-name libpkg -emit-silgen %s -enable-library-evolution -wmo -allow-non-resilient-access -package-cmo -o %t/Lib-silgen.sil
// RUN: %target-swift-frontend -module-name=Lib -package-name libpkg -emit-sil %s -enable-library-evolution -wmo -allow-non-resilient-access -package-cmo -o %t/Lib-sil.sil
// RUN: %target-swift-frontend -module-name=Lib -package-name libpkg -emit-ir %s -enable-library-evolution -wmo -allow-non-resilient-access -package-cmo -o %t/Lib-ir.ll -emit-tbd-path %t/Lib-tbd.tbd -tbd-install_name Lib
// RUN: %FileCheck %s --check-prefix=CHECK-NO-PCMO-SILGEN < %t/Lib-no-pcmo-silgen.sil
// RUN: %FileCheck %s --check-prefix=CHECK-NO-PCMO-SIL < %t/Lib-no-pcmo-sil.sil
// RUN: %FileCheck %s --check-prefix=CHECK-NO-PCMO-IR < %t/Lib-no-pcmo-ir.ll
// RUN: %FileCheck %s --check-prefix=CHECK-NO-PCMO-TBD < %t/Lib-no-pcmo-tbd.tbd
// RUN: %FileCheck %s --check-prefix=CHECK-SILGEN < %t/Lib-silgen.sil
// RUN: %FileCheck %s --check-prefix=CHECK-SIL < %t/Lib-sil.sil
// RUN: %FileCheck %s --check-prefix=CHECK-IR < %t/Lib-ir.ll
// RUN: %FileCheck %s --check-prefix=CHECK-TBD < %t/Lib-tbd.tbd
/// TEST that a public (or package) protocol witness thunk gets a shared linkage if Package CMO is enabled.
/// It also gets [serialized] in emit-silgen.
///
// protocol witness for Proto.foo.getter in conformance Pub
// CHECK-NO-PCMO-SILGEN-DAG: sil private [transparent] [thunk] [ossa] @$s3Lib3PubVAA5ProtoA2aDP3fooSSvgTW : $@convention(witness_method: Proto) (@in_guaranteed Pub) -> @owned String {
// CHECK-SILGEN-DAG: sil shared [transparent] [serialized] [thunk] [ossa] @$s3Lib3PubVAA5ProtoA2aDP3fooSSvgTW : $@convention(witness_method: Proto) (@in_guaranteed Pub) -> @owned String {
// CHECK-NO-PCMO-SIL-DAG: sil private [transparent] [thunk] @$s3Lib3PubVAA5ProtoA2aDP3fooSSvgTW : $@convention(witness_method: Proto) (@in_guaranteed Pub) -> @owned String {
// CHECK-SIL-DAG: sil shared [transparent] [thunk] @$s3Lib3PubVAA5ProtoA2aDP3fooSSvgTW : $@convention(witness_method: Proto) (@in_guaranteed Pub) -> @owned String {
// CHECK-NO-PCMO-IR-DAG: define internal swiftcc { {{i64|i32}}, ptr } @"$s3Lib3PubVAA5ProtoA2aDP3fooSSvgTW"
// CHECK-IR-DAG: define linkonce_odr hidden swiftcc { {{i64|i32}}, ptr } @"$s3Lib3PubVAA5ProtoA2aDP3fooSSvgTW"
// protocol witness for Proto.bar(_:) in conformance Pub
// CHECK-NO-PCMO-SILGEN-DAG: sil private [transparent] [thunk] [ossa] @$s3Lib3PubVAA5ProtoA2aDP3baryS2iFTW : $@convention(witness_method: Proto) (Int, @in_guaranteed Pub) -> Int {
// CHECK-SILGEN-DAG: sil shared [transparent] [serialized] [thunk] [ossa] @$s3Lib3PubVAA5ProtoA2aDP3baryS2iFTW : $@convention(witness_method: Proto) (Int, @in_guaranteed Pub) -> Int {
// CHECK-NO-PCMO-SIL-DAG: sil private [transparent] [thunk] @$s3Lib3PubVAA5ProtoA2aDP3baryS2iFTW : $@convention(witness_method: Proto) (Int, @in_guaranteed Pub) -> Int {
// CHECK-SIL-DAG: sil shared [transparent] [thunk] @$s3Lib3PubVAA5ProtoA2aDP3baryS2iFTW : $@convention(witness_method: Proto) (Int, @in_guaranteed Pub) -> Int {
// CHECK-NO-PCMO-IR-DAG: define internal swiftcc {{i64|i32}} @"$s3Lib3PubVAA5ProtoA2aDP3baryS2iFTW"
// CHECK-IR-DAG: define linkonce_odr hidden swiftcc i64 @"$s3Lib3PubVAA5ProtoA2aDP3baryS2iFTW"
// CHECK-NO-PCMO-TBD-NOT: s3Lib3PubVAA5ProtoA2aDP3fooSSvgTW
// CHECK-NO-PCMO-TBD-NOT: s3Lib3PubVAA5ProtoA2aDP3baryS2iFTW
// CHECK-TBD-NOT: s3Lib3PubVAA5ProtoA2aDP3fooSSvgTW
// CHECK-TBD-NOT: s3Lib3PubVAA5ProtoA2aDP3baryS2iFTW
public protocol Proto {
var foo: String { get set }
func bar(_ arg: Int) -> Int
}
public struct Pub: Proto {
public var foo = "foo"
public func bar(_ arg: Int) -> Int {
return arg
}
}

View File

@@ -1,13 +0,0 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s | %FileCheck %s --check-prefix=CHECK-IR-NONRES
// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution | %FileCheck %s --check-prefix=CHECK-IR-RES
// RUN: %target-build-swift -module-name=File -package-name Pkg -I%t -emit-ir %s -enable-library-evolution -Xfrontend -experimental-allow-non-resilient-access -Xfrontend -experimental-package-cmo | %FileCheck %s --check-prefix=CHECK-IR-RES
public struct S {
public static var x = "hello world"
}
// CHECK-IR-NONRES: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @"$s4File1SV1xSSvau"()
// CHECK-IR-RES: define hidden swiftcc ptr @"$s4File1SV1xSSvau"()

View File

@@ -20,13 +20,12 @@
/// Test 1: They should be deserialized into Client as Lib and Client are in the same package.
// RUN: %FileCheck -check-prefix=CHECK-INPKG %s < %t/InPkgClient.sil
// Pub.init(_:) is removed after getting lined below.
// CHECK-INPKG-NOT: @$s3Lib3PubCyACSicfc
// Pub.__allocating_init(_:)
// CHECK-INPKG: sil public_external @$s3Lib3PubCyACSicfC : $@convention(method) (Int, @thick Pub.Type) -> @owned Pub {
// Pub.init(_:) is inlined in this block, as its body was deserialized.
// CHECK-INPKG: ref_element_addr {{.*}} : $Pub, #Pub.pubVar
// CHECK-INPKG: function_ref @$s3Lib3PubCyACSicfc
// Pub.init(_:)
// CHECK-INPKG: sil @$s3Lib3PubCyACSicfc : $@convention(method) (Int, @owned Pub) -> @owned Pub
// CHECK-INPKG: sil_vtable Pub {
// CHECK-INPKG: #Pub.pubVar!getter: (Pub) -> () -> Int : @$s3Lib3PubC6pubVarSivg // Pub.pubVar.getter
@@ -72,11 +71,6 @@
// CHECK-LIB: sil [serialized] [exact_self_class] [canonical] @$s3Lib3PubCyACSicfC : $@convention(method) (Int, @thick Pub.Type) -> @owned Pub {
// CHECK-LIB: function_ref @$s3Lib3PubCyACSicfc : $@convention(method) (Int, @owned Pub) -> @owned Pub
// Pub.init(_:)
// CHECK-LIB: sil [serialized_for_package] [canonical] @$s3Lib3PubCyACSicfc : $@convention(method) (Int, @owned Pub) -> @owned Pub {
// CHECK-LIB: ref_element_addr {{.*}} : $Pub, #Pub.pubVar
// Pub.__allocating_init(_:)
// Pub.pkgVar.getter
// CHECK-LIB: sil package [serialized_for_package] [canonical] @$s3Lib3PubC6pkgVarSivg : $@convention(method) (@guaranteed Pub) -> Int {
@@ -106,21 +100,35 @@ public protocol PubProto {
public class Pub: PubProto {
public var pubVar: Int = 1
package var pkgVar: Int = 2
var internalVar: Int = 3
public init(_ arg: Int) {
pubVar = arg
pkgVar = arg
}
public func pubFunc(_ arg: Pub) {
print(arg.pubVar)
}
}
public class SubPub: Pub {
override public func pubFunc(_ arg: Pub) {
print(arg.pubVar, arg.internalVar)
}
}
//--- Client.swift
import Lib
public func test(_ arg: Int) -> Int {
public func test1(_ arg: Int) -> Int {
let x = Pub(arg)
x.pubVar = 3
return x.run()
}
public func test2(_ arg: Int) {
SubPub(arg).pubFunc(Pub(arg))
}
public extension PubProto {
func run() -> Int {
return pubVar

View File

@@ -0,0 +1,53 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s \
// RUN: -emit-sil -module-name=Lib -package-name Pkg \
// RUN: -package-cmo -allow-non-resilient-access \
// RUN: -O -wmo -enable-library-evolution \
// RUN: -Xllvm -sil-print-function=s3Lib3fooyS2iF 2>&1 | %FileCheck %s
/// TEST that accessing PkgStruct in the following functions gets inlined after perf inlining pass.
public func bar(_ arg: Int) -> Int {
let p = PkgStruct(1, 2)
return arg > 0 ? p.field1 : p.field2
}
package func foo(_ arg: Int) -> Int {
let p = PkgStruct(1, 2)
return arg > 0 ? p.field1 : p.field2
}
package struct PkgStruct {
package let field1: Int
package let field2: Int
package init(_ arg1: Int, _ arg2: Int) {
field1 = arg1
field2 = arg2
}
}
/// BEFORE perf inlining pass.
// CHECK: sil package @$s3Lib3fooyS2iF : $@convention(thin) (Int) -> Int {
// CHECK: [[PKG_STACK:%.*]] = alloc_stack $PkgStruct
// CHECK: [[FUNC_REF:%.*]] = function_ref @$s3Lib9PkgStructVyACSi_SitcfC : $@convention(method) (Int, Int, @thin PkgStruct.Type) -> @out PkgStruct
// CHECK: apply [[FUNC_REF]]
// CHECK: [[F1:%.*]] = struct_element_addr [[PKG_STACK]] : $*PkgStruct, #PkgStruct.field1
// CHECK: load [[F1]] : $*Int
// CHECK: [[F2:%.*]] = struct_element_addr [[PKG_STACK]] : $*PkgStruct, #PkgStruct.field2
// CHECK: load [[F2]] : $*Int
/// AFTER perf inlining pass; body of `@$s3Lib9PkgStructVyACSi_SitcfC` gets inlined.
// CHECK: *** SIL function after {{.*}} EarlyPerfInliner (early-inline)
// CHECK: sil package @$s3Lib3fooyS2iF : $@convention(thin) (Int) -> Int {
// CHECK: [[PKG_ALLOC:%.*]] = alloc_stack $PkgStruct
// CHECK: [[PKG_INIT:%.*]] = alloc_stack [var_decl] $PkgStruct, var, name "self"
// CHECK: [[FIELD1_IVAR:%.*]] = struct_element_addr [[PKG_INIT]] : $*PkgStruct, #PkgStruct.field1
// CHECK: store {{.*}} to [[FIELD1_IVAR]] : $*Int
// CHECK: [[FIELD2_IVAR:%.*]] = struct_element_addr [[PKG_INIT]] : $*PkgStruct, #PkgStruct.field2
// CHECK: store {{.*}} to [[FIELD2_IVAR]] : $*Int
// CHECK: [[PKG_STR:%.*]] = struct $PkgStruct
// CHECK: store [[PKG_STR]] to [[PKG_ALLOC]] : $*PkgStruct
// CHECK: [[FIELD1:%.*]] = struct_element_addr [[PKG_ALLOC]] : $*PkgStruct, #PkgStruct.field1
// CHECK: load [[FIELD1]] : $*Int
// CHECK: [[FIELD2:%.*]] = struct_element_addr [[PKG_ALLOC]] : $*PkgStruct, #PkgStruct.field2
// CHECK: load [[FIELD2]] : $*Int

View File

@@ -29,10 +29,15 @@ import Lib
/// There should be no linker error on a public function
/// that contains symbols internal to Lib module.
///
// CHECK-MAIN-NOT: s3Lib14createPubClassySixlF
// CHECK-MAIN-NOT: s3Lib19usePubStructKeypathySixlF
// CHECK-MAIN: function_ref @$s3Lib11useInternalySiAA4BaseCF : $@convention(thin) (@guaranteed Base) -> Int
let x = useInternal(Base())
/// Since Base is not serialized, accessing its field should go
/// Since Base is not serialized, accessing its field should go
/// through `class_method`.
// CHECK-MAIN: class_method {{.*}} : $Base, #Base.baseVarPkg!getter : (Base) -> () -> Int, $@convention(method) (@guaranteed Base) -> Int
let y = usePkg(Base())
@@ -51,7 +56,55 @@ let w = usePubWithInternalField(PubKlassWithInternalMember(1))
// CHECK-MAIN: sil @$s3Lib11useInternalySiAA4BaseCF : $@convention(thin) (@guaranteed Base) -> Int
// PubKlassWithInternalMember.__allocating_init(_:)
// CHECK-MAIN: sil public_external @$s3Lib26PubKlassWithInternalMemberCyACSicfC : $@convention(method) (Int, @thick PubKlassWithInternalMember.Type) -> @owned PubKlassWithInternalMember {
// CHECK-MAIN-DAG: sil public_external @$s3Lib26PubKlassWithInternalMemberCyACSicfC : $@convention(method) (Int, @thick PubKlassWithInternalMember.Type) -> @owned PubKlassWithInternalMember {
func checkNested() {
// PubContainer initializer is inlined.
// CHECK-MAIN: struct $PubContainer ()
let c = PubContainer()
// CHECK-MAIN: function_ref @$s3Lib12PubContainerV9pubMemberyxxlF
print(c.pubMember(27))
}
func checkClasses() {
/// Inlined
print(createPubClass(0))
/// Not inlined as functions below contain private/internal symbols
// CHECK-MAIN: function_ref @$s3Lib20createPubClass_neverySixlF
print(createPubClass_never(0))
// CHECK-MAIN: function_ref @$s3Lib14createPrvClassySixlF
print(createPrvClass(0))
// CHECK-MAIN: function_ref @$s3Lib20createPrvClass_neverySixlF
print(createPrvClass_never(0))
}
func checkKeyPaths() {
/// Inlined
// CHECK-MAIN: function_ref @$s3Lib19getPubStructKeypathys7KeyPathCyAA0cD0VSiGxlF
print(usePubStructKeypath(0))
/// Not inlined as functions below contain private/internal symbols
// CHECK-MAIN: function_ref @$s3Lib24useInternalStructKeypathySixlF
print(useInternalStructKeypath(0))
// CHECK-MAIN: function_ref @$s3Lib15useClassKeypathySixlF
print(useClassKeypath(0))
}
checkNested()
checkClasses()
checkKeyPaths()
// CHECK-MAIN-DAG: sil public_external [_semantics "optimize.sil.specialize.generic.never"] @$s3Lib20createPubClass_neverySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
// CHECK-MAIN-DAG: sil @$s3Lib14createPrvClassySixlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Int
// CHECK-MAIN-DAG: sil [_semantics "optimize.sil.specialize.generic.never"] @$s3Lib20createPrvClass_neverySixlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Int
// CHECK-MAIN-DAG: sil @$s3Lib12PubContainerV9pubMemberyxxlF : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @in_guaranteed PubContainer) -> @out τ_0_0
// CHECK-MAIN-DAG: sil @$s3Lib24useInternalStructKeypathySixlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Int
// CHECK-MAIN-DAG: sil @$s3Lib15useClassKeypathySixlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Int
//--- Lib.swift
@@ -140,6 +193,139 @@ public class PubKlassWithInternalMember {
}
}
// createPubClass<A>(_:)
// CHECK-DAG: sil [serialized_for_package] [canonical] @$s3Lib14createPubClassySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
public func createPubClass<T>(_ t: T) -> Int {
return getPubClass(t).foo()
}
// CHECK-DAG: sil [serialized_for_package] [_semantics "optimize.sil.specialize.generic.never"] [canonical] @$s3Lib20createPubClass_neverySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
@_semantics("optimize.sil.specialize.generic.never")
public func createPubClass_never<T>(_ t: T) -> Int {
return getPubClass(t).foo()
}
// CHECK-DAG: sil [serialized_for_package] [canonical] @$s3Lib11getPubClassyAA13PublicDerivedCyxGxlF : $@convention(thin) <T> (@in_guaranteed T) -> @owned PublicDerived<T> {
public func getPubClass<T>(_ t : T) -> PublicDerived<T> {
return PublicDerived<T>(t)
}
// Not serialized
public func createPrvClass<T>(_ t: T) -> Int {
return getPrvClass(t).foo()
}
// Not serialized
@_semantics("optimize.sil.specialize.generic.never")
public func createPrvClass_never<T>(_ t: T) -> Int {
return getPrvClass(t).foo()
}
// Not serialized
private func getPrvClass<T>(_ t : T) -> PrivateBase<T> {
return PrivateDerived<T>(t)
}
public class PublicBase<T> {
public var t: T
public func foo() -> Int { return 27 }
public init(_ t: T) { self.t = t }
}
public class PublicDerived<T> : PublicBase<T> {
override public func foo() -> Int { return 28 }
}
private class PrivateBase<T> {
var t: T
func foo() -> Int { return 27 }
init(_ t: T) { self.t = t }
}
private class PrivateDerived<T> : PrivateBase<T> {
override func foo() -> Int { return 28 }
}
public struct PubContainer {
private final class PrvBase {}
public init() {}
// Not serialized; contains exported func
// but references a private class.
public func pubMember<T>(_ t: T) -> T {
var arr = Array<PrvBase>()
arr.append(PrvBase())
print(arr)
exportedFunc(arr)
return t
}
}
@_specialize(exported: true, where T == Int)
@inlinable
public func exportedFunc<T>(_ t: T) {
print(t)
}
public func pubFunc<T>(_ t: T) -> Int {
return getPubClass(t).foo()
}
@_semantics("optimize.sil.specialize.generic.never")
public func pubFuncNoSpecialize<T>(_ t: T) -> Int {
return getPubClass(t).foo()
}
struct MyInternalStruct {
var x: Int { return 27 }
var y: Int { return 28 }
}
public struct PubStruct {
public var x: Int { return 27 }
public var y: Int { return 28 }
}
class Myclass {
var x: Int { return 27 }
var y: Int { return 28 }
}
class Derived : Myclass {
override var x: Int { return 29 }
override var y: Int { return 30 }
}
func getInternalStructKeypath<T>(_ t: T) -> KeyPath<MyInternalStruct, Int> {
return \MyInternalStruct.x
}
// CHECK-DAG: sil [canonical] @$s3Lib19getPubStructKeypathys7KeyPathCyAA0cD0VSiGxlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned KeyPath<PubStruct, Int>
public func getPubStructKeypath<T>(_ t: T) -> KeyPath<PubStruct, Int> {
return \PubStruct.x
}
public func useInternalStructKeypath<T>(_ t: T) -> Int {
let s = MyInternalStruct()
return s[keyPath: getInternalStructKeypath(t)]
}
// CHECK-DAG: sil [serialized_for_package] [canonical] @$s3Lib19usePubStructKeypathySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
public func usePubStructKeypath<T>(_ t: T) -> Int {
let p = PubStruct()
return p[keyPath: getPubStructKeypath(t)]
}
func getClassKeypath<T>(_ t: T) -> KeyPath<Myclass, Int> {
return \Myclass.x
}
public func useClassKeypath<T>(_ t: T) -> Int {
let c = Derived()
return c[keyPath: getClassKeypath(t)]
}
/// PubKlass doesn't contain internal symbols so its vtable is serialized.
// CHECK-LABEL: sil_vtable [serialized_for_package] PubKlass {
// CHECK-NEXT: #PubKlass.init!allocator: (PubKlass.Type) -> () -> PubKlass : @$s3Lib8PubKlassCACycfC

View File

@@ -1,206 +0,0 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// RUN: %target-build-swift %t/Lib.swift \
// RUN: -module-name=Lib -package-name Pkg \
// RUN: -parse-as-library -emit-module -emit-module-path %t/Lib.swiftmodule -I%t \
// RUN: -Xfrontend -experimental-package-cmo -Xfrontend -experimental-allow-non-resilient-access \
// RUN: -O -wmo -enable-library-evolution
// RUN: %target-sil-opt %t/Lib.swiftmodule -sil-verify-all -o %t/Lib.sil
// RUN: %target-build-swift -module-name=Main -package-name Pkg -I%t -emit-sil -O -wmo -Xllvm -sil-disable-pass=FunctionSignatureOpts %t/main.swift -o %t/Main.sil
// RUN: %FileCheck %s --check-prefixes=CHECK < %t/Lib.sil
// RUN: %FileCheck %s --check-prefixes=CHECK-MAIN < %t/Main.sil
//--- main.swift
import Lib
// CHECK-MAIN-NOT: s3Lib14createPubClassySixlF
// CHECK-MAIN-NOT: s3Lib19usePubStructKeypathySixlF
func checkClasses() {
/// Inlined
print(createPubClass(0))
/// Not inlined as functions below contain private/internal symbols
// CHECK-MAIN-DAG: function_ref @$s3Lib20createPubClass_neverySixlF
// CHECK-MAIN-DAG: sil public_external [_semantics "optimize.sil.specialize.generic.never"] @$s3Lib20createPubClass_neverySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
print(createPubClass_never(0))
// CHECK-MAIN-DAG: function_ref @$s3Lib14createPrvClassySixlF
// CHECK-MAIN-DAG: sil @$s3Lib14createPrvClassySixlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Int
print(createPrvClass(0))
// CHECK-MAIN-DAG: function_ref @$s3Lib20createPrvClass_neverySixlF
// CHECK-MAIN-DAG: sil [_semantics "optimize.sil.specialize.generic.never"] @$s3Lib20createPrvClass_neverySixlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Int
print(createPrvClass_never(0))
}
func checkNested() {
// PubContainer initializer is inlined.
// CHECK-MAIN-DAG: struct $PubContainer ()
let c = PubContainer()
// CHECK-MAIN-DAG: function_ref @$s3Lib12PubContainerV9pubMemberyxxlF
// CHECK-MAIN-DAG: sil @$s3Lib12PubContainerV9pubMemberyxxlF : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @in_guaranteed PubContainer) -> @out τ_0_0
print(c.pubMember(27))
}
func checkKeyPaths() {
/// Inlined
// CHECK-MAIN-DAG: function_ref @$s3Lib19getPubStructKeypathys7KeyPathCyAA0cD0VSiGxlF
print(usePubStructKeypath(0))
/// Not inlined as functions below contain private/internal symbols
// CHECK-MAIN-DAG: function_ref @$s3Lib24useInternalStructKeypathySixlF
// CHECK-MAIN-DAG: sil @$s3Lib24useInternalStructKeypathySixlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Int
print(useInternalStructKeypath(0))
// CHECK-MAIN-DAG: function_ref @$s3Lib15useClassKeypathySixlF
// CHECK-MAIN-DAG: sil @$s3Lib15useClassKeypathySixlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Int
print(useClassKeypath(0))
}
checkNested()
checkClasses()
checkKeyPaths()
//--- Lib.swift
// createPubClass<A>(_:)
// CHECK-DAG: sil [serialized_for_package] [canonical] @$s3Lib14createPubClassySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
public func createPubClass<T>(_ t: T) -> Int {
return getPubClass(t).foo()
}
// CHECK-DAG: sil [serialized_for_package] [_semantics "optimize.sil.specialize.generic.never"] [canonical] @$s3Lib20createPubClass_neverySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
@_semantics("optimize.sil.specialize.generic.never")
public func createPubClass_never<T>(_ t: T) -> Int {
return getPubClass(t).foo()
}
// CHECK-DAG: sil [serialized_for_package] [canonical] @$s3Lib11getPubClassyAA13PublicDerivedCyxGxlF : $@convention(thin) <T> (@in_guaranteed T) -> @owned PublicDerived<T> {
public func getPubClass<T>(_ t : T) -> PublicDerived<T> {
return PublicDerived<T>(t)
}
// Not serialized
public func createPrvClass<T>(_ t: T) -> Int {
return getPrvClass(t).foo()
}
// Not serialized
@_semantics("optimize.sil.specialize.generic.never")
public func createPrvClass_never<T>(_ t: T) -> Int {
return getPrvClass(t).foo()
}
// Not serialized
private func getPrvClass<T>(_ t : T) -> PrivateBase<T> {
return PrivateDerived<T>(t)
}
public class PublicBase<T> {
public var t: T
public func foo() -> Int { return 27 }
public init(_ t: T) { self.t = t }
}
public class PublicDerived<T> : PublicBase<T> {
override public func foo() -> Int { return 28 }
}
private class PrivateBase<T> {
var t: T
func foo() -> Int { return 27 }
init(_ t: T) { self.t = t }
}
private class PrivateDerived<T> : PrivateBase<T> {
override func foo() -> Int { return 28 }
}
public struct PubContainer {
private final class PrvBase {}
public init() {}
// Not serialized; contains exported func
// but references a private class.
public func pubMember<T>(_ t: T) -> T {
var arr = Array<PrvBase>()
arr.append(PrvBase())
print(arr)
exportedFunc(arr)
return t
}
}
@_specialize(exported: true, where T == Int)
@inlinable
public func exportedFunc<T>(_ t: T) {
print(t)
}
public func pubFunc<T>(_ t: T) -> Int {
return getPubClass(t).foo()
}
@_semantics("optimize.sil.specialize.generic.never")
public func pubFuncNoSpecialize<T>(_ t: T) -> Int {
return getPubClass(t).foo()
}
struct InternalStruct {
var x: Int { return 27 }
var y: Int { return 28 }
}
public struct PubStruct {
public var x: Int { return 27 }
public var y: Int { return 28 }
}
class Myclass {
var x: Int { return 27 }
var y: Int { return 28 }
}
class Derived : Myclass {
override var x: Int { return 29 }
override var y: Int { return 30 }
}
func getInternalStructKeypath<T>(_ t: T) -> KeyPath<InternalStruct, Int> {
return \InternalStruct.x
}
// CHECK-DAG: sil [canonical] @$s3Lib19getPubStructKeypathys7KeyPathCyAA0cD0VSiGxlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned KeyPath<PubStruct, Int>
public func getPubStructKeypath<T>(_ t: T) -> KeyPath<PubStruct, Int> {
return \PubStruct.x
}
public func useInternalStructKeypath<T>(_ t: T) -> Int {
let s = InternalStruct()
return s[keyPath: getInternalStructKeypath(t)]
}
// CHECK-DAG: sil [serialized_for_package] [canonical] @$s3Lib19usePubStructKeypathySixlF : $@convention(thin) <T> (@in_guaranteed T) -> Int {
public func usePubStructKeypath<T>(_ t: T) -> Int {
let p = PubStruct()
return p[keyPath: getPubStructKeypath(t)]
}
func getClassKeypath<T>(_ t: T) -> KeyPath<Myclass, Int> {
return \Myclass.x
}
public func useClassKeypath<T>(_ t: T) -> Int {
let c = Derived()
return c[keyPath: getClassKeypath(t)]
}