Skip to content

Commit 8edb812

Browse files
authored
Merge pull request swiftlang#33087 from nkcsgexi/cross-import-overlay-resolver
DependenciesScanner: refactor cross import overlay resolver to a standalone function. NFC
2 parents 4787768 + 056f003 commit 8edb812

File tree

10 files changed

+153
-62
lines changed

10 files changed

+153
-62
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class ModuleDependencies {
255255

256256
/// Add a dependency on the given module, if it was not already in the set.
257257
void addModuleDependency(StringRef module,
258-
llvm::StringSet<> &alreadyAddedModules);
258+
llvm::StringSet<> *alreadyAddedModules = nullptr);
259259

260260
/// Add all of the module dependencies for the imports in the given source
261261
/// file to the set of module dependencies.

lib/AST/ModuleDependencies.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ ModuleDependencies::getAsClangModule() const {
3737
}
3838

3939
void ModuleDependencies::addModuleDependency(
40-
StringRef module, llvm::StringSet<> &alreadyAddedModules) {
41-
if (alreadyAddedModules.insert(module).second)
40+
StringRef module, llvm::StringSet<> *alreadyAddedModules) {
41+
if (!alreadyAddedModules || alreadyAddedModules->insert(module).second)
4242
storage->moduleDependencies.push_back(module.str());
4343
}
4444

@@ -53,7 +53,7 @@ void ModuleDependencies::addModuleDependencies(
5353
continue;
5454

5555
addModuleDependency(importDecl->getModulePath().front().Item.str(),
56-
alreadyAddedModules);
56+
&alreadyAddedModules);
5757
}
5858

5959
auto fileName = sf.getFilename();

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ void ClangImporter::recordModuleDependencies(
265265
swiftArgs,
266266
fileDeps);
267267
for (const auto &moduleName : clangModuleDep.ClangModuleDeps) {
268-
dependencies.addModuleDependency(moduleName.ModuleName, alreadyAddedModules);
268+
dependencies.addModuleDependency(moduleName.ModuleName, &alreadyAddedModules);
269269
}
270270

271271
cache.recordDependencies(clangModuleDep.ModuleName,

lib/FrontendTool/ScanDependencies.cpp

Lines changed: 101 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -62,23 +62,12 @@ static void findAllImportedClangModules(ASTContext &ctx, StringRef moduleName,
6262
/// Resolve the direct dependencies of the given module.
6363
static std::vector<ModuleDependencyID> resolveDirectDependencies(
6464
CompilerInstance &instance, ModuleDependencyID module,
65-
ModuleDependenciesCache &cache) {
65+
ModuleDependenciesCache &cache,
66+
InterfaceSubContextDelegate &ASTDelegate) {
6667
auto &ctx = instance.getASTContext();
6768
auto knownDependencies = *cache.findDependencies(module.first, module.second);
6869
auto isSwift = knownDependencies.isSwiftModule();
69-
auto ModuleCachePath = getModuleCachePathFromClang(ctx
70-
.getClangModuleLoader()->getClangInstance());
71-
auto &FEOpts = instance.getInvocation().getFrontendOptions();
72-
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
73-
InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags,
74-
ctx.SearchPathOpts, ctx.LangOpts,
75-
LoaderOpts,
76-
ctx.getClangModuleLoader(),
77-
/*buildModuleCacheDirIfAbsent*/false,
78-
ModuleCachePath,
79-
FEOpts.PrebuiltModuleCachePath,
80-
FEOpts.SerializeModuleInterfaceDependencyHashes,
81-
FEOpts.shouldTrackSystemDependencies());
70+
8271
// Find the dependencies of every module this module directly depends on.
8372
std::vector<ModuleDependencyID> result;
8473
for (auto dependsOn : knownDependencies.getModuleDependencies()) {
@@ -138,39 +127,75 @@ static std::vector<ModuleDependencyID> resolveDirectDependencies(
138127
}
139128
}
140129
}
141-
// Only resolve cross-import overlays when this is the main module.
142-
// For other modules, these overlays are explicitly written.
143-
bool isMainModule =
144-
instance.getMainModule()->getName().str() == module.first &&
145-
module.second == ModuleDependenciesKind::Swift;
146-
if (isMainModule) {
147-
// Modules explicitly imported. Only these can be secondary module.
148-
std::vector<ModuleDependencyID> explicitImports = result;
149-
for (unsigned I = 0; I != result.size(); ++I) {
150-
auto dep = result[I];
151-
auto moduleName = dep.first;
152-
auto dependencies = *cache.findDependencies(moduleName, dep.second);
153-
// Collect a map from secondary module name to cross-import overlay names.
154-
auto overlayMap = dependencies.collectCrossImportOverlayNames(
155-
instance.getASTContext(), moduleName);
156-
if (overlayMap.empty())
157-
continue;
158-
std::for_each(explicitImports.begin(), explicitImports.end(),
159-
[&](ModuleDependencyID Id) {
160-
// check if any explicitly imported modules can serve as a secondary
161-
// module, and add the overlay names to the dependencies list.
162-
for (auto overlayName: overlayMap[Id.first]) {
163-
if (auto found = ctx.getModuleDependencies(overlayName.str(),
164-
/*onlyClangModule=*/false,
165-
cache,
166-
ASTDelegate)) {
167-
result.emplace_back(overlayName.str(), found->getKind());
168-
}
130+
return result;
131+
}
132+
133+
static void discoverCrosssImportOverlayDependencies(
134+
CompilerInstance &instance, StringRef mainModuleName,
135+
ArrayRef<ModuleDependencyID> allDependencies,
136+
ModuleDependenciesCache &cache, InterfaceSubContextDelegate &ASTDelegate,
137+
llvm::function_ref<void(ModuleDependencyID)> action) {
138+
// Modules explicitly imported. Only these can be secondary module.
139+
llvm::SetVector<Identifier> newOverlays;
140+
for (auto dep: allDependencies) {
141+
auto moduleName = dep.first;
142+
auto dependencies = *cache.findDependencies(moduleName, dep.second);
143+
// Collect a map from secondary module name to cross-import overlay names.
144+
auto overlayMap = dependencies.collectCrossImportOverlayNames(
145+
instance.getASTContext(), moduleName);
146+
if (overlayMap.empty())
147+
continue;
148+
std::for_each(allDependencies.begin(), allDependencies.end(),
149+
[&](ModuleDependencyID Id) {
150+
// check if any explicitly imported modules can serve as a secondary
151+
// module, and add the overlay names to the dependencies list.
152+
for (auto overlayName: overlayMap[Id.first]) {
153+
if (std::find_if(allDependencies.begin(), allDependencies.end(),
154+
[&](ModuleDependencyID Id) { return Id.first == overlayName.str(); })
155+
== allDependencies.end()) {
156+
newOverlays.insert(overlayName);
169157
}
170-
});
171-
}
158+
}
159+
});
172160
}
173-
return result;
161+
// No new cross-import overlays are found, return.
162+
if (newOverlays.empty())
163+
return;
164+
// Construct a dummy main to resolve the newly discovered cross import overlays.
165+
StringRef dummyMainName = "DummyMainModuleForResolvingCrossImportOverlays";
166+
auto dummyMainDependencies = ModuleDependencies::forMainSwiftModule({});
167+
168+
// Update main module's dependencies to include these new overlays.
169+
auto mainDep = *cache.findDependencies(mainModuleName, ModuleDependenciesKind::Swift);
170+
std::for_each(newOverlays.begin(), newOverlays.end(), [&](Identifier modName) {
171+
dummyMainDependencies.addModuleDependency(modName.str());
172+
mainDep.addModuleDependency(modName.str());
173+
});
174+
cache.updateDependencies({mainModuleName, ModuleDependenciesKind::Swift}, mainDep);
175+
176+
// Record the dummy main module's direct dependencies. The dummy main module
177+
// only directly depend on these newly discovered overlay modules.
178+
cache.recordDependencies(dummyMainName, dummyMainDependencies,
179+
ModuleDependenciesKind::Swift);
180+
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
181+
std::set<ModuleDependencyID>> allModules;
182+
183+
// Seed the all module list from the dummpy main module.
184+
allModules.insert({dummyMainName.str(), dummyMainDependencies.getKind()});
185+
186+
// Explore the dependencies of every module.
187+
for (unsigned currentModuleIdx = 0;
188+
currentModuleIdx < allModules.size();
189+
++currentModuleIdx) {
190+
auto module = allModules[currentModuleIdx];
191+
auto discoveredModules = resolveDirectDependencies(instance, module,
192+
cache, ASTDelegate);
193+
allModules.insert(discoveredModules.begin(), discoveredModules.end());
194+
}
195+
// Report any discovered modules to the clients, which include all overlays
196+
// and their dependencies.
197+
std::for_each(/* +1 to exclude dummy main*/allModules.begin() + 1,
198+
allModules.end(), action);
174199
}
175200

176201
/// Write a single JSON field.
@@ -259,6 +284,7 @@ namespace {
259284
static void writeJSON(llvm::raw_ostream &out,
260285
CompilerInstance &instance,
261286
ModuleDependenciesCache &cache,
287+
InterfaceSubContextDelegate &ASTDelegate,
262288
ArrayRef<ModuleDependencyID> allModules) {
263289
// Write out a JSON description of all of the dependencies.
264290
out << "{\n";
@@ -277,7 +303,8 @@ static void writeJSON(llvm::raw_ostream &out,
277303
};
278304
for (const auto &module : allModules) {
279305
auto directDependencies = resolveDirectDependencies(
280-
instance, ModuleDependencyID(module.first, module.second), cache);
306+
instance, ModuleDependencyID(module.first, module.second), cache,
307+
ASTDelegate);
281308

282309
// Grab the completed module dependencies.
283310
auto moduleDeps = *cache.findDependencies(module.first, module.second);
@@ -469,18 +496,18 @@ bool swift::scanDependencies(CompilerInstance &instance) {
469496
break;
470497

471498
case ImplicitStdlibKind::Stdlib:
472-
mainDependencies.addModuleDependency("Swift", alreadyAddedModules);
499+
mainDependencies.addModuleDependency("Swift", &alreadyAddedModules);
473500
break;
474501
}
475502

476503
// Add any implicit module names.
477504
for (const auto &moduleName : importInfo.ModuleNames) {
478-
mainDependencies.addModuleDependency(moduleName.str(), alreadyAddedModules);
505+
mainDependencies.addModuleDependency(moduleName.str(), &alreadyAddedModules);
479506
}
480507

481508
// Already-loaded, implicitly imported module names.
482509
for (const auto &module : importInfo.AdditionalModules) {
483-
mainDependencies.addModuleDependency(module.first->getNameStr(), alreadyAddedModules);
510+
mainDependencies.addModuleDependency(module.first->getNameStr(), &alreadyAddedModules);
484511
}
485512

486513
// Add the bridging header.
@@ -492,7 +519,7 @@ bool swift::scanDependencies(CompilerInstance &instance) {
492519
// add a dependency with the same name to trigger the search.
493520
if (importInfo.ShouldImportUnderlyingModule) {
494521
mainDependencies.addModuleDependency(mainModule->getName().str(),
495-
alreadyAddedModules);
522+
&alreadyAddedModules);
496523
}
497524
}
498525

@@ -508,18 +535,40 @@ bool swift::scanDependencies(CompilerInstance &instance) {
508535
cache.recordDependencies(mainModuleName, std::move(mainDependencies),
509536
ModuleDependenciesKind::Swift);
510537

538+
auto &ctx = instance.getASTContext();
539+
auto ModuleCachePath = getModuleCachePathFromClang(ctx
540+
.getClangModuleLoader()->getClangInstance());
541+
auto &FEOpts = instance.getInvocation().getFrontendOptions();
542+
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
543+
InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags,
544+
ctx.SearchPathOpts, ctx.LangOpts,
545+
LoaderOpts,
546+
ctx.getClangModuleLoader(),
547+
/*buildModuleCacheDirIfAbsent*/false,
548+
ModuleCachePath,
549+
FEOpts.PrebuiltModuleCachePath,
550+
FEOpts.SerializeModuleInterfaceDependencyHashes,
551+
FEOpts.shouldTrackSystemDependencies());
552+
511553
// Explore the dependencies of every module.
512554
for (unsigned currentModuleIdx = 0;
513555
currentModuleIdx < allModules.size();
514556
++currentModuleIdx) {
515557
auto module = allModules[currentModuleIdx];
516558
auto discoveredModules =
517-
resolveDirectDependencies(instance, module, cache);
559+
resolveDirectDependencies(instance, module, cache, ASTDelegate);
518560
allModules.insert(discoveredModules.begin(), discoveredModules.end());
519561
}
520562

563+
// We have all explicit imports now, resolve cross import overlays.
564+
discoverCrosssImportOverlayDependencies(instance, mainModuleName,
565+
/*All transitive dependencies*/allModules.getArrayRef().slice(1), cache,
566+
ASTDelegate, [&](ModuleDependencyID id) {
567+
allModules.insert(id);
568+
});
569+
521570
// Write out the JSON description.
522-
writeJSON(out, instance, cache, allModules.getArrayRef());
571+
writeJSON(out, instance, cache, ASTDelegate, allModules.getArrayRef());
523572

524573
// Update the dependency tracker.
525574
if (auto depTracker = instance.getDependencyTracker()) {

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ llvm::ErrorOr<ModuleDependencies> SerializedModuleLoaderBase::scanModuleFile(
410410
if (dotPos != std::string::npos)
411411
moduleName = moduleName.slice(0, dotPos);
412412

413-
dependencies.addModuleDependency(moduleName, addedModuleNames);
413+
dependencies.addModuleDependency(moduleName, &addedModuleNames);
414414
}
415415

416416
return std::move(dependencies);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name EWrapper
3+
import Swift
4+
import E
5+
public func funcEWrapper() { }
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// swift-interface-format-version: 1.0
22
// swift-module-flags: -module-name SubE
33
import Swift
4-
import E
54
public func funcSubE() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name SubEWrapper
3+
import Swift
4+
import SubE
5+
public func funcSubEWrapper() { }

test/ScanDependencies/module_deps.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ import SubE
5252
// CHECK-NEXT: "swift": "SwiftOnoneSupport"
5353
// CHECK-NEXT: }
5454
// CHECK-NEXT: {
55-
// CHECK-NEXT: "swift": "F"
55+
// CHECK-NEXT: "swift": "_cross_import_E"
5656
// CHECK-NEXT: }
5757
// CHECK-NEXT: {
58-
// CHECK-NEXT: "swift": "A"
58+
// CHECK-NEXT: "swift": "F"
5959
// CHECK-NEXT: }
6060
// CHECK-NEXT: {
61-
// CHECK-NEXT: "swift": "_cross_import_E"
61+
// CHECK-NEXT: "swift": "A"
6262
// CHECK-NEXT: }
6363
// CHECK-NEXT: ],
6464

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: mkdir -p %t/clang-module-cache
3+
// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -Xcc -Xclang -Xcc -fno-implicit-modules
4+
5+
// Check the contents of the JSON output
6+
// RUN: %FileCheck %s < %t/deps.json
7+
8+
// REQUIRES: executable_test
9+
// REQUIRES: objc_interop
10+
11+
import EWrapper
12+
import SubEWrapper
13+
14+
// CHECK: "directDependencies": [
15+
// CHECK-NEXT: {
16+
// CHECK-NEXT: "swift": "EWrapper"
17+
// CHECK-NEXT: },
18+
// CHECK-NEXT: {
19+
// CHECK-NEXT: "swift": "SubEWrapper"
20+
// CHECK-NEXT: },
21+
// CHECK-NEXT: {
22+
// CHECK-NEXT: "swift": "Swift"
23+
// CHECK-NEXT: },
24+
// CHECK-NEXT: {
25+
// CHECK-NEXT: "swift": "SwiftOnoneSupport"
26+
// CHECK-NEXT: },
27+
// CHECK-NEXT: {
28+
// CHECK-NEXT: "swift": "_cross_import_E"
29+
// CHECK-NEXT: },
30+
// CHECK-NEXT: {
31+
// CHECK-NEXT: "swift": "F"
32+
// CHECK-NEXT: }
33+
// CHECK-NEXT: ],

0 commit comments

Comments
 (0)