@@ -532,42 +532,141 @@ ModuleDependencyScanner::getNamedSwiftModuleDependencyInfo(
532
532
return cache.findDependency (moduleName);
533
533
}
534
534
535
+ // / For the dependency set of the main module, discover all
536
+ // / cross-import overlays and their corresponding '.swiftcrossimport'
537
+ // / files. Cross-import overlay dependencies are required when
538
+ // / the two constituent modules are imported *from the same source file*,
539
+ // / directly or indirectly.
540
+ // /
541
+ // / Given a complete module dependency graph in this stage of the scan,
542
+ // / the algorithm for discovering cross-import overlays is:
543
+ // / 1. For each source file of the module under scan construct a
544
+ // / set of module dependnecies only reachable from this source file.
545
+ // / 2. For each module set constructed in (1), perform pair-wise lookup
546
+ // / of cross import files for each pair of modules in the set.
547
+ // /
548
+ // / Notably, if for some pair of modules 'A' and 'B' there exists
549
+ // / a cross-import overlay '_A_B', and these two modules are not reachable
550
+ // / from any single source file via direct or indirect imports, then
551
+ // / the cross-import overlay module is not required for compilation.
535
552
static void discoverCrossImportOverlayFiles (
536
- StringRef mainModuleName, ArrayRef<ModuleDependencyID> allDependencies,
537
- ModuleDependenciesCache &cache, ASTContext &scanASTContext,
538
- llvm::SetVector<Identifier> &newOverlays,
553
+ StringRef mainModuleName, ModuleDependenciesCache &cache,
554
+ ASTContext &scanASTContext, llvm::SetVector<Identifier> &newOverlays,
539
555
std::vector<std::pair<std::string, std::string>> &overlayFiles) {
540
- for (auto moduleID : allDependencies) {
541
- auto moduleName = moduleID.ModuleName ;
542
- // Do not look for overlays of main module under scan
543
- if (moduleName == mainModuleName)
544
- continue ;
556
+ auto mainModuleInfo = cache.findKnownDependency (ModuleDependencyID{
557
+ mainModuleName.str (), ModuleDependencyKind::SwiftSource});
558
+
559
+ llvm::StringMap<ModuleDependencyIDSet> perSourceFileDependencies;
560
+ const ModuleDependencyIDSet directSwiftDepsSet{
561
+ mainModuleInfo.getImportedSwiftDependencies ().begin (),
562
+ mainModuleInfo.getImportedSwiftDependencies ().end ()};
563
+ const ModuleDependencyIDSet directClangDepsSet{
564
+ mainModuleInfo.getImportedClangDependencies ().begin (),
565
+ mainModuleInfo.getImportedClangDependencies ().end ()};
566
+
567
+ // A utility to map an import identifier to one of the
568
+ // known resolved module dependencies
569
+ auto getModuleIDForImportIdentifier =
570
+ [directSwiftDepsSet, directClangDepsSet](
571
+ const std::string &importIdentifierStr) -> ModuleDependencyID {
572
+ if (auto textualDepIt = directSwiftDepsSet.find (
573
+ {importIdentifierStr, ModuleDependencyKind::SwiftInterface});
574
+ textualDepIt != directSwiftDepsSet.end ())
575
+ return *textualDepIt;
576
+ else if (auto binaryDepIt = directSwiftDepsSet.find (
577
+ {importIdentifierStr, ModuleDependencyKind::SwiftBinary});
578
+ binaryDepIt != directSwiftDepsSet.end ())
579
+ return *binaryDepIt;
580
+ else if (auto clangDepIt = directClangDepsSet.find (
581
+ {importIdentifierStr, ModuleDependencyKind::Clang});
582
+ clangDepIt != directClangDepsSet.end ())
583
+ return *clangDepIt;
584
+ llvm_unreachable (
585
+ " Unresolved import during cross-import overlay resolution" );
586
+ };
545
587
546
- auto dependencies = cache.findDependency (moduleName, moduleID.Kind ).value ();
547
- // Collect a map from secondary module name to cross-import overlay names.
548
- auto overlayMap = dependencies->collectCrossImportOverlayNames (
549
- scanASTContext, moduleName, overlayFiles);
550
- if (overlayMap.empty ())
551
- continue ;
552
- for (const auto &dependencyId : allDependencies) {
553
- auto moduleName = dependencyId.ModuleName ;
554
- // Do not look for overlays of main module under scan
555
- if (moduleName == mainModuleName)
556
- continue ;
557
- // check if any explicitly imported modules can serve as a
558
- // secondary module, and add the overlay names to the
559
- // dependencies list.
560
- for (auto overlayName : overlayMap[moduleName]) {
561
- if (overlayName.str () != mainModuleName &&
562
- std::find_if (allDependencies.begin (), allDependencies.end (),
563
- [&](ModuleDependencyID Id) {
564
- return moduleName == overlayName.str ();
565
- }) == allDependencies.end ()) {
566
- newOverlays.insert (overlayName);
588
+ // Collect the set of directly-imported module dependencies
589
+ // for each source file in the source module under scan.
590
+ for (const auto &import : mainModuleInfo.getModuleImports ()) {
591
+ auto importResolvedModuleID =
592
+ getModuleIDForImportIdentifier (import .importIdentifier );
593
+ for (const auto &importLocation : import .importLocations )
594
+ perSourceFileDependencies[importLocation.bufferIdentifier ].insert (
595
+ importResolvedModuleID);
596
+ }
597
+
598
+ // For each source-file, build a set of module dependencies of the
599
+ // module under scan corresponding to a sub-graph of modules only reachable
600
+ // from this source file's direct imports.
601
+ for (auto &keyValPair : perSourceFileDependencies) {
602
+ const auto &bufferIdentifier = keyValPair.getKey ();
603
+ auto &directDependencyIDs = keyValPair.second ;
604
+ SmallVector<ModuleDependencyID, 8 > worklist{directDependencyIDs.begin (),
605
+ directDependencyIDs.end ()};
606
+ while (!worklist.empty ()) {
607
+ auto moduleID = worklist.pop_back_val ();
608
+ perSourceFileDependencies[bufferIdentifier].insert (moduleID);
609
+ if (isSwiftDependencyKind (moduleID.Kind )) {
610
+ for (const auto &directSwiftDepID :
611
+ cache.getImportedSwiftDependencies (moduleID)) {
612
+ if (perSourceFileDependencies[bufferIdentifier].count (directSwiftDepID))
613
+ continue ;
614
+ worklist.push_back (directSwiftDepID);
567
615
}
568
616
}
617
+ for (const auto &directClangDepID :
618
+ cache.getImportedClangDependencies (moduleID)) {
619
+ if (perSourceFileDependencies[bufferIdentifier].count (directClangDepID))
620
+ continue ;
621
+ worklist.push_back (directClangDepID);
622
+ }
569
623
}
570
624
}
625
+
626
+ // Within a provided set of module dependencies reachable via
627
+ // direct imports from a given file, determine the available and required
628
+ // cross-import overlays.
629
+ auto discoverCrossImportOverlayFilesForModuleSet =
630
+ [&mainModuleName, &cache, &scanASTContext, &newOverlays,
631
+ &overlayFiles](const ModuleDependencyIDSet &inputDependencies) {
632
+ for (auto moduleID : inputDependencies) {
633
+ auto moduleName = moduleID.ModuleName ;
634
+ // Do not look for overlays of main module under scan
635
+ if (moduleName == mainModuleName)
636
+ continue ;
637
+
638
+ auto dependencies =
639
+ cache.findDependency (moduleName, moduleID.Kind ).value ();
640
+ // Collect a map from secondary module name to cross-import overlay
641
+ // names.
642
+ auto overlayMap = dependencies->collectCrossImportOverlayNames (
643
+ scanASTContext, moduleName, overlayFiles);
644
+ if (overlayMap.empty ())
645
+ continue ;
646
+ for (const auto &dependencyId : inputDependencies) {
647
+ auto moduleName = dependencyId.ModuleName ;
648
+ // Do not look for overlays of main module under scan
649
+ if (moduleName == mainModuleName)
650
+ continue ;
651
+ // check if any explicitly imported modules can serve as a
652
+ // secondary module, and add the overlay names to the
653
+ // dependencies list.
654
+ for (auto overlayName : overlayMap[moduleName]) {
655
+ if (overlayName.str () != mainModuleName &&
656
+ std::find_if (inputDependencies.begin (),
657
+ inputDependencies.end (),
658
+ [&](ModuleDependencyID Id) {
659
+ return moduleName == overlayName.str ();
660
+ }) == inputDependencies.end ()) {
661
+ newOverlays.insert (overlayName);
662
+ }
663
+ }
664
+ }
665
+ }
666
+ };
667
+
668
+ for (const auto &keyValPair : perSourceFileDependencies)
669
+ discoverCrossImportOverlayFilesForModuleSet (keyValPair.second );
571
670
}
572
671
573
672
std::vector<ModuleDependencyID>
@@ -598,8 +697,8 @@ ModuleDependencyScanner::performDependencyScan(
598
697
// binary Swift modules already encode their dependencies on cross-import overlays
599
698
// with explicit imports.
600
699
if (ScanCompilerInvocation.getLangOptions ().EnableCrossImportOverlays )
601
- discoverCrossImportOverlayDependencies (
602
- rootModuleID.ModuleName , allModules. getArrayRef (). slice ( 1 ), cache,
700
+ resolveCrossImportOverlayDependencies (
701
+ rootModuleID.ModuleName , cache,
603
702
[&](ModuleDependencyID id) { allModules.insert (id); });
604
703
605
704
return allModules.takeVector ();
@@ -1154,15 +1253,15 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
1154
1253
cache.setSwiftOverlayDependencies (moduleID, swiftOverlayDependencies.getArrayRef ());
1155
1254
}
1156
1255
1157
- void ModuleDependencyScanner::discoverCrossImportOverlayDependencies (
1158
- StringRef mainModuleName, ArrayRef<ModuleDependencyID> allDependencies,
1256
+ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies (
1257
+ StringRef mainModuleName,
1159
1258
ModuleDependenciesCache &cache,
1160
1259
llvm::function_ref<void (ModuleDependencyID)> action) {
1161
1260
// Modules explicitly imported. Only these can be secondary module.
1162
1261
llvm::SetVector<Identifier> newOverlays;
1163
1262
std::vector<std::pair<std::string, std::string>> overlayFiles;
1164
- discoverCrossImportOverlayFiles (mainModuleName, allDependencies, cache ,
1165
- ScanASTContext, newOverlays, overlayFiles);
1263
+ discoverCrossImportOverlayFiles (mainModuleName, cache, ScanASTContext ,
1264
+ newOverlays, overlayFiles);
1166
1265
1167
1266
// No new cross-import overlays are found, return.
1168
1267
if (newOverlays.empty ())
@@ -1184,11 +1283,10 @@ void ModuleDependencyScanner::discoverCrossImportOverlayDependencies(
1184
1283
1185
1284
// Record the dummy main module's direct dependencies. The dummy main module
1186
1285
// only directly depend on these newly discovered overlay modules.
1187
- if (cache.findDependency (dummyMainName, ModuleDependencyKind::SwiftSource)) {
1286
+ if (cache.findDependency (dummyMainID))
1188
1287
cache.updateDependency (dummyMainID, dummyMainDependencies);
1189
- } else {
1288
+ else
1190
1289
cache.recordDependency (dummyMainName, dummyMainDependencies);
1191
- }
1192
1290
1193
1291
ModuleDependencyIDSetVector allModules =
1194
1292
resolveImportedModuleDependencies (dummyMainID, cache);
0 commit comments