Skip to content

Commit 8ccee27

Browse files
committed
ModuleInterface: refactor ModuleInterfaceChecker out of ModuleInterfaceLoader
This refactoring allows us to drop ModuleInterfaceLoader when explicit modules are enabled. Before this change, the dependencies scanner needs the loader to be present to access functionalities like collecting prebuilt module candidates.
1 parent 8920da2 commit 8ccee27

File tree

10 files changed

+117
-91
lines changed

10 files changed

+117
-91
lines changed

include/swift/AST/ASTContext.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,12 @@ class ASTContext final {
762762
bool isClang = false, bool isDWARF = false,
763763
bool IsInterface = false);
764764

765+
/// Add a module interface checker to use for this AST context.
766+
void addModuleInterfaceChecker(std::unique_ptr<ModuleInterfaceChecker> checker);
767+
768+
/// Retrieve the module interface checker associated with this AST context.
769+
ModuleInterfaceChecker *getModuleInterfaceChecker() const;
770+
765771
/// Retrieve the module dependencies for the module with the given name.
766772
///
767773
/// \param isUnderlyingClangModule When true, only look for a Clang module
@@ -839,9 +845,6 @@ class ASTContext final {
839845
/// If there is no Clang module loader, returns a null pointer.
840846
/// The loader is owned by the AST context.
841847
ClangModuleLoader *getDWARFModuleLoader() const;
842-
843-
/// Retrieve the module interface loader for this ASTContext.
844-
ModuleLoader *getModuleInterfaceLoader() const;
845848
public:
846849
namelookup::ImportCache &getImportCache() const;
847850

include/swift/AST/ModuleLoader.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,23 @@ struct SubCompilerInstanceInfo {
116116
ArrayRef<StringRef> ExtraPCMArgs;
117117
};
118118

119+
/// Abstract interface for a checker of module interfaces and prebuilt modules.
120+
class ModuleInterfaceChecker {
121+
public:
122+
virtual std::vector<std::string>
123+
getCompiledModuleCandidatesForInterface(StringRef moduleName,
124+
StringRef interfacePath) = 0;
125+
126+
/// Given a list of potential ready-to-use compiled modules for \p interfacePath,
127+
/// check if any one of them is up-to-date. If so, emit a forwarding module
128+
/// to the candidate binary module to \p outPath.
129+
virtual bool tryEmitForwardingModule(StringRef moduleName,
130+
StringRef interfacePath,
131+
ArrayRef<std::string> candidates,
132+
StringRef outPath) = 0;
133+
virtual ~ModuleInterfaceChecker() = default;
134+
};
135+
119136
/// Abstract interface to run an action in a sub ASTContext.
120137
struct InterfaceSubContextDelegate {
121138
virtual std::error_code runInSubContext(StringRef moduleName,

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -309,27 +309,52 @@ struct ModuleInterfaceLoaderOptions {
309309
ModuleInterfaceLoaderOptions() = default;
310310
};
311311

312+
class ModuleInterfaceCheckerImpl: public ModuleInterfaceChecker {
313+
friend class ModuleInterfaceLoader;
314+
ASTContext &Ctx;
315+
std::string CacheDir;
316+
std::string PrebuiltCacheDir;
317+
ModuleInterfaceLoaderOptions Opts;
318+
319+
public:
320+
explicit ModuleInterfaceCheckerImpl(ASTContext &Ctx,
321+
StringRef cacheDir,
322+
StringRef prebuiltCacheDir,
323+
ModuleInterfaceLoaderOptions Opts)
324+
: Ctx(Ctx), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir),
325+
Opts(Opts) {}
326+
327+
std::vector<std::string>
328+
getCompiledModuleCandidatesForInterface(StringRef moduleName,
329+
StringRef interfacePath) override;
330+
331+
/// Given a list of potential ready-to-use compiled modules for \p interfacePath,
332+
/// check if any one of them is up-to-date. If so, emit a forwarding module
333+
/// to the candidate binary module to \p outPath.
334+
bool tryEmitForwardingModule(StringRef moduleName,
335+
StringRef interfacePath,
336+
ArrayRef<std::string> candidates,
337+
StringRef outPath) override;
338+
bool isCached(StringRef DepPath);
339+
};
340+
312341
/// A ModuleLoader that runs a subordinate \c CompilerInvocation and
313342
/// \c CompilerInstance to convert .swiftinterface files to .swiftmodule
314343
/// files on the fly, caching the resulting .swiftmodules in the module cache
315344
/// directory, and loading the serialized .swiftmodules from there.
316345
class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
317346
friend class unittest::ModuleInterfaceLoaderTest;
318347
explicit ModuleInterfaceLoader(
319-
ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir,
348+
ASTContext &ctx, ModuleInterfaceCheckerImpl &InterfaceChecker,
320349
DependencyTracker *tracker, ModuleLoadingMode loadMode,
321350
ArrayRef<std::string> PreferInterfaceForModules,
322-
bool IgnoreSwiftSourceInfoFile, ModuleInterfaceLoaderOptions Opts)
323-
: SerializedModuleLoaderBase(ctx, tracker, loadMode,
324-
IgnoreSwiftSourceInfoFile),
325-
CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir),
326-
PreferInterfaceForModules(PreferInterfaceForModules),
327-
Opts(Opts) {}
351+
bool IgnoreSwiftSourceInfoFile)
352+
: SerializedModuleLoaderBase(ctx, tracker, loadMode, IgnoreSwiftSourceInfoFile),
353+
InterfaceChecker(InterfaceChecker),
354+
PreferInterfaceForModules(PreferInterfaceForModules){}
328355

329-
std::string CacheDir;
330-
std::string PrebuiltCacheDir;
356+
ModuleInterfaceCheckerImpl &InterfaceChecker;
331357
ArrayRef<std::string> PreferInterfaceForModules;
332-
ModuleInterfaceLoaderOptions Opts;
333358

334359
std::error_code findModuleFilesInDirectory(
335360
ImportPath::Element ModuleID,
@@ -343,17 +368,14 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
343368
bool isCached(StringRef DepPath) override;
344369
public:
345370
static std::unique_ptr<ModuleInterfaceLoader>
346-
create(ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir,
371+
create(ASTContext &ctx, ModuleInterfaceCheckerImpl &InterfaceChecker,
347372
DependencyTracker *tracker, ModuleLoadingMode loadMode,
348373
ArrayRef<std::string> PreferInterfaceForModules = {},
349-
ModuleInterfaceLoaderOptions Opts = ModuleInterfaceLoaderOptions(),
350374
bool IgnoreSwiftSourceInfoFile = false) {
351375
return std::unique_ptr<ModuleInterfaceLoader>(
352-
new ModuleInterfaceLoader(ctx, cacheDir, prebuiltCacheDir,
353-
tracker, loadMode,
354-
PreferInterfaceForModules,
355-
IgnoreSwiftSourceInfoFile,
356-
Opts));
376+
new ModuleInterfaceLoader(ctx, InterfaceChecker, tracker, loadMode,
377+
PreferInterfaceForModules,
378+
IgnoreSwiftSourceInfoFile));
357379
}
358380

359381
/// Append visible module names to \p names. Note that names are possibly
@@ -373,18 +395,6 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
373395
StringRef ModuleName, StringRef InPath, StringRef OutPath,
374396
bool SerializeDependencyHashes, bool TrackSystemDependencies,
375397
ModuleInterfaceLoaderOptions Opts);
376-
377-
std::vector<std::string>
378-
getCompiledModuleCandidatesForInterface(StringRef moduleName,
379-
StringRef interfacePath) override;
380-
381-
/// Given a list of potential ready-to-use compiled modules for \p interfacePath,
382-
/// check if any one of them is up-to-date. If so, emit a forwarding module
383-
/// to the candidate binary module to \p outPath.
384-
bool tryEmitForwardingModule(StringRef moduleName,
385-
StringRef interfacePath,
386-
ArrayRef<std::string> candidates,
387-
StringRef outPath) override;
388398
};
389399

390400
struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -201,18 +201,6 @@ class SerializedModuleLoaderBase : public ModuleLoader {
201201
virtual Optional<ModuleDependencies> getModuleDependencies(
202202
StringRef moduleName, ModuleDependenciesCache &cache,
203203
InterfaceSubContextDelegate &delegate) override;
204-
205-
virtual std::vector<std::string>
206-
getCompiledModuleCandidatesForInterface(StringRef moduleName,
207-
StringRef interfacePath) {
208-
return std::vector<std::string>();
209-
}
210-
virtual bool tryEmitForwardingModule(StringRef moduleName,
211-
StringRef interfacePath,
212-
ArrayRef<std::string> candidates,
213-
StringRef outPath) {
214-
return false;
215-
}
216204
};
217205

218206
/// Imports serialized Swift modules into an ASTContext.

lib/AST/ASTContext.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ struct ASTContext::Implementation {
255255
/// The set of known protocols, lazily populated as needed.
256256
ProtocolDecl *KnownProtocols[NumKnownProtocols] = { };
257257

258+
/// The module interface checker owned by the ASTContext.
259+
std::unique_ptr<ModuleInterfaceChecker> InterfaceChecker;
260+
258261
/// The various module loaders that import external modules into this
259262
/// ASTContext.
260263
SmallVector<std::unique_ptr<swift::ModuleLoader>, 4> ModuleLoaders;
@@ -268,9 +271,6 @@ struct ASTContext::Implementation {
268271
/// The module loader used to load Clang modules from DWARF.
269272
ClangModuleLoader *TheDWARFModuleLoader = nullptr;
270273

271-
/// The module loader used to load Swift textual interface.
272-
ModuleLoader *TheModuleInterfaceLoader = nullptr;
273-
274274
/// Map from Swift declarations to raw comments.
275275
llvm::DenseMap<const Decl *, RawComment> RawComments;
276276

@@ -1519,11 +1519,15 @@ void ASTContext::addModuleLoader(std::unique_ptr<ModuleLoader> loader,
15191519
if (IsClang && IsDwarf && !getImpl().TheDWARFModuleLoader)
15201520
getImpl().TheDWARFModuleLoader =
15211521
static_cast<ClangModuleLoader *>(loader.get());
1522-
if (IsInterface && !getImpl().TheModuleInterfaceLoader)
1523-
getImpl().TheModuleInterfaceLoader = loader.get();
15241522
getImpl().ModuleLoaders.push_back(std::move(loader));
15251523
}
15261524

1525+
void ASTContext::addModuleInterfaceChecker(
1526+
std::unique_ptr<ModuleInterfaceChecker> checker) {
1527+
assert(!getImpl().InterfaceChecker && "Checker has been set already");
1528+
getImpl().InterfaceChecker = std::move(checker);
1529+
}
1530+
15271531
Optional<ModuleDependencies> ASTContext::getModuleDependencies(
15281532
StringRef moduleName, bool isUnderlyingClangModule,
15291533
ModuleDependenciesCache &cache, InterfaceSubContextDelegate &delegate) {
@@ -1610,8 +1614,10 @@ ClangModuleLoader *ASTContext::getDWARFModuleLoader() const {
16101614
return getImpl().TheDWARFModuleLoader;
16111615
}
16121616

1613-
ModuleLoader *ASTContext::getModuleInterfaceLoader() const {
1614-
return getImpl().TheModuleInterfaceLoader;
1617+
ModuleInterfaceChecker *ASTContext::getModuleInterfaceChecker() const {
1618+
auto *result = getImpl().InterfaceChecker.get();
1619+
assert(result);
1620+
return result;
16151621
}
16161622

16171623
ModuleDecl *ASTContext::getLoadedModule(

lib/Frontend/Frontend.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,14 @@ bool CompilerInstance::setUpModuleLoaders() {
493493
return true;
494494
}
495495

496+
// Configure ModuleInterfaceChecker for the ASTContext.
497+
auto const &Clang = clangImporter->getClangInstance();
498+
std::string ModuleCachePath = getModuleCachePathFromClang(Clang);
499+
auto &FEOpts = Invocation.getFrontendOptions();
500+
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
501+
Context->addModuleInterfaceChecker(
502+
std::make_unique<ModuleInterfaceCheckerImpl>(*Context, ModuleCachePath,
503+
FEOpts.PrebuiltModuleCachePath, LoaderOpts));
496504
// If implicit modules are disabled, we need to install an explicit module
497505
// loader.
498506
bool ExplicitModuleBuild = Invocation.getFrontendOptions().DisableImplicitModules;
@@ -505,23 +513,15 @@ bool CompilerInstance::setUpModuleLoaders() {
505513
IgnoreSourceInfoFile);
506514
this->DefaultSerializedLoader = ESML.get();
507515
Context->addModuleLoader(std::move(ESML));
508-
}
509-
510-
if (MLM != ModuleLoadingMode::OnlySerialized) {
511-
auto const &Clang = clangImporter->getClangInstance();
512-
std::string ModuleCachePath = getModuleCachePathFromClang(Clang);
513-
auto &FEOpts = Invocation.getFrontendOptions();
514-
StringRef PrebuiltModuleCachePath = FEOpts.PrebuiltModuleCachePath;
515-
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
516-
auto PIML = ModuleInterfaceLoader::create(
517-
*Context, ModuleCachePath, PrebuiltModuleCachePath,
518-
getDependencyTracker(), MLM, FEOpts.PreferInterfaceForModules,
519-
LoaderOpts,
520-
IgnoreSourceInfoFile);
521-
Context->addModuleLoader(std::move(PIML), false, false, true);
522-
}
523-
524-
if (!ExplicitModuleBuild) {
516+
} else {
517+
if (MLM != ModuleLoadingMode::OnlySerialized) {
518+
// We only need ModuleInterfaceLoader for implicit modules.
519+
auto PIML = ModuleInterfaceLoader::create(
520+
*Context, *static_cast<ModuleInterfaceCheckerImpl*>(Context
521+
->getModuleInterfaceChecker()), getDependencyTracker(), MLM,
522+
FEOpts.PreferInterfaceForModules, IgnoreSourceInfoFile);
523+
Context->addModuleLoader(std::move(PIML), false, false, true);
524+
}
525525
std::unique_ptr<ImplicitSerializedModuleLoader> ISML =
526526
ImplicitSerializedModuleLoader::create(*Context, getDependencyTracker(), MLM,
527527
IgnoreSourceInfoFile);

lib/Frontend/ModuleInterfaceBuilder.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,9 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
170170
auto &SubInstance = *info.Instance;
171171
auto subInvocation = SubInstance.getInvocation();
172172
// Try building forwarding module first. If succeed, return.
173-
if (static_cast<ModuleInterfaceLoader*>(SubInstance.getASTContext()
174-
.getModuleInterfaceLoader())->tryEmitForwardingModule(moduleName,
175-
interfacePath,
176-
CompiledCandidates, OutPath)) {
173+
if (SubInstance.getASTContext().getModuleInterfaceChecker()
174+
->tryEmitForwardingModule(moduleName, interfacePath,
175+
CompiledCandidates, OutPath)) {
177176
return std::error_code();
178177
}
179178
FrontendOptions &FEOpts = subInvocation.getFrontendOptions();

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ struct ModuleRebuildInfo {
335335
/// a module that we'll build from a module interface.
336336
class ModuleInterfaceLoaderImpl {
337337
friend class swift::ModuleInterfaceLoader;
338+
friend class swift::ModuleInterfaceCheckerImpl;
338339
ASTContext &ctx;
339340
llvm::vfs::FileSystem &fs;
340341
DiagnosticEngine &diags;
@@ -907,10 +908,6 @@ class ModuleInterfaceLoaderImpl {
907908

908909
return std::move(module.moduleBuffer);
909910
}
910-
// If implicit module is disabled, we are done.
911-
if (Opts.disableImplicitSwiftModule) {
912-
return std::make_error_code(std::errc::not_supported);
913-
}
914911

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

@@ -942,12 +939,16 @@ class ModuleInterfaceLoaderImpl {
942939

943940
} // end anonymous namespace
944941

945-
bool ModuleInterfaceLoader::isCached(StringRef DepPath) {
942+
bool ModuleInterfaceCheckerImpl::isCached(StringRef DepPath) {
946943
if (!CacheDir.empty() && DepPath.startswith(CacheDir))
947944
return true;
948945
return !PrebuiltCacheDir.empty() && DepPath.startswith(PrebuiltCacheDir);
949946
}
950947

948+
bool ModuleInterfaceLoader::isCached(StringRef DepPath) {
949+
return InterfaceChecker.isCached(DepPath);
950+
}
951+
951952
/// Load a .swiftmodule associated with a .swiftinterface either from a
952953
/// cache or by converting it in a subordinate \c CompilerInstance, caching
953954
/// the results.
@@ -990,8 +991,8 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
990991
auto ModuleName = ModuleID.Item.str();
991992
ModuleInterfaceLoaderImpl Impl(
992993
Ctx, ModPath, InPath, ModuleName,
993-
CacheDir, PrebuiltCacheDir, ModuleID.Loc,
994-
Opts,
994+
InterfaceChecker.CacheDir, InterfaceChecker.PrebuiltCacheDir,
995+
ModuleID.Loc, InterfaceChecker.Opts,
995996
dependencyTracker,
996997
llvm::is_contained(PreferInterfaceForModules,
997998
ModuleName) ?
@@ -1024,8 +1025,8 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory(
10241025
}
10251026

10261027
std::vector<std::string>
1027-
ModuleInterfaceLoader::getCompiledModuleCandidatesForInterface(StringRef moduleName,
1028-
StringRef interfacePath) {
1028+
ModuleInterfaceCheckerImpl::getCompiledModuleCandidatesForInterface(
1029+
StringRef moduleName, StringRef interfacePath) {
10291030
// Derive .swiftmodule path from the .swiftinterface path.
10301031
auto newExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
10311032
llvm::SmallString<32> modulePath = interfacePath;
@@ -1034,9 +1035,8 @@ ModuleInterfaceLoader::getCompiledModuleCandidatesForInterface(StringRef moduleN
10341035
Ctx, modulePath, interfacePath, moduleName,
10351036
CacheDir, PrebuiltCacheDir, SourceLoc(),
10361037
Opts,
1037-
dependencyTracker,
1038-
llvm::is_contained(PreferInterfaceForModules, moduleName) ?
1039-
ModuleLoadingMode::PreferInterface : LoadMode);
1038+
nullptr,
1039+
ModuleLoadingMode::PreferSerialized);
10401040
std::vector<std::string> results;
10411041
auto pair = Impl.getCompiledModuleCandidates();
10421042
// Add compiled module candidates only when they are non-empty.
@@ -1047,7 +1047,7 @@ ModuleInterfaceLoader::getCompiledModuleCandidatesForInterface(StringRef moduleN
10471047
return results;
10481048
}
10491049

1050-
bool ModuleInterfaceLoader::tryEmitForwardingModule(StringRef moduleName,
1050+
bool ModuleInterfaceCheckerImpl::tryEmitForwardingModule(StringRef moduleName,
10511051
StringRef interfacePath,
10521052
ArrayRef<std::string> candidates,
10531053
StringRef outputPath) {
@@ -1059,9 +1059,8 @@ bool ModuleInterfaceLoader::tryEmitForwardingModule(StringRef moduleName,
10591059
Ctx, modulePath, interfacePath, moduleName,
10601060
CacheDir, PrebuiltCacheDir, SourceLoc(),
10611061
Opts,
1062-
dependencyTracker,
1063-
llvm::is_contained(PreferInterfaceForModules, moduleName) ?
1064-
ModuleLoadingMode::PreferInterface : LoadMode);
1062+
nullptr,
1063+
ModuleLoadingMode::PreferSerialized);
10651064
SmallVector<FileDependency, 16> deps;
10661065
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
10671066
for (auto mod: candidates) {

lib/Serialization/ModuleDependencyScanner.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ std::error_code PlaceholderSwiftModuleScanner::findModuleFilesInDirectory(
9898
static std::vector<std::string> getCompiledCandidates(ASTContext &ctx,
9999
StringRef moduleName,
100100
StringRef interfacePath) {
101-
return static_cast<SerializedModuleLoaderBase*>(ctx
102-
.getModuleInterfaceLoader())->getCompiledModuleCandidatesForInterface(
101+
return ctx.getModuleInterfaceChecker()->getCompiledModuleCandidatesForInterface(
103102
moduleName.str(), interfacePath);
104103
}
105104

unittests/FrontendTool/ModuleLoadingTests.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,13 @@ class ModuleInterfaceLoaderTest : public testing::Test {
103103
ASTContext::get(langOpts, typeckOpts, searchPathOpts, clangImpOpts,
104104
sourceMgr, diags);
105105

106+
ctx->addModuleInterfaceChecker(
107+
std::make_unique<ModuleInterfaceCheckerImpl>(*ctx, cacheDir,
108+
prebuiltCacheDir, ModuleInterfaceLoaderOptions()));
109+
106110
auto loader = ModuleInterfaceLoader::create(
107-
*ctx, cacheDir, prebuiltCacheDir,
111+
*ctx, *static_cast<ModuleInterfaceCheckerImpl*>(
112+
ctx->getModuleInterfaceChecker()),
108113
/*dependencyTracker*/nullptr,
109114
ModuleLoadingMode::PreferSerialized);
110115

0 commit comments

Comments
 (0)