@@ -561,42 +561,141 @@ ModuleDependencyScanner::getNamedSwiftModuleDependencyInfo(
561
561
return cache.findDependency (moduleName);
562
562
}
563
563
564
+ // / For the dependency set of the main module, discover all
565
+ // / cross-import overlays and their corresponding '.swiftcrossimport'
566
+ // / files. Cross-import overlay dependencies are required when
567
+ // / the two constituent modules are imported *from the same source file*,
568
+ // / directly or indirectly.
569
+ // /
570
+ // / Given a complete module dependency graph in this stage of the scan,
571
+ // / the algorithm for discovering cross-import overlays is:
572
+ // / 1. For each source file of the module under scan construct a
573
+ // / set of module dependnecies only reachable from this source file.
574
+ // / 2. For each module set constructed in (1), perform pair-wise lookup
575
+ // / of cross import files for each pair of modules in the set.
576
+ // /
577
+ // / Notably, if for some pair of modules 'A' and 'B' there exists
578
+ // / a cross-import overlay '_A_B', and these two modules are not reachable
579
+ // / from any single source file via direct or indirect imports, then
580
+ // / the cross-import overlay module is not required for compilation.
564
581
static void discoverCrossImportOverlayFiles (
565
- StringRef mainModuleName, ArrayRef<ModuleDependencyID> allDependencies,
566
- ModuleDependenciesCache &cache, ASTContext &scanASTContext,
567
- llvm::SetVector<Identifier> &newOverlays,
582
+ StringRef mainModuleName, ModuleDependenciesCache &cache,
583
+ ASTContext &scanASTContext, llvm::SetVector<Identifier> &newOverlays,
568
584
std::vector<std::pair<std::string, std::string>> &overlayFiles) {
569
- for (auto moduleID : allDependencies) {
570
- auto moduleName = moduleID.ModuleName ;
571
- // Do not look for overlays of main module under scan
572
- if (moduleName == mainModuleName)
573
- continue ;
585
+ auto mainModuleInfo = cache.findKnownDependency (ModuleDependencyID{
586
+ mainModuleName.str (), ModuleDependencyKind::SwiftSource});
587
+
588
+ llvm::StringMap<ModuleDependencyIDSet> perSourceFileDependencies;
589
+ const ModuleDependencyIDSet directSwiftDepsSet{
590
+ mainModuleInfo.getImportedSwiftDependencies ().begin (),
591
+ mainModuleInfo.getImportedSwiftDependencies ().end ()};
592
+ const ModuleDependencyIDSet directClangDepsSet{
593
+ mainModuleInfo.getImportedClangDependencies ().begin (),
594
+ mainModuleInfo.getImportedClangDependencies ().end ()};
595
+
596
+ // A utility to map an import identifier to one of the
597
+ // known resolved module dependencies
598
+ auto getModuleIDForImportIdentifier =
599
+ [directSwiftDepsSet, directClangDepsSet](
600
+ const std::string &importIdentifierStr) -> ModuleDependencyID {
601
+ if (auto textualDepIt = directSwiftDepsSet.find (
602
+ {importIdentifierStr, ModuleDependencyKind::SwiftInterface});
603
+ textualDepIt != directSwiftDepsSet.end ())
604
+ return *textualDepIt;
605
+ else if (auto binaryDepIt = directSwiftDepsSet.find (
606
+ {importIdentifierStr, ModuleDependencyKind::SwiftBinary});
607
+ binaryDepIt != directSwiftDepsSet.end ())
608
+ return *binaryDepIt;
609
+ else if (auto clangDepIt = directClangDepsSet.find (
610
+ {importIdentifierStr, ModuleDependencyKind::Clang});
611
+ clangDepIt != directClangDepsSet.end ())
612
+ return *clangDepIt;
613
+ llvm_unreachable (
614
+ " Unresolved import during cross-import overlay resolution" );
615
+ };
574
616
575
- auto dependencies = cache.findDependency (moduleName, moduleID.Kind ).value ();
576
- // Collect a map from secondary module name to cross-import overlay names.
577
- auto overlayMap = dependencies->collectCrossImportOverlayNames (
578
- scanASTContext, moduleName, overlayFiles);
579
- if (overlayMap.empty ())
580
- continue ;
581
- for (const auto &dependencyId : allDependencies) {
582
- auto moduleName = dependencyId.ModuleName ;
583
- // Do not look for overlays of main module under scan
584
- if (moduleName == mainModuleName)
585
- continue ;
586
- // check if any explicitly imported modules can serve as a
587
- // secondary module, and add the overlay names to the
588
- // dependencies list.
589
- for (auto overlayName : overlayMap[moduleName]) {
590
- if (overlayName.str () != mainModuleName &&
591
- std::find_if (allDependencies.begin (), allDependencies.end (),
592
- [&](ModuleDependencyID Id) {
593
- return moduleName == overlayName.str ();
594
- }) == allDependencies.end ()) {
595
- newOverlays.insert (overlayName);
617
+ // Collect the set of directly-imported module dependencies
618
+ // for each source file in the source module under scan.
619
+ for (const auto &import : mainModuleInfo.getModuleImports ()) {
620
+ auto importResolvedModuleID =
621
+ getModuleIDForImportIdentifier (import.importIdentifier );
622
+ for (const auto &importLocation : import.importLocations )
623
+ perSourceFileDependencies[importLocation.bufferIdentifier ].insert (
624
+ importResolvedModuleID);
625
+ }
626
+
627
+ // For each source-file, build a set of module dependencies of the
628
+ // module under scan corresponding to a sub-graph of modules only reachable
629
+ // from this source file's direct imports.
630
+ for (auto &keyValPair : perSourceFileDependencies) {
631
+ const auto &bufferIdentifier = keyValPair.getKey ();
632
+ auto &directDependencyIDs = keyValPair.second ;
633
+ SmallVector<ModuleDependencyID, 8 > worklist{directDependencyIDs.begin (),
634
+ directDependencyIDs.end ()};
635
+ while (!worklist.empty ()) {
636
+ auto moduleID = worklist.pop_back_val ();
637
+ perSourceFileDependencies[bufferIdentifier].insert (moduleID);
638
+ if (isSwiftDependencyKind (moduleID.Kind )) {
639
+ for (const auto &directSwiftDepID :
640
+ cache.getImportedSwiftDependencies (moduleID)) {
641
+ if (perSourceFileDependencies[bufferIdentifier].count (directSwiftDepID))
642
+ continue ;
643
+ worklist.push_back (directSwiftDepID);
596
644
}
597
645
}
646
+ for (const auto &directClangDepID :
647
+ cache.getImportedClangDependencies (moduleID)) {
648
+ if (perSourceFileDependencies[bufferIdentifier].count (directClangDepID))
649
+ continue ;
650
+ worklist.push_back (directClangDepID);
651
+ }
598
652
}
599
653
}
654
+
655
+ // Within a provided set of module dependencies reachable via
656
+ // direct imports from a given file, determine the available and required
657
+ // cross-import overlays.
658
+ auto discoverCrossImportOverlayFilesForModuleSet =
659
+ [&mainModuleName, &cache, &scanASTContext, &newOverlays,
660
+ &overlayFiles](const ModuleDependencyIDSet &inputDependencies) {
661
+ for (auto moduleID : inputDependencies) {
662
+ auto moduleName = moduleID.ModuleName ;
663
+ // Do not look for overlays of main module under scan
664
+ if (moduleName == mainModuleName)
665
+ continue ;
666
+
667
+ auto dependencies =
668
+ cache.findDependency (moduleName, moduleID.Kind ).value ();
669
+ // Collect a map from secondary module name to cross-import overlay
670
+ // names.
671
+ auto overlayMap = dependencies->collectCrossImportOverlayNames (
672
+ scanASTContext, moduleName, overlayFiles);
673
+ if (overlayMap.empty ())
674
+ continue ;
675
+ for (const auto &dependencyId : inputDependencies) {
676
+ auto moduleName = dependencyId.ModuleName ;
677
+ // Do not look for overlays of main module under scan
678
+ if (moduleName == mainModuleName)
679
+ continue ;
680
+ // check if any explicitly imported modules can serve as a
681
+ // secondary module, and add the overlay names to the
682
+ // dependencies list.
683
+ for (auto overlayName : overlayMap[moduleName]) {
684
+ if (overlayName.str () != mainModuleName &&
685
+ std::find_if (inputDependencies.begin (),
686
+ inputDependencies.end (),
687
+ [&](ModuleDependencyID Id) {
688
+ return moduleName == overlayName.str ();
689
+ }) == inputDependencies.end ()) {
690
+ newOverlays.insert (overlayName);
691
+ }
692
+ }
693
+ }
694
+ }
695
+ };
696
+
697
+ for (const auto &keyValPair : perSourceFileDependencies)
698
+ discoverCrossImportOverlayFilesForModuleSet (keyValPair.second );
600
699
}
601
700
602
701
std::vector<ModuleDependencyID>
@@ -627,8 +726,8 @@ ModuleDependencyScanner::performDependencyScan(
627
726
// binary Swift modules already encode their dependencies on cross-import overlays
628
727
// with explicit imports.
629
728
if (ScanCompilerInvocation.getLangOptions ().EnableCrossImportOverlays )
630
- discoverCrossImportOverlayDependencies (
631
- rootModuleID.ModuleName , allModules. getArrayRef (). slice ( 1 ), cache,
729
+ resolveCrossImportOverlayDependencies (
730
+ rootModuleID.ModuleName , cache,
632
731
[&](ModuleDependencyID id) { allModules.insert (id); });
633
732
634
733
if (ScanCompilerInvocation.getSearchPathOptions ().BridgingHeaderChaining ) {
@@ -1230,15 +1329,15 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
1230
1329
cache.setSwiftOverlayDependencies (moduleID, swiftOverlayDependencies.getArrayRef ());
1231
1330
}
1232
1331
1233
- void ModuleDependencyScanner::discoverCrossImportOverlayDependencies (
1234
- StringRef mainModuleName, ArrayRef<ModuleDependencyID> allDependencies,
1332
+ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies (
1333
+ StringRef mainModuleName,
1235
1334
ModuleDependenciesCache &cache,
1236
1335
llvm::function_ref<void (ModuleDependencyID)> action) {
1237
1336
// Modules explicitly imported. Only these can be secondary module.
1238
1337
llvm::SetVector<Identifier> newOverlays;
1239
1338
std::vector<std::pair<std::string, std::string>> overlayFiles;
1240
- discoverCrossImportOverlayFiles (mainModuleName, allDependencies, cache ,
1241
- ScanASTContext, newOverlays, overlayFiles);
1339
+ discoverCrossImportOverlayFiles (mainModuleName, cache, ScanASTContext ,
1340
+ newOverlays, overlayFiles);
1242
1341
1243
1342
// No new cross-import overlays are found, return.
1244
1343
if (newOverlays.empty ())
@@ -1260,11 +1359,10 @@ void ModuleDependencyScanner::discoverCrossImportOverlayDependencies(
1260
1359
1261
1360
// Record the dummy main module's direct dependencies. The dummy main module
1262
1361
// only directly depend on these newly discovered overlay modules.
1263
- if (cache.findDependency (dummyMainName, ModuleDependencyKind::SwiftSource)) {
1362
+ if (cache.findDependency (dummyMainID))
1264
1363
cache.updateDependency (dummyMainID, dummyMainDependencies);
1265
- } else {
1364
+ else
1266
1365
cache.recordDependency (dummyMainName, dummyMainDependencies);
1267
- }
1268
1366
1269
1367
ModuleDependencyIDSetVector allModules =
1270
1368
resolveImportedModuleDependencies (dummyMainID, cache);
0 commit comments