diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 361bd1cddbaf7..c8d7c58f00372 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -576,6 +576,9 @@ ERROR(no_allocations_without_embedded,none, ERROR(no_swift_sources_with_embedded,none, "embedded swift cannot be enabled in a compiler built without Swift sources", ()) +ERROR(package_cmo_requires_library_evolution, none, + "Library evolution must be enabled for Package CMO", ()) + ERROR(experimental_not_supported_in_production,none, "experimental feature '%0' cannot be enabled in production compiler", (StringRef)) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 6ad91ddd8e7f1..e2f3db7401207 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2688,6 +2688,8 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args, Diags.diagnose(SourceLoc(), diag::ignoring_option_requires_option, "-package-cmo", "-allow-non-resilient-access"); + } else if (!FEOpts.EnableLibraryEvolution) { + Diags.diagnose(SourceLoc(), diag::package_cmo_requires_library_evolution); } else { Opts.EnableSerializePackage = true; Opts.CMOMode = CrossModuleOptimizationMode::Default; diff --git a/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp b/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp index ae320df503772..d825009ef293b 100644 --- a/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp +++ b/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp @@ -947,9 +947,15 @@ void CrossModuleOptimization::makeSubstUsableFromInline( class CrossModuleOptimizationPass: public SILModuleTransform { void run() override { auto &M = *getModule(); - if (M.getSwiftModule()->isResilient() && - !M.getSwiftModule()->serializePackageEnabled()) + if (M.getSwiftModule()->serializePackageEnabled()) { + assert(M.getSwiftModule()->isResilient() && + "Package CMO requires library-evolution"); + } else if (M.getSwiftModule()->isResilient()) { + // If no Package CMO flags are passed and library + // evolution is enabled, just return. return; + } + if (!M.isWholeModule()) return; @@ -974,6 +980,9 @@ class CrossModuleOptimizationPass: public SILModuleTransform { return; } + if (isPackageCMOEnabled(M.getSwiftModule())) + assert(conservative && "Package CMO requires conservative CMO mode"); + CrossModuleOptimization CMO(M, conservative, everything); CMO.serializeFunctionsInModule(PM); diff --git a/test/SILOptimizer/package-cmo-non-resilient-mode.swift b/test/SILOptimizer/cmo-with-package-decls.swift similarity index 90% rename from test/SILOptimizer/package-cmo-non-resilient-mode.swift rename to test/SILOptimizer/cmo-with-package-decls.swift index d55cc354ef9bf..259025678ee67 100644 --- a/test/SILOptimizer/package-cmo-non-resilient-mode.swift +++ b/test/SILOptimizer/cmo-with-package-decls.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift -O -wmo -Xfrontend -experimental-package-cmo -Xfrontend -experimental-allow-non-resilient-access -parse-as-library -emit-module -emit-module-path=%t/Submodule.swiftmodule -module-name=Submodule -package-name Pkg %S/Inputs/cross-module/default-submodule.swift -c -o %t/submodule.o -// RUN: %target-build-swift -O -wmo -Xfrontend -experimental-package-cmo -Xfrontend -experimental-allow-non-resilient-access -parse-as-library -emit-module -emit-module-path=%t/Module.swiftmodule -module-name=Module -package-name Pkg -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/module.o -// RUN: %target-build-swift -O -wmo -Xfrontend -experimental-package-cmo -Xfrontend -experimental-allow-non-resilient-access -parse-as-library -emit-tbd -emit-tbd-path %t/ModuleTBD.tbd -emit-module -emit-module-path=%t/ModuleTBD.swiftmodule -module-name=ModuleTBD -package-name Pkg -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/moduletbd.o -Xfrontend -tbd-install_name -Xfrontend module +// RUN: %target-build-swift -O -wmo -Xfrontend -enable-default-cmo -parse-as-library -emit-module -emit-module-path=%t/Submodule.swiftmodule -module-name=Submodule -package-name Pkg %S/Inputs/cross-module/default-submodule.swift -c -o %t/submodule.o +// RUN: %target-build-swift -O -wmo -Xfrontend -enable-default-cmo -parse-as-library -emit-module -emit-module-path=%t/Module.swiftmodule -module-name=Module -package-name Pkg -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/module.o +// RUN: %target-build-swift -O -wmo -Xfrontend -enable-default-cmo -parse-as-library -emit-tbd -emit-tbd-path %t/ModuleTBD.tbd -emit-module -emit-module-path=%t/ModuleTBD.swiftmodule -module-name=ModuleTBD -package-name Pkg -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/moduletbd.o -Xfrontend -tbd-install_name -Xfrontend module // RUN: %target-build-swift -O -wmo -module-name=Main -package-name Pkg -I%t -I%S/Inputs/cross-module %s -emit-sil -o %t/Main.sil // RUN: %FileCheck %s < %t/Main.sil diff --git a/test/SILOptimizer/package-cmo-require-library-evolution.swift b/test/SILOptimizer/package-cmo-require-library-evolution.swift new file mode 100644 index 0000000000000..a9b1ae8a61e60 --- /dev/null +++ b/test/SILOptimizer/package-cmo-require-library-evolution.swift @@ -0,0 +1,33 @@ +// RUN: %empty-directory(%t) + +// RUN: not %target-build-swift %s \ +// RUN: -module-name=Lib -package-name Pkg \ +// RUN: -emit-module -o %t/Lib.swiftmodule -I%t \ +// RUN: -Xfrontend -package-cmo \ +// RUN: -Xfrontend -allow-non-resilient-access \ +// RUN: -O -wmo 2>&1 | %FileCheck %s --check-prefix CHECK-DIAGS +// CHECK-DIAGS: error: Library evolution must be enabled for Package CMO + +// RUN: %target-build-swift %s \ +// RUN: -module-name=Lib -package-name Pkg \ +// RUN: -emit-module -o %t/Lib.swiftmodule -I%t \ +// RUN: -Xfrontend -package-cmo \ +// RUN: -Xfrontend -allow-non-resilient-access \ +// RUN: -enable-library-evolution \ +// RUN: -O -wmo + +// RUN: llvm-bcanalyzer %t/Lib.swiftmodule | %FileCheck %s -check-prefix=CHECK-BC +// CHECK-BC: SERIALIZE_PACKAGE_ENABLED + +// REQUIRES: swift_in_compiler + +public struct S { + public init() {} + package var x: Int { + get { return 0 } + set {} + } + package func f() -> Int { + return 1 + } +} diff --git a/test/SILOptimizer/package-cmo-resilient-mode.swift b/test/SILOptimizer/package-cmo-resilient-mode.swift index bd0dfd9acaba4..808429e6d2124 100644 --- a/test/SILOptimizer/package-cmo-resilient-mode.swift +++ b/test/SILOptimizer/package-cmo-resilient-mode.swift @@ -1,6 +1,7 @@ // RUN: %empty-directory(%t) // RUN: split-file %s %t +/// Enable Package CMO; conservative mode on resilient module. // 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 \ @@ -18,10 +19,12 @@ // RUN: rm -rf %t/Lib.swiftmodule +/// Enable non-package CMO; conservative mode on non-resilient module, +/// and compare results with Package CMO. // 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: -Xfrontend -enable-default-cmo \ // RUN: -O -wmo // RUN: %target-sil-opt %t/Lib.swiftmodule -sil-verify-all -o %t/Lib-non-res.sil