Skip to content

Commit 6ca24c9

Browse files
committed
Factor out checking if a binary module is up-to-date from the rest of 'ModuleInterfaceLoaderImpl' logic, to be used by other clients
1 parent 72caba2 commit 6ca24c9

File tree

1 file changed

+141
-119
lines changed

1 file changed

+141
-119
lines changed

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 141 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -337,58 +337,100 @@ struct ModuleRebuildInfo {
337337
}
338338
};
339339

340-
/// Handles the details of loading module interfaces as modules, and will
341-
/// do the necessary lookup to determine if we should be loading from the
342-
/// normal cache, the prebuilt cache, a module adjacent to the interface, or
343-
/// a module that we'll build from a module interface.
344-
class ModuleInterfaceLoaderImpl {
345-
friend class swift::ModuleInterfaceLoader;
346-
friend class swift::ModuleInterfaceCheckerImpl;
340+
/// Constructs the full path of the dependency \p dep by prepending the SDK
341+
/// path if necessary.
342+
StringRef getFullDependencyPath(const FileDependency &dep,
343+
const ASTContext &ctx,
344+
SmallVectorImpl<char> &scratch) {
345+
if (!dep.isSDKRelative())
346+
return dep.getPath();
347+
348+
path::native(ctx.SearchPathOpts.getSDKPath(), scratch);
349+
llvm::sys::path::append(scratch, dep.getPath());
350+
return StringRef(scratch.data(), scratch.size());
351+
}
352+
353+
class UpToDateModuleCheker {
347354
ASTContext &ctx;
348355
llvm::vfs::FileSystem &fs;
349-
DiagnosticEngine &diags;
350-
ModuleRebuildInfo rebuildInfo;
351-
const StringRef modulePath;
352-
const std::string interfacePath;
353-
const StringRef moduleName;
354-
const StringRef prebuiltCacheDir;
355-
const StringRef backupInterfaceDir;
356-
const StringRef cacheDir;
357-
const SourceLoc diagnosticLoc;
358-
DependencyTracker *const dependencyTracker;
359-
const ModuleLoadingMode loadMode;
360-
ModuleInterfaceLoaderOptions Opts;
361356
RequireOSSAModules_t requiresOSSAModules;
362357

363-
ModuleInterfaceLoaderImpl(
364-
ASTContext &ctx, StringRef modulePath, StringRef interfacePath,
365-
StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir,
366-
StringRef backupInterfaceDir,
367-
SourceLoc diagLoc, ModuleInterfaceLoaderOptions Opts,
368-
RequireOSSAModules_t requiresOSSAModules,
369-
DependencyTracker *dependencyTracker = nullptr,
370-
ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized)
371-
: ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags),
372-
modulePath(modulePath), interfacePath(interfacePath),
373-
moduleName(moduleName),
374-
prebuiltCacheDir(prebuiltCacheDir),
375-
backupInterfaceDir(backupInterfaceDir),
376-
cacheDir(cacheDir), diagnosticLoc(diagLoc),
377-
dependencyTracker(dependencyTracker), loadMode(loadMode), Opts(Opts),
378-
requiresOSSAModules(requiresOSSAModules) {}
358+
public:
359+
UpToDateModuleCheker(ASTContext &ctx, RequireOSSAModules_t requiresOSSAModules)
360+
: ctx(ctx),
361+
fs(*ctx.SourceMgr.getFileSystem()),
362+
requiresOSSAModules(requiresOSSAModules) {}
363+
364+
// Check if all the provided file dependencies are up-to-date compared to
365+
// what's currently on disk.
366+
bool dependenciesAreUpToDate(StringRef modulePath,
367+
ModuleRebuildInfo &rebuildInfo,
368+
ArrayRef<FileDependency> deps,
369+
bool skipSystemDependencies) {
370+
SmallString<128> SDKRelativeBuffer;
371+
for (auto &in : deps) {
372+
if (skipSystemDependencies && in.isSDKRelative() &&
373+
in.isModificationTimeBased()) {
374+
continue;
375+
}
376+
StringRef fullPath = getFullDependencyPath(in, ctx, SDKRelativeBuffer);
377+
switch (checkDependency(modulePath, in, fullPath)) {
378+
case DependencyStatus::UpToDate:
379+
LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is up to date\n");
380+
break;
381+
case DependencyStatus::OutOfDate:
382+
LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is out of date\n");
383+
rebuildInfo.addOutOfDateDependency(modulePath, fullPath);
384+
return false;
385+
case DependencyStatus::Missing:
386+
LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is missing\n");
387+
rebuildInfo.addMissingDependency(modulePath, fullPath);
388+
return false;
389+
}
390+
}
391+
return true;
392+
}
393+
394+
// Check that the output .swiftmodule file is at least as new as all the
395+
// dependencies it read when it was built last time.
396+
bool serializedASTBufferIsUpToDate(
397+
StringRef path, const llvm::MemoryBuffer &buf,
398+
ModuleRebuildInfo &rebuildInfo,
399+
SmallVectorImpl<FileDependency> &allDeps) {
400+
401+
// Clear the existing dependencies, because we're going to re-fill them
402+
// in validateSerializedAST.
403+
allDeps.clear();
379404

380-
/// Constructs the full path of the dependency \p dep by prepending the SDK
381-
/// path if necessary.
382-
StringRef getFullDependencyPath(const FileDependency &dep,
383-
SmallVectorImpl<char> &scratch) const {
384-
if (!dep.isSDKRelative())
385-
return dep.getPath();
405+
LLVM_DEBUG(llvm::dbgs() << "Validating deps of " << path << "\n");
406+
auto validationInfo = serialization::validateSerializedAST(
407+
buf.getBuffer(), requiresOSSAModules, ctx.LangOpts.SDKName,
408+
/*ExtendedValidationInfo=*/nullptr, &allDeps);
386409

387-
path::native(ctx.SearchPathOpts.getSDKPath(), scratch);
388-
llvm::sys::path::append(scratch, dep.getPath());
389-
return StringRef(scratch.data(), scratch.size());
410+
if (validationInfo.status != serialization::Status::Valid) {
411+
rebuildInfo.setSerializationStatus(path, validationInfo.status);
412+
return false;
413+
}
414+
415+
bool skipCheckingSystemDependencies =
416+
ctx.SearchPathOpts.DisableModulesValidateSystemDependencies;
417+
return dependenciesAreUpToDate(path, rebuildInfo, allDeps,
418+
skipCheckingSystemDependencies);
390419
}
391420

421+
// Check that the output .swiftmodule file is at least as new as all the
422+
// dependencies it read when it was built last time.
423+
bool swiftModuleIsUpToDate(
424+
StringRef modulePath, ModuleRebuildInfo &rebuildInfo,
425+
SmallVectorImpl<FileDependency> &AllDeps,
426+
std::unique_ptr<llvm::MemoryBuffer> &moduleBuffer) {
427+
auto OutBuf = fs.getBufferForFile(modulePath);
428+
if (!OutBuf)
429+
return false;
430+
moduleBuffer = std::move(*OutBuf);
431+
return serializedASTBufferIsUpToDate(modulePath, *moduleBuffer, rebuildInfo, AllDeps);
432+
}
433+
392434
enum class DependencyStatus {
393435
UpToDate,
394436
OutOfDate,
@@ -429,6 +471,49 @@ class ModuleInterfaceLoaderImpl {
429471
DependencyStatus::UpToDate :
430472
DependencyStatus::OutOfDate;
431473
}
474+
};
475+
476+
/// Handles the details of loading module interfaces as modules, and will
477+
/// do the necessary lookup to determine if we should be loading from the
478+
/// normal cache, the prebuilt cache, a module adjacent to the interface, or
479+
/// a module that we'll build from a module interface.
480+
class ModuleInterfaceLoaderImpl {
481+
friend class swift::ModuleInterfaceLoader;
482+
friend class swift::ModuleInterfaceCheckerImpl;
483+
ASTContext &ctx;
484+
llvm::vfs::FileSystem &fs;
485+
DiagnosticEngine &diags;
486+
ModuleRebuildInfo rebuildInfo;
487+
UpToDateModuleCheker upToDateChecker;
488+
const StringRef modulePath;
489+
const std::string interfacePath;
490+
const StringRef moduleName;
491+
const StringRef prebuiltCacheDir;
492+
const StringRef backupInterfaceDir;
493+
const StringRef cacheDir;
494+
const SourceLoc diagnosticLoc;
495+
DependencyTracker *const dependencyTracker;
496+
const ModuleLoadingMode loadMode;
497+
ModuleInterfaceLoaderOptions Opts;
498+
RequireOSSAModules_t requiresOSSAModules;
499+
500+
ModuleInterfaceLoaderImpl(
501+
ASTContext &ctx, StringRef modulePath, StringRef interfacePath,
502+
StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir,
503+
StringRef backupInterfaceDir,
504+
SourceLoc diagLoc, ModuleInterfaceLoaderOptions Opts,
505+
RequireOSSAModules_t requiresOSSAModules,
506+
DependencyTracker *dependencyTracker = nullptr,
507+
ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized)
508+
: ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags),
509+
upToDateChecker(ctx, requiresOSSAModules),
510+
modulePath(modulePath), interfacePath(interfacePath),
511+
moduleName(moduleName),
512+
prebuiltCacheDir(prebuiltCacheDir),
513+
backupInterfaceDir(backupInterfaceDir),
514+
cacheDir(cacheDir), diagnosticLoc(diagLoc),
515+
dependencyTracker(dependencyTracker), loadMode(loadMode), Opts(Opts),
516+
requiresOSSAModules(requiresOSSAModules) {}
432517

433518
std::string getBackupPublicModuleInterfacePath() {
434519
return getBackupPublicModuleInterfacePath(ctx.SourceMgr, backupInterfaceDir,
@@ -461,73 +546,6 @@ class ModuleInterfaceLoaderImpl {
461546
return std::string();
462547
}
463548

464-
// Check if all the provided file dependencies are up-to-date compared to
465-
// what's currently on disk.
466-
bool dependenciesAreUpToDate(StringRef modulePath,
467-
ArrayRef<FileDependency> deps,
468-
bool skipSystemDependencies) {
469-
SmallString<128> SDKRelativeBuffer;
470-
for (auto &in : deps) {
471-
if (skipSystemDependencies && in.isSDKRelative() &&
472-
in.isModificationTimeBased()) {
473-
continue;
474-
}
475-
StringRef fullPath = getFullDependencyPath(in, SDKRelativeBuffer);
476-
switch (checkDependency(modulePath, in, fullPath)) {
477-
case DependencyStatus::UpToDate:
478-
LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is up to date\n");
479-
break;
480-
case DependencyStatus::OutOfDate:
481-
LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is out of date\n");
482-
rebuildInfo.addOutOfDateDependency(modulePath, fullPath);
483-
return false;
484-
case DependencyStatus::Missing:
485-
LLVM_DEBUG(llvm::dbgs() << "Dep " << fullPath << " is missing\n");
486-
rebuildInfo.addMissingDependency(modulePath, fullPath);
487-
return false;
488-
}
489-
}
490-
return true;
491-
}
492-
493-
// Check that the output .swiftmodule file is at least as new as all the
494-
// dependencies it read when it was built last time.
495-
bool serializedASTBufferIsUpToDate(
496-
StringRef path, const llvm::MemoryBuffer &buf,
497-
SmallVectorImpl<FileDependency> &allDeps) {
498-
499-
// Clear the existing dependencies, because we're going to re-fill them
500-
// in validateSerializedAST.
501-
allDeps.clear();
502-
503-
LLVM_DEBUG(llvm::dbgs() << "Validating deps of " << path << "\n");
504-
auto validationInfo = serialization::validateSerializedAST(
505-
buf.getBuffer(), requiresOSSAModules, ctx.LangOpts.SDKName,
506-
/*ExtendedValidationInfo=*/nullptr, &allDeps);
507-
508-
if (validationInfo.status != serialization::Status::Valid) {
509-
rebuildInfo.setSerializationStatus(path, validationInfo.status);
510-
return false;
511-
}
512-
513-
bool skipCheckingSystemDependencies =
514-
ctx.SearchPathOpts.DisableModulesValidateSystemDependencies;
515-
return dependenciesAreUpToDate(path, allDeps,
516-
skipCheckingSystemDependencies);
517-
}
518-
519-
// Check that the output .swiftmodule file is at least as new as all the
520-
// dependencies it read when it was built last time.
521-
bool swiftModuleIsUpToDate(
522-
StringRef modulePath, SmallVectorImpl<FileDependency> &AllDeps,
523-
std::unique_ptr<llvm::MemoryBuffer> &moduleBuffer) {
524-
auto OutBuf = fs.getBufferForFile(modulePath);
525-
if (!OutBuf)
526-
return false;
527-
moduleBuffer = std::move(*OutBuf);
528-
return serializedASTBufferIsUpToDate(modulePath, *moduleBuffer, AllDeps);
529-
}
530-
531549
// Check that a "forwarding" .swiftmodule file is at least as new as all the
532550
// dependencies it read when it was built last time. Requires that the
533551
// forwarding module has been loaded from disk.
@@ -557,7 +575,8 @@ class ModuleInterfaceLoaderImpl {
557575

558576
bool skipCheckingSystemDependencies =
559577
ctx.SearchPathOpts.DisableModulesValidateSystemDependencies;
560-
if (!dependenciesAreUpToDate(path, deps, skipCheckingSystemDependencies))
578+
if (!upToDateChecker.dependenciesAreUpToDate(path, rebuildInfo, deps,
579+
skipCheckingSystemDependencies))
561580
return false;
562581

563582
moduleBuffer = std::move(*modBuf);
@@ -729,8 +748,8 @@ class ModuleInterfaceLoaderImpl {
729748
if (!adjacentMod.empty()) {
730749
auto adjacentModuleBuffer = fs.getBufferForFile(adjacentMod);
731750
if (adjacentModuleBuffer) {
732-
if (serializedASTBufferIsUpToDate(adjacentMod, *adjacentModuleBuffer.get(),
733-
deps)) {
751+
if (upToDateChecker.serializedASTBufferIsUpToDate(adjacentMod, *adjacentModuleBuffer.get(),
752+
rebuildInfo, deps)) {
734753
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date module at "
735754
<< adjacentMod
736755
<< "; deferring to serialized module loader\n");
@@ -767,7 +786,8 @@ class ModuleInterfaceLoaderImpl {
767786

768787
if(!prebuiltMod.empty()) {
769788
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
770-
if (swiftModuleIsUpToDate(prebuiltMod, deps, moduleBuffer)) {
789+
if (upToDateChecker.swiftModuleIsUpToDate(prebuiltMod, rebuildInfo,
790+
deps, moduleBuffer)) {
771791
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date prebuilt module at "
772792
<< prebuiltMod << "\n");
773793
UsableModulePath = prebuiltMod;
@@ -819,7 +839,8 @@ class ModuleInterfaceLoaderImpl {
819839
ModuleRebuildInfo::ModuleKind::Forwarding);
820840
}
821841
// Otherwise, check if the AST buffer itself is up to date.
822-
} else if (serializedASTBufferIsUpToDate(cachedOutputPath, *buf, deps)) {
842+
} else if (upToDateChecker.serializedASTBufferIsUpToDate(cachedOutputPath, *buf,
843+
rebuildInfo, deps)) {
823844
LLVM_DEBUG(llvm::dbgs() << "Found up-to-date cached module at "
824845
<< cachedOutputPath << "\n");
825846
return DiscoveredModule::normal(cachedOutputPath, std::move(buf));
@@ -854,7 +875,7 @@ class ModuleInterfaceLoaderImpl {
854875
// we may record out-of-date information.
855876
SmallString<128> SDKRelativeBuffer;
856877
auto addDependency = [&](FileDependency dep) -> FileDependency {
857-
auto status = fs.status(getFullDependencyPath(dep, SDKRelativeBuffer));
878+
auto status = fs.status(getFullDependencyPath(dep, ctx, SDKRelativeBuffer));
858879
uint64_t mtime =
859880
status->getLastModificationTime().time_since_epoch().count();
860881
fwd.addDependency(dep.getPath(), dep.isSDKRelative(), status->getSize(),
@@ -955,7 +976,7 @@ class ModuleInterfaceLoaderImpl {
955976
if (dependencyTracker) {
956977
SmallString<128> SDKRelativeBuffer;
957978
for (auto &dep: allDeps) {
958-
StringRef fullPath = getFullDependencyPath(dep, SDKRelativeBuffer);
979+
StringRef fullPath = getFullDependencyPath(dep, ctx, SDKRelativeBuffer);
959980
dependencyTracker->addDependency(fullPath,
960981
/*IsSystem=*/dep.isSDKRelative());
961982
}
@@ -1197,7 +1218,8 @@ bool ModuleInterfaceCheckerImpl::tryEmitForwardingModule(
11971218
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
11981219
for (auto mod: candidates) {
11991220
// Check if the candidate compiled module is still up-to-date.
1200-
if (Impl.swiftModuleIsUpToDate(mod, deps, moduleBuffer)) {
1221+
if (Impl.upToDateChecker.swiftModuleIsUpToDate(mod, Impl.rebuildInfo,
1222+
deps, moduleBuffer)) {
12011223
// If so, emit a forwarding module to the candidate.
12021224
ForwardingModule FM(mod);
12031225
auto hadError = withOutputFile(Ctx.Diags, outputPath,

0 commit comments

Comments
 (0)