mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #79035 from swiftlang/elsh/pcmo-imports
Package CMO: Enable serializing decls imported with `@_spiOnly` or `package import`.
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
#define DEBUG_TYPE "cross-module-serialization-setup"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ImportCache.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
#include "swift/IRGen/TBDGen.h"
|
||||
#include "swift/SIL/ApplySite.h"
|
||||
@@ -103,6 +104,11 @@ private:
|
||||
bool canSerializeType(CanType type);
|
||||
bool canSerializeDecl(NominalTypeDecl *decl);
|
||||
|
||||
/// Check whether decls imported with certain access levels or attributes
|
||||
/// can be serialized.
|
||||
/// The \p ctxt can e.g. be a NominalType or the context of a function.
|
||||
bool checkImports(DeclContext *ctxt) const;
|
||||
|
||||
bool canUseFromInline(DeclContext *declCtxt);
|
||||
|
||||
bool canUseFromInline(SILFunction *func);
|
||||
@@ -745,7 +751,12 @@ static bool couldBeLinkedStatically(DeclContext *funcCtxt, SILModule &module) {
|
||||
// The stdlib module is always linked dynamically.
|
||||
if (funcModule == module.getASTContext().getStdlibModule())
|
||||
return false;
|
||||
|
||||
|
||||
// An sdk or system module should be linked dynamically.
|
||||
if (isPackageCMOEnabled(module.getSwiftModule()) &&
|
||||
funcModule->isNonUserModule())
|
||||
return false;
|
||||
|
||||
// Conservatively assume the function is in a statically linked module.
|
||||
return true;
|
||||
}
|
||||
@@ -755,7 +766,7 @@ bool CrossModuleOptimization::canUseFromInline(DeclContext *declCtxt) {
|
||||
if (everything)
|
||||
return true;
|
||||
|
||||
if (!M.getSwiftModule()->canBeUsedForCrossModuleOptimization(declCtxt))
|
||||
if (!checkImports(declCtxt))
|
||||
return false;
|
||||
|
||||
/// If we are emitting a TBD file, the TBD file only contains public symbols
|
||||
@@ -771,6 +782,52 @@ bool CrossModuleOptimization::canUseFromInline(DeclContext *declCtxt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CrossModuleOptimization::checkImports(DeclContext *ctxt) const {
|
||||
ModuleDecl *moduleOfCtxt = ctxt->getParentModule();
|
||||
|
||||
// If the context defined in the same module - or is the same module, it's
|
||||
// fine.
|
||||
if (moduleOfCtxt == M.getSwiftModule())
|
||||
return true;
|
||||
|
||||
ModuleDecl::ImportFilter filter;
|
||||
|
||||
if (isPackageCMOEnabled(M.getSwiftModule())) {
|
||||
// If Package CMO is enabled, decls imported with `package import`
|
||||
// or `@_spiOnly import` into this module should be allowed to be
|
||||
// serialized. They are used in decls with `package` or higher
|
||||
// access level, with or without @_spi; a client of this module
|
||||
// should be able to access them directly if in the same package.
|
||||
filter = { ModuleDecl::ImportFilterKind::ImplementationOnly };
|
||||
} else {
|
||||
// See if context is imported in a "regular" way, i.e. not with
|
||||
// @_implementationOnly, `package import` or @_spiOnly.
|
||||
filter = {
|
||||
ModuleDecl::ImportFilterKind::ImplementationOnly,
|
||||
ModuleDecl::ImportFilterKind::PackageOnly,
|
||||
ModuleDecl::ImportFilterKind::SPIOnly
|
||||
};
|
||||
}
|
||||
SmallVector<ImportedModule, 4> results;
|
||||
M.getSwiftModule()->getImportedModules(results, filter);
|
||||
|
||||
auto &imports = M.getSwiftModule()->getASTContext().getImportCache();
|
||||
for (auto &desc : results) {
|
||||
if (imports.isImportedBy(moduleOfCtxt, desc.importedModule)) {
|
||||
// E.g. `@_implementationOnly import QuartzCore_Private.CALayerPrivate`
|
||||
// imports `Foundation` as its transitive dependency module; use of a
|
||||
// a `public` decl in `Foundation` such as `IndexSet` in a function
|
||||
// signature should not block serialization in Package CMO given the
|
||||
// function has `package` or higher access level.
|
||||
if (isPackageCMOEnabled(M.getSwiftModule()) &&
|
||||
moduleOfCtxt->isNonUserModule())
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Returns true if the function \p func can be used from a serialized function.
|
||||
bool CrossModuleOptimization::canUseFromInline(SILFunction *function) {
|
||||
if (everything)
|
||||
|
||||
Reference in New Issue
Block a user