Skip to content

ModuleInterface: refactor ModuleInterfaceChecker out of ModuleInterfaceLoader #34121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,12 @@ class ASTContext final {
bool isClang = false, bool isDWARF = false,
bool IsInterface = false);

/// Add a module interface checker to use for this AST context.
void addModuleInterfaceChecker(std::unique_ptr<ModuleInterfaceChecker> checker);

/// Retrieve the module interface checker associated with this AST context.
ModuleInterfaceChecker *getModuleInterfaceChecker() const;

/// Retrieve the module dependencies for the module with the given name.
///
/// \param isUnderlyingClangModule When true, only look for a Clang module
Expand Down Expand Up @@ -839,9 +845,6 @@ class ASTContext final {
/// If there is no Clang module loader, returns a null pointer.
/// The loader is owned by the AST context.
ClangModuleLoader *getDWARFModuleLoader() const;

/// Retrieve the module interface loader for this ASTContext.
ModuleLoader *getModuleInterfaceLoader() const;
public:
namelookup::ImportCache &getImportCache() const;

Expand Down
17 changes: 17 additions & 0 deletions include/swift/AST/ModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,23 @@ struct SubCompilerInstanceInfo {
ArrayRef<StringRef> ExtraPCMArgs;
};

/// Abstract interface for a checker of module interfaces and prebuilt modules.
class ModuleInterfaceChecker {
public:
virtual std::vector<std::string>
getCompiledModuleCandidatesForInterface(StringRef moduleName,
StringRef interfacePath) = 0;

/// Given a list of potential ready-to-use compiled modules for \p interfacePath,
/// check if any one of them is up-to-date. If so, emit a forwarding module
/// to the candidate binary module to \p outPath.
virtual bool tryEmitForwardingModule(StringRef moduleName,
StringRef interfacePath,
ArrayRef<std::string> candidates,
StringRef outPath) = 0;
virtual ~ModuleInterfaceChecker() = default;
};

/// Abstract interface to run an action in a sub ASTContext.
struct InterfaceSubContextDelegate {
virtual std::error_code runInSubContext(StringRef moduleName,
Expand Down
68 changes: 39 additions & 29 deletions include/swift/Frontend/ModuleInterfaceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,27 +309,52 @@ struct ModuleInterfaceLoaderOptions {
ModuleInterfaceLoaderOptions() = default;
};

class ModuleInterfaceCheckerImpl: public ModuleInterfaceChecker {
friend class ModuleInterfaceLoader;
ASTContext &Ctx;
std::string CacheDir;
std::string PrebuiltCacheDir;
ModuleInterfaceLoaderOptions Opts;

public:
explicit ModuleInterfaceCheckerImpl(ASTContext &Ctx,
StringRef cacheDir,
StringRef prebuiltCacheDir,
ModuleInterfaceLoaderOptions Opts)
: Ctx(Ctx), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir),
Opts(Opts) {}

std::vector<std::string>
getCompiledModuleCandidatesForInterface(StringRef moduleName,
StringRef interfacePath) override;

/// Given a list of potential ready-to-use compiled modules for \p interfacePath,
/// check if any one of them is up-to-date. If so, emit a forwarding module
/// to the candidate binary module to \p outPath.
bool tryEmitForwardingModule(StringRef moduleName,
StringRef interfacePath,
ArrayRef<std::string> candidates,
StringRef outPath) override;
bool isCached(StringRef DepPath);
};

/// A ModuleLoader that runs a subordinate \c CompilerInvocation and
/// \c CompilerInstance to convert .swiftinterface files to .swiftmodule
/// files on the fly, caching the resulting .swiftmodules in the module cache
/// directory, and loading the serialized .swiftmodules from there.
class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
friend class unittest::ModuleInterfaceLoaderTest;
explicit ModuleInterfaceLoader(
ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir,
ASTContext &ctx, ModuleInterfaceCheckerImpl &InterfaceChecker,
DependencyTracker *tracker, ModuleLoadingMode loadMode,
ArrayRef<std::string> PreferInterfaceForModules,
bool IgnoreSwiftSourceInfoFile, ModuleInterfaceLoaderOptions Opts)
: SerializedModuleLoaderBase(ctx, tracker, loadMode,
IgnoreSwiftSourceInfoFile),
CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir),
PreferInterfaceForModules(PreferInterfaceForModules),
Opts(Opts) {}
bool IgnoreSwiftSourceInfoFile)
: SerializedModuleLoaderBase(ctx, tracker, loadMode, IgnoreSwiftSourceInfoFile),
InterfaceChecker(InterfaceChecker),
PreferInterfaceForModules(PreferInterfaceForModules){}

std::string CacheDir;
std::string PrebuiltCacheDir;
ModuleInterfaceCheckerImpl &InterfaceChecker;
ArrayRef<std::string> PreferInterfaceForModules;
ModuleInterfaceLoaderOptions Opts;

std::error_code findModuleFilesInDirectory(
ImportPath::Element ModuleID,
Expand All @@ -343,17 +368,14 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
bool isCached(StringRef DepPath) override;
public:
static std::unique_ptr<ModuleInterfaceLoader>
create(ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir,
create(ASTContext &ctx, ModuleInterfaceCheckerImpl &InterfaceChecker,
DependencyTracker *tracker, ModuleLoadingMode loadMode,
ArrayRef<std::string> PreferInterfaceForModules = {},
ModuleInterfaceLoaderOptions Opts = ModuleInterfaceLoaderOptions(),
bool IgnoreSwiftSourceInfoFile = false) {
return std::unique_ptr<ModuleInterfaceLoader>(
new ModuleInterfaceLoader(ctx, cacheDir, prebuiltCacheDir,
tracker, loadMode,
PreferInterfaceForModules,
IgnoreSwiftSourceInfoFile,
Opts));
new ModuleInterfaceLoader(ctx, InterfaceChecker, tracker, loadMode,
PreferInterfaceForModules,
IgnoreSwiftSourceInfoFile));
}

/// Append visible module names to \p names. Note that names are possibly
Expand All @@ -373,18 +395,6 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
StringRef ModuleName, StringRef InPath, StringRef OutPath,
bool SerializeDependencyHashes, bool TrackSystemDependencies,
ModuleInterfaceLoaderOptions Opts);

std::vector<std::string>
getCompiledModuleCandidatesForInterface(StringRef moduleName,
StringRef interfacePath) override;

/// Given a list of potential ready-to-use compiled modules for \p interfacePath,
/// check if any one of them is up-to-date. If so, emit a forwarding module
/// to the candidate binary module to \p outPath.
bool tryEmitForwardingModule(StringRef moduleName,
StringRef interfacePath,
ArrayRef<std::string> candidates,
StringRef outPath) override;
};

struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
Expand Down
12 changes: 0 additions & 12 deletions include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,18 +201,6 @@ class SerializedModuleLoaderBase : public ModuleLoader {
virtual Optional<ModuleDependencies> getModuleDependencies(
StringRef moduleName, ModuleDependenciesCache &cache,
InterfaceSubContextDelegate &delegate) override;

virtual std::vector<std::string>
getCompiledModuleCandidatesForInterface(StringRef moduleName,
StringRef interfacePath) {
return std::vector<std::string>();
}
virtual bool tryEmitForwardingModule(StringRef moduleName,
StringRef interfacePath,
ArrayRef<std::string> candidates,
StringRef outPath) {
return false;
}
};

/// Imports serialized Swift modules into an ASTContext.
Expand Down
20 changes: 13 additions & 7 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ struct ASTContext::Implementation {
/// The set of known protocols, lazily populated as needed.
ProtocolDecl *KnownProtocols[NumKnownProtocols] = { };

/// The module interface checker owned by the ASTContext.
std::unique_ptr<ModuleInterfaceChecker> InterfaceChecker;

/// The various module loaders that import external modules into this
/// ASTContext.
SmallVector<std::unique_ptr<swift::ModuleLoader>, 4> ModuleLoaders;
Expand All @@ -268,9 +271,6 @@ struct ASTContext::Implementation {
/// The module loader used to load Clang modules from DWARF.
ClangModuleLoader *TheDWARFModuleLoader = nullptr;

/// The module loader used to load Swift textual interface.
ModuleLoader *TheModuleInterfaceLoader = nullptr;

/// Map from Swift declarations to raw comments.
llvm::DenseMap<const Decl *, RawComment> RawComments;

Expand Down Expand Up @@ -1519,11 +1519,15 @@ void ASTContext::addModuleLoader(std::unique_ptr<ModuleLoader> loader,
if (IsClang && IsDwarf && !getImpl().TheDWARFModuleLoader)
getImpl().TheDWARFModuleLoader =
static_cast<ClangModuleLoader *>(loader.get());
if (IsInterface && !getImpl().TheModuleInterfaceLoader)
getImpl().TheModuleInterfaceLoader = loader.get();
getImpl().ModuleLoaders.push_back(std::move(loader));
}

void ASTContext::addModuleInterfaceChecker(
std::unique_ptr<ModuleInterfaceChecker> checker) {
assert(!getImpl().InterfaceChecker && "Checker has been set already");
getImpl().InterfaceChecker = std::move(checker);
}

Optional<ModuleDependencies> ASTContext::getModuleDependencies(
StringRef moduleName, bool isUnderlyingClangModule,
ModuleDependenciesCache &cache, InterfaceSubContextDelegate &delegate) {
Expand Down Expand Up @@ -1610,8 +1614,10 @@ ClangModuleLoader *ASTContext::getDWARFModuleLoader() const {
return getImpl().TheDWARFModuleLoader;
}

ModuleLoader *ASTContext::getModuleInterfaceLoader() const {
return getImpl().TheModuleInterfaceLoader;
ModuleInterfaceChecker *ASTContext::getModuleInterfaceChecker() const {
auto *result = getImpl().InterfaceChecker.get();
assert(result);
return result;
}

ModuleDecl *ASTContext::getLoadedModule(
Expand Down
34 changes: 17 additions & 17 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,14 @@ bool CompilerInstance::setUpModuleLoaders() {
return true;
}

// Configure ModuleInterfaceChecker for the ASTContext.
auto const &Clang = clangImporter->getClangInstance();
std::string ModuleCachePath = getModuleCachePathFromClang(Clang);
auto &FEOpts = Invocation.getFrontendOptions();
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
Context->addModuleInterfaceChecker(
std::make_unique<ModuleInterfaceCheckerImpl>(*Context, ModuleCachePath,
FEOpts.PrebuiltModuleCachePath, LoaderOpts));
// If implicit modules are disabled, we need to install an explicit module
// loader.
bool ExplicitModuleBuild = Invocation.getFrontendOptions().DisableImplicitModules;
Expand All @@ -505,23 +513,15 @@ bool CompilerInstance::setUpModuleLoaders() {
IgnoreSourceInfoFile);
this->DefaultSerializedLoader = ESML.get();
Context->addModuleLoader(std::move(ESML));
}

if (MLM != ModuleLoadingMode::OnlySerialized) {
auto const &Clang = clangImporter->getClangInstance();
std::string ModuleCachePath = getModuleCachePathFromClang(Clang);
auto &FEOpts = Invocation.getFrontendOptions();
StringRef PrebuiltModuleCachePath = FEOpts.PrebuiltModuleCachePath;
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
auto PIML = ModuleInterfaceLoader::create(
*Context, ModuleCachePath, PrebuiltModuleCachePath,
getDependencyTracker(), MLM, FEOpts.PreferInterfaceForModules,
LoaderOpts,
IgnoreSourceInfoFile);
Context->addModuleLoader(std::move(PIML), false, false, true);
}

if (!ExplicitModuleBuild) {
} else {
if (MLM != ModuleLoadingMode::OnlySerialized) {
// We only need ModuleInterfaceLoader for implicit modules.
auto PIML = ModuleInterfaceLoader::create(
*Context, *static_cast<ModuleInterfaceCheckerImpl*>(Context
->getModuleInterfaceChecker()), getDependencyTracker(), MLM,
FEOpts.PreferInterfaceForModules, IgnoreSourceInfoFile);
Context->addModuleLoader(std::move(PIML), false, false, true);
}
std::unique_ptr<ImplicitSerializedModuleLoader> ISML =
ImplicitSerializedModuleLoader::create(*Context, getDependencyTracker(), MLM,
IgnoreSourceInfoFile);
Expand Down
7 changes: 3 additions & 4 deletions lib/Frontend/ModuleInterfaceBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,9 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
auto &SubInstance = *info.Instance;
auto subInvocation = SubInstance.getInvocation();
// Try building forwarding module first. If succeed, return.
if (static_cast<ModuleInterfaceLoader*>(SubInstance.getASTContext()
.getModuleInterfaceLoader())->tryEmitForwardingModule(moduleName,
interfacePath,
CompiledCandidates, OutPath)) {
if (SubInstance.getASTContext().getModuleInterfaceChecker()
->tryEmitForwardingModule(moduleName, interfacePath,
CompiledCandidates, OutPath)) {
return std::error_code();
}
FrontendOptions &FEOpts = subInvocation.getFrontendOptions();
Expand Down
31 changes: 15 additions & 16 deletions lib/Frontend/ModuleInterfaceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ struct ModuleRebuildInfo {
/// a module that we'll build from a module interface.
class ModuleInterfaceLoaderImpl {
friend class swift::ModuleInterfaceLoader;
friend class swift::ModuleInterfaceCheckerImpl;
ASTContext &ctx;
llvm::vfs::FileSystem &fs;
DiagnosticEngine &diags;
Expand Down Expand Up @@ -907,10 +908,6 @@ class ModuleInterfaceLoaderImpl {

return std::move(module.moduleBuffer);
}
// If implicit module is disabled, we are done.
if (Opts.disableImplicitSwiftModule) {
return std::make_error_code(std::errc::not_supported);
}

std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;

Expand Down Expand Up @@ -942,12 +939,16 @@ class ModuleInterfaceLoaderImpl {

} // end anonymous namespace

bool ModuleInterfaceLoader::isCached(StringRef DepPath) {
bool ModuleInterfaceCheckerImpl::isCached(StringRef DepPath) {
if (!CacheDir.empty() && DepPath.startswith(CacheDir))
return true;
return !PrebuiltCacheDir.empty() && DepPath.startswith(PrebuiltCacheDir);
}

bool ModuleInterfaceLoader::isCached(StringRef DepPath) {
return InterfaceChecker.isCached(DepPath);
}

/// Load a .swiftmodule associated with a .swiftinterface either from a
/// cache or by converting it in a subordinate \c CompilerInstance, caching
/// the results.
Expand Down Expand Up @@ -990,8 +991,8 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
auto ModuleName = ModuleID.Item.str();
ModuleInterfaceLoaderImpl Impl(
Ctx, ModPath, InPath, ModuleName,
CacheDir, PrebuiltCacheDir, ModuleID.Loc,
Opts,
InterfaceChecker.CacheDir, InterfaceChecker.PrebuiltCacheDir,
ModuleID.Loc, InterfaceChecker.Opts,
dependencyTracker,
llvm::is_contained(PreferInterfaceForModules,
ModuleName) ?
Expand Down Expand Up @@ -1024,8 +1025,8 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
}

std::vector<std::string>
ModuleInterfaceLoader::getCompiledModuleCandidatesForInterface(StringRef moduleName,
StringRef interfacePath) {
ModuleInterfaceCheckerImpl::getCompiledModuleCandidatesForInterface(
StringRef moduleName, StringRef interfacePath) {
// Derive .swiftmodule path from the .swiftinterface path.
auto newExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
llvm::SmallString<32> modulePath = interfacePath;
Expand All @@ -1034,9 +1035,8 @@ ModuleInterfaceLoader::getCompiledModuleCandidatesForInterface(StringRef moduleN
Ctx, modulePath, interfacePath, moduleName,
CacheDir, PrebuiltCacheDir, SourceLoc(),
Opts,
dependencyTracker,
llvm::is_contained(PreferInterfaceForModules, moduleName) ?
ModuleLoadingMode::PreferInterface : LoadMode);
nullptr,
ModuleLoadingMode::PreferSerialized);
std::vector<std::string> results;
auto pair = Impl.getCompiledModuleCandidates();
// Add compiled module candidates only when they are non-empty.
Expand All @@ -1047,7 +1047,7 @@ ModuleInterfaceLoader::getCompiledModuleCandidatesForInterface(StringRef moduleN
return results;
}

bool ModuleInterfaceLoader::tryEmitForwardingModule(StringRef moduleName,
bool ModuleInterfaceCheckerImpl::tryEmitForwardingModule(StringRef moduleName,
StringRef interfacePath,
ArrayRef<std::string> candidates,
StringRef outputPath) {
Expand All @@ -1059,9 +1059,8 @@ bool ModuleInterfaceLoader::tryEmitForwardingModule(StringRef moduleName,
Ctx, modulePath, interfacePath, moduleName,
CacheDir, PrebuiltCacheDir, SourceLoc(),
Opts,
dependencyTracker,
llvm::is_contained(PreferInterfaceForModules, moduleName) ?
ModuleLoadingMode::PreferInterface : LoadMode);
nullptr,
ModuleLoadingMode::PreferSerialized);
SmallVector<FileDependency, 16> deps;
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
for (auto mod: candidates) {
Expand Down
3 changes: 1 addition & 2 deletions lib/Serialization/ModuleDependencyScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ std::error_code PlaceholderSwiftModuleScanner::findModuleFilesInDirectory(
static std::vector<std::string> getCompiledCandidates(ASTContext &ctx,
StringRef moduleName,
StringRef interfacePath) {
return static_cast<SerializedModuleLoaderBase*>(ctx
.getModuleInterfaceLoader())->getCompiledModuleCandidatesForInterface(
return ctx.getModuleInterfaceChecker()->getCompiledModuleCandidatesForInterface(
moduleName.str(), interfacePath);
}

Expand Down
7 changes: 6 additions & 1 deletion unittests/FrontendTool/ModuleLoadingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,13 @@ class ModuleInterfaceLoaderTest : public testing::Test {
ASTContext::get(langOpts, typeckOpts, searchPathOpts, clangImpOpts,
sourceMgr, diags);

ctx->addModuleInterfaceChecker(
std::make_unique<ModuleInterfaceCheckerImpl>(*ctx, cacheDir,
prebuiltCacheDir, ModuleInterfaceLoaderOptions()));

auto loader = ModuleInterfaceLoader::create(
*ctx, cacheDir, prebuiltCacheDir,
*ctx, *static_cast<ModuleInterfaceCheckerImpl*>(
ctx->getModuleInterfaceChecker()),
/*dependencyTracker*/nullptr,
ModuleLoadingMode::PreferSerialized);

Expand Down