Skip to content

Commit 7d1d8a4

Browse files
committed
[Dependency Scanning] Factor ModuleDependenciesCache out of a CompilerInstance into callers of scanDependencies
It is now the responsibility of the scanDependencies code to instantiate (and share) the cache. e.g. FrontendTool instantiates a new cache per `-scan-dependencies` invocation, and the DependencyScanningTool keeps one shared cache across its lifetime.
1 parent 6cbb141 commit 7d1d8a4

File tree

9 files changed

+58
-59
lines changed

9 files changed

+58
-59
lines changed

include/swift/Frontend/Frontend.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,6 @@ class CompilerInstance {
491491
DependencyTracker *getDependencyTracker() { return DepTracker.get(); }
492492
const DependencyTracker *getDependencyTracker() const { return DepTracker.get(); }
493493

494-
ModuleDependenciesCache *getModuleDependencyCache() { return ModDepCache.get(); }
495-
496494
UnifiedStatsReporter *getStatsReporter() const { return Stats.get(); }
497495

498496
/// Retrieve the main module containing the files being compiled.
@@ -558,7 +556,6 @@ class CompilerInstance {
558556
bool setUpVirtualFileSystemOverlays();
559557
void setUpLLVMArguments();
560558
void setUpDiagnosticOptions();
561-
void setUpModuleDependencyCacheIfNeeded();
562559
bool setUpModuleLoaders();
563560
bool setUpInputs();
564561
bool setUpASTContextIfNeeded();

include/swift/SwiftScan/DependencyScanningTool.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ class DependencyScanningTool {
3535
///
3636
/// \returns a \c StringError with the diagnostic output if clang errors
3737
/// occurred, \c FullDependencies otherwise.
38-
std::string
38+
llvm::ErrorOr<std::string>
3939
getFullDependencies(ArrayRef<const char *> Command,
4040
const llvm::StringSet<> &InputFiles,
4141
const llvm::StringSet<> &PlaceholderModules);
4242

4343
private:
4444
/// Shared cache of module dependencies, re-used by individual queries
4545
/// during the lifetime of this Tool
46-
ModuleDependenciesCache GlobalCache;
46+
std::unique_ptr<ModuleDependenciesCache> SharedCache;
4747

4848
llvm::BumpPtrAllocator Alloc;
4949
llvm::StringSaver Saver;

include/swift/SwiftScan/ScanDependencies.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,27 @@ namespace swift {
1919

2020
class CompilerInvocation;
2121
class CompilerInstance;
22+
class ModuleDependenciesCache;
2223

2324
/// Batch scan the dependencies for modules specified in \c batchInputFile.
2425
bool batchScanModuleDependencies(CompilerInstance &instance,
2526
llvm::StringRef batchInputFile);
2627

2728
/// Scans the dependencies of the main module of \c instance and writes out
28-
/// the result in JSON
29+
/// the resulting JSON according to the instance's output parameters.
30+
/// This method is used for swift-frontend invocations in dependency scanning mode
31+
/// (-scan-dependencies), where the module dependency cache is not shared.
2932
bool scanAndOutputDependencies(CompilerInstance &instance);
3033

31-
/// Scans the dependencies of the main module of \c instance.
32-
bool scanDependencies(CompilerInstance &instance,
33-
llvm::raw_ostream &out);
34-
3534
/// Scans the dependencies of the underlying clang module of the main module
3635
/// of \c instance.
3736
bool scanClangDependencies(CompilerInstance &instance);
3837

38+
/// Scans the dependencies of the main module of \c instance.
39+
bool scanDependencies(CompilerInstance &instance,
40+
ModuleDependenciesCache &cache,
41+
llvm::raw_ostream &out);
42+
3943
} // end namespace swift
4044

4145
#endif

lib/Frontend/Frontend.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -321,22 +321,11 @@ void CompilerInstance::setupDependencyTrackerIfNeeded() {
321321
DepTracker = std::make_unique<DependencyTracker>(*collectionMode);
322322
}
323323

324-
void CompilerInstance::setUpModuleDependencyCacheIfNeeded() {
325-
const auto &Invocation = getInvocation();
326-
const auto &opts = Invocation.getFrontendOptions();
327-
if (opts.RequestedAction == FrontendOptions::ActionType::ScanDependencies ||
328-
opts.RequestedAction == FrontendOptions::ActionType::ScanClangDependencies) {
329-
ModDepCache = std::make_unique<ModuleDependenciesCache>();
330-
}
331-
}
332-
333324
bool CompilerInstance::setup(const CompilerInvocation &Invok) {
334325
Invocation = Invok;
335326

336327
setupDependencyTrackerIfNeeded();
337328

338-
setUpModuleDependencyCacheIfNeeded();
339-
340329
// If initializing the overlay file system fails there's no sense in
341330
// continuing because the compiler will read the wrong files.
342331
if (setUpVirtualFileSystemOverlays())

lib/FrontendTool/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ add_swift_host_library(swiftFrontendTool STATIC
44
ImportedModules.cpp
55
LoadedModuleTrace.cpp
66
MakeStyleDependencies.cpp
7-
ScanDependencies.cpp
87
TBD.cpp)
98
add_dependencies(swiftFrontendTool
109
swift-syntax-generated-headers

lib/FrontendTool/FrontendTool.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
#include "swift/FrontendTool/FrontendTool.h"
2424
#include "swift/SwiftScan/ScanDependencies.h"
25-
#include "ImportedModules.h"
25+
#include "Dependencies.h"
2626
#include "TBD.h"
2727
#include "swift/Subsystems.h"
2828
#include "swift/AST/DiagnosticsFrontend.h"
@@ -1134,6 +1134,7 @@ withSemanticAnalysis(CompilerInstance &Instance, FrontendObserver *observer,
11341134
static bool performScanDependencies(CompilerInstance &Instance) {
11351135
auto batchScanInput =
11361136
Instance.getASTContext().SearchPathOpts.BatchScanInputFilePath;
1137+
ModuleDependenciesCache SingleUseCache;
11371138
if (batchScanInput.empty()) {
11381139
return scanAndOutputDependencies(Instance);
11391140
} else {

lib/SwiftScan/DependencyScanningTool.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,10 @@ namespace swift {
2626
namespace dependencies {
2727

2828
DependencyScanningTool::DependencyScanningTool()
29-
: GlobalCache(), Alloc(), Saver(Alloc) {
30-
31-
32-
}
29+
: SharedCache(std::make_unique<ModuleDependenciesCache>()),
30+
Alloc(), Saver(Alloc) {}
3331

34-
std::string
32+
llvm::ErrorOr<std::string>
3533
DependencyScanningTool::getFullDependencies(ArrayRef<const char *> Command,
3634
const llvm::StringSet<> &InputFiles,
3735
const llvm::StringSet<> &PlaceholderModules) {
@@ -43,7 +41,7 @@ DependencyScanningTool::getFullDependencies(ArrayRef<const char *> Command,
4341
// Basic error checking on the arguments
4442
if (Command.empty()) {
4543
Instance->getDiags().diagnose(SourceLoc(), diag::error_no_frontend_args);
46-
return "Error";
44+
return std::make_error_code(std::errc::not_supported);
4745
}
4846

4947
CompilerInvocation Invocation;
@@ -59,15 +57,15 @@ DependencyScanningTool::getFullDependencies(ArrayRef<const char *> Command,
5957
SmallVector<const char*, 4> Args;
6058
llvm::cl::TokenizeGNUCommandLine(CommandString, Saver, Args);
6159
if (Invocation.parseArgs(Args, Instance->getDiags())) {
62-
return "Error";
60+
return std::make_error_code(std::errc::not_supported);
6361
}
6462

6563
// Setup the instance
6664
Instance->setup(Invocation);
6765

6866
std::string JSONOutput;
6967
llvm::raw_string_ostream Oss(JSONOutput);
70-
scanDependencies(*Instance, Oss);
68+
scanDependencies(*Instance, *SharedCache, Oss);
7169
Oss.flush();
7270

7371
return JSONOutput;

lib/SwiftScan/ScanDependencies.cpp

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,7 @@ static bool diagnoseCycle(CompilerInstance &instance,
670670
}
671671

672672
static bool scanModuleDependencies(CompilerInstance &instance,
673+
ModuleDependenciesCache &cache,
673674
StringRef moduleName,
674675
bool isClang,
675676
StringRef outputPath) {
@@ -681,10 +682,6 @@ static bool scanModuleDependencies(CompilerInstance &instance,
681682

682683
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
683684
std::set<ModuleDependencyID>> allModules;
684-
// Retrieve the instance's module dependency cache.
685-
ModuleDependenciesCache *cache = instance.getModuleDependencyCache();
686-
assert(cache &&
687-
"Dependency Scanner expected a ModuleDependenciesCache on a compiler instance.");
688685
InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags,
689686
ctx.SearchPathOpts, ctx.LangOpts,
690687
ctx.ClangImporterOpts,
@@ -700,11 +697,11 @@ static bool scanModuleDependencies(CompilerInstance &instance,
700697
if (isClang) {
701698
// Loading the clang module using Clang importer.
702699
// This action will populate the cache with the main module's dependencies.
703-
rootDeps = ctx.getModuleDependencies(moduleName, /*IsClang*/true, *cache,
700+
rootDeps = ctx.getModuleDependencies(moduleName, /*IsClang*/true, cache,
704701
ASTDelegate);
705702
} else {
706703
// Loading the swift module's dependencies.
707-
rootDeps = ctx.getSwiftModuleDependencies(moduleName, *cache, ASTDelegate);
704+
rootDeps = ctx.getSwiftModuleDependencies(moduleName, cache, ASTDelegate);
708705
}
709706
if (!rootDeps.hasValue()) {
710707
// We cannot find the clang module, abort.
@@ -726,16 +723,17 @@ static bool scanModuleDependencies(CompilerInstance &instance,
726723
++currentModuleIdx) {
727724
auto module = allModules[currentModuleIdx];
728725
auto discoveredModules =
729-
resolveDirectDependencies(instance, module, *cache, ASTDelegate);
726+
resolveDirectDependencies(instance, module, cache, ASTDelegate);
730727
allModules.insert(discoveredModules.begin(), discoveredModules.end());
731728
}
732729
// Write out the JSON description.
733-
writeJSON(out, instance, *cache, ASTDelegate, allModules.getArrayRef());
730+
writeJSON(out, instance, cache, ASTDelegate, allModules.getArrayRef());
734731
return false;
735732
}
736733

737734
bool swift::scanClangDependencies(CompilerInstance &instance) {
738-
return scanModuleDependencies(instance,
735+
ModuleDependenciesCache cache;
736+
return scanModuleDependencies(instance, cache,
739737
instance.getMainModule()->getNameStr(),
740738
/*isClang*/true,
741739
instance.getInvocation().getFrontendOptions()
@@ -745,6 +743,9 @@ bool swift::scanClangDependencies(CompilerInstance &instance) {
745743
bool swift::batchScanModuleDependencies(CompilerInstance &instance,
746744
llvm::StringRef batchInputFile) {
747745
const CompilerInvocation &invok = instance.getInvocation();
746+
// The primary cache used for scans carried out with the compiler instance
747+
// we have created
748+
ModuleDependenciesCache cache;
748749

749750
(void)instance.getMainModule();
750751
llvm::BumpPtrAllocator alloc;
@@ -755,20 +756,31 @@ bool swift::batchScanModuleDependencies(CompilerInstance &instance,
755756
return true;
756757
auto &diags = instance.getDiags();
757758
ForwardingDiagnosticConsumer FDC(diags);
758-
// Keep track of all compiler instances we have created.
759-
llvm::StringMap<std::unique_ptr<CompilerInstance>> subInstanceMap;
759+
760+
// Keep track of all compiler instances and dependency caches we have created.
761+
// TODO: Re-use a single cache across all invocations, once `alreadySeen`
762+
// state is no longer shared.
763+
llvm::StringMap<std::pair<std::unique_ptr<CompilerInstance>,
764+
std::unique_ptr<ModuleDependenciesCache>>> subInstanceMap;
760765
for (auto &entry: *results) {
761766
CompilerInstance *pInstance = nullptr;
767+
ModuleDependenciesCache *pCache = nullptr;
762768
if (entry.arguments.empty()) {
763769
// Use the compiler's instance if no arguments are specified.
764770
pInstance = &instance;
771+
pCache = &cache;
765772
} else if (subInstanceMap.count(entry.arguments)) {
766773
// Use the previously created instance if we've seen the arguments before.
767-
pInstance = subInstanceMap[entry.arguments].get();
774+
pInstance = subInstanceMap[entry.arguments].first.get();
775+
pCache = subInstanceMap[entry.arguments].second.get();
768776
} else {
769777
// Create a new instance by the arguments and save it in the map.
770-
pInstance = subInstanceMap.insert({entry.arguments,
771-
std::make_unique<CompilerInstance>()}).first->getValue().get();
778+
subInstanceMap.insert({entry.arguments,
779+
std::make_pair(std::make_unique<CompilerInstance>(),
780+
std::make_unique<ModuleDependenciesCache>())});
781+
782+
pInstance = subInstanceMap[entry.arguments].first.get();
783+
pCache = subInstanceMap[entry.arguments].second.get();
772784
SmallVector<const char*, 4> args;
773785
llvm::cl::TokenizeGNUCommandLine(entry.arguments, saver, args);
774786
CompilerInvocation subInvok = invok;
@@ -786,8 +798,8 @@ bool swift::batchScanModuleDependencies(CompilerInstance &instance,
786798
}
787799
assert(pInstance);
788800
// Scan using the chosen compiler instance.
789-
if (scanModuleDependencies(*pInstance, entry.moduleName, !entry.isSwift,
790-
entry.outputPath)) {
801+
if (scanModuleDependencies(*pInstance, *pCache, entry.moduleName,
802+
!entry.isSwift, entry.outputPath)) {
791803
return true;
792804
}
793805
}
@@ -801,6 +813,8 @@ bool swift::scanAndOutputDependencies(CompilerInstance &instance) {
801813
std::error_code EC;
802814
llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None);
803815

816+
ModuleDependenciesCache SingleUseCache;
817+
804818
if (out.has_error() || EC) {
805819
Context.Diags.diagnose(SourceLoc(), diag::error_opening_output, path,
806820
EC.message());
@@ -809,10 +823,11 @@ bool swift::scanAndOutputDependencies(CompilerInstance &instance) {
809823
}
810824

811825
// Execute scan, writing JSON output to the output stream
812-
return scanDependencies(instance, out);
826+
return scanDependencies(instance, SingleUseCache, out);
813827
}
814828

815829
bool swift::scanDependencies(CompilerInstance &instance,
830+
ModuleDependenciesCache &cache,
816831
llvm::raw_ostream &out) {
817832
ASTContext &Context = instance.getASTContext();
818833
ModuleDecl *mainModule = instance.getMainModule();
@@ -900,11 +915,7 @@ bool swift::scanDependencies(CompilerInstance &instance,
900915

901916
allModules.insert({mainModuleName.str(), mainDependencies.getKind()});
902917

903-
// Retrieve the instance's module dependency cache.
904-
ModuleDependenciesCache *cache = instance.getModuleDependencyCache();
905-
assert(cache &&
906-
"Dependency Scanner expected a ModuleDependenciesCache on a compiler instance.");
907-
cache->recordDependencies(mainModuleName, std::move(mainDependencies));
918+
cache.recordDependencies(mainModuleName, std::move(mainDependencies));
908919

909920
auto &ctx = instance.getASTContext();
910921
auto ModuleCachePath = getModuleCachePathFromClang(ctx
@@ -927,28 +938,28 @@ bool swift::scanDependencies(CompilerInstance &instance,
927938
++currentModuleIdx) {
928939
auto module = allModules[currentModuleIdx];
929940
auto discoveredModules =
930-
resolveDirectDependencies(instance, module, *cache, ASTDelegate);
941+
resolveDirectDependencies(instance, module, cache, ASTDelegate);
931942
allModules.insert(discoveredModules.begin(), discoveredModules.end());
932943
}
933944

934945
// We have all explicit imports now, resolve cross import overlays.
935946
discoverCrosssImportOverlayDependencies(instance, mainModuleName,
936-
/*All transitive dependencies*/allModules.getArrayRef().slice(1), *cache,
947+
/*All transitive dependencies*/allModules.getArrayRef().slice(1), cache,
937948
ASTDelegate, [&](ModuleDependencyID id) {
938949
allModules.insert(id);
939950
});
940951

941952
// Dignose cycle in dependency graph.
942-
if (diagnoseCycle(instance, *cache, /*MainModule*/allModules.front(), ASTDelegate))
953+
if (diagnoseCycle(instance, cache, /*MainModule*/allModules.front(), ASTDelegate))
943954
return true;
944955

945956
// Write out the JSON description.
946-
writeJSON(out, instance, *cache, ASTDelegate, allModules.getArrayRef());
957+
writeJSON(out, instance, cache, ASTDelegate, allModules.getArrayRef());
947958

948959
// Update the dependency tracker.
949960
if (auto depTracker = instance.getDependencyTracker()) {
950961
for (auto module : allModules) {
951-
auto deps = cache->findDependencies(module.first, module.second);
962+
auto deps = cache.findDependencies(module.first, module.second);
952963
if (!deps)
953964
continue;
954965

unittests/SwiftScan/ModuleDeps.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export *\n\
160160
" -I " + CHeadersDirPath +
161161
" -I " + StdLibDir.str().str() +
162162
" -I " + ShimsLibDir.str().str();
163-
std::string deps = ScannerTool.getFullDependencies(Command.c_str(),
163+
llvm::ErrorOr<std::string> deps = ScannerTool.getFullDependencies(Command.c_str(),
164164
{TestPathStr.c_str()}, {});
165165

166166
// TODO: Output/verify dependency graph correctness

0 commit comments

Comments
 (0)