@@ -561,42 +561,147 @@ 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
+ std::unordered_map<std::string, ModuleDependencyIDSetVector>
589
+ perSourceFileDependencies;
590
+ const ModuleDependencyIDSet directSwiftDepsSet{
591
+ mainModuleInfo.getImportedSwiftDependencies ().begin (),
592
+ mainModuleInfo.getImportedSwiftDependencies ().end ()};
593
+ const ModuleDependencyIDSet directClangDepsSet{
594
+ mainModuleInfo.getImportedClangDependencies ().begin (),
595
+ mainModuleInfo.getImportedClangDependencies ().end ()};
596
+
597
+ // A utility to map an import identifier to one of the
598
+ // known resolved module dependencies
599
+ auto getModuleIDForImportIdentifier =
600
+ [directSwiftDepsSet, directClangDepsSet](
601
+ const std::string &importIdentifierStr) -> ModuleDependencyID {
602
+ if (auto textualDepIt = directSwiftDepsSet.find (
603
+ {importIdentifierStr, ModuleDependencyKind::SwiftInterface});
604
+ textualDepIt != directSwiftDepsSet.end ())
605
+ return *textualDepIt;
606
+ else if (auto binaryDepIt = directSwiftDepsSet.find (
607
+ {importIdentifierStr, ModuleDependencyKind::SwiftBinary});
608
+ binaryDepIt != directSwiftDepsSet.end ())
609
+ return *binaryDepIt;
610
+ else if (auto clangDepIt = directClangDepsSet.find (
611
+ {importIdentifierStr, ModuleDependencyKind::Clang});
612
+ clangDepIt != directClangDepsSet.end ())
613
+ return *clangDepIt;
614
+ llvm_unreachable (
615
+ " Unresolved import during cross-import overlay resolution" );
616
+ };
574
617
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);
618
+ // Collect the set of directly-imported module dependencies
619
+ // for each source file in the source module under scan.
620
+ for (const auto &import : mainModuleInfo.getModuleImports ()) {
621
+ auto importResolvedModuleID =
622
+ getModuleIDForImportIdentifier (import .importIdentifier );
623
+ for (const auto &importLocation : import .importLocations ) {
624
+ if (perSourceFileDependencies.find (importLocation.bufferIdentifier ) ==
625
+ perSourceFileDependencies.end ())
626
+ perSourceFileDependencies.insert (
627
+ {importLocation.bufferIdentifier , ModuleDependencyIDSetVector ()});
628
+ perSourceFileDependencies.at (importLocation.bufferIdentifier )
629
+ .insert (importResolvedModuleID);
630
+ }
631
+ }
632
+
633
+ // For each source-file, build a set of module dependencies of the
634
+ // module under scan corresponding to a sub-graph of modules only reachable
635
+ // from this source file's direct imports.
636
+ for (auto &[sourceBufferIdentifierStr, dependencyIDs] :
637
+ perSourceFileDependencies) {
638
+ SmallVector<ModuleDependencyID, 8 > worklist{dependencyIDs.begin (),
639
+ dependencyIDs.end ()};
640
+ while (!worklist.empty ()) {
641
+ auto moduleID = worklist.pop_back_val ();
642
+ dependencyIDs.insert (moduleID);
643
+ if (isSwiftDependencyKind (moduleID.Kind )) {
644
+ for (const auto &directSwiftDepID :
645
+ cache.getImportedSwiftDependencies (moduleID)) {
646
+ if (dependencyIDs.contains (directSwiftDepID))
647
+ continue ;
648
+ worklist.push_back (directSwiftDepID);
596
649
}
597
650
}
651
+ for (const auto &directClangDepID :
652
+ cache.getImportedClangDependencies (moduleID)) {
653
+ if (dependencyIDs.contains (directClangDepID))
654
+ continue ;
655
+ worklist.push_back (directClangDepID);
656
+ }
598
657
}
599
658
}
659
+
660
+ // Within a provided set of module dependencies reachable via
661
+ // direct imports from a given file, determine the available and required
662
+ // cross-import overlays.
663
+ auto discoverCrossImportOverlayFilesForModuleSet =
664
+ [&mainModuleName, &cache, &scanASTContext, &newOverlays,
665
+ &overlayFiles](const ArrayRef<ModuleDependencyID> inputDependencies) {
666
+ for (auto moduleID : inputDependencies) {
667
+ auto moduleName = moduleID.ModuleName ;
668
+ // Do not look for overlays of main module under scan
669
+ if (moduleName == mainModuleName)
670
+ continue ;
671
+
672
+ auto dependencies =
673
+ cache.findDependency (moduleName, moduleID.Kind ).value ();
674
+ // Collect a map from secondary module name to cross-import overlay
675
+ // names.
676
+ auto overlayMap = dependencies->collectCrossImportOverlayNames (
677
+ scanASTContext, moduleName, overlayFiles);
678
+ if (overlayMap.empty ())
679
+ continue ;
680
+ for (const auto &dependencyId : inputDependencies) {
681
+ auto moduleName = dependencyId.ModuleName ;
682
+ // Do not look for overlays of main module under scan
683
+ if (moduleName == mainModuleName)
684
+ continue ;
685
+ // check if any explicitly imported modules can serve as a
686
+ // secondary module, and add the overlay names to the
687
+ // dependencies list.
688
+ for (auto overlayName : overlayMap[moduleName]) {
689
+ if (overlayName.str () != mainModuleName &&
690
+ std::find_if (inputDependencies.begin (),
691
+ inputDependencies.end (),
692
+ [&](ModuleDependencyID Id) {
693
+ return moduleName == overlayName.str ();
694
+ }) == inputDependencies.end ()) {
695
+ newOverlays.insert (overlayName);
696
+ }
697
+ }
698
+ }
699
+ }
700
+ };
701
+
702
+ for (const auto &[sourceBufferIdentifierStr, dependencyIDs] :
703
+ perSourceFileDependencies)
704
+ discoverCrossImportOverlayFilesForModuleSet (dependencyIDs.getArrayRef ());
600
705
}
601
706
602
707
std::vector<ModuleDependencyID>
@@ -627,8 +732,8 @@ ModuleDependencyScanner::performDependencyScan(
627
732
// binary Swift modules already encode their dependencies on cross-import overlays
628
733
// with explicit imports.
629
734
if (ScanCompilerInvocation.getLangOptions ().EnableCrossImportOverlays )
630
- discoverCrossImportOverlayDependencies (
631
- rootModuleID.ModuleName , allModules. getArrayRef (). slice ( 1 ), cache,
735
+ resolveCrossImportOverlayDependencies (
736
+ rootModuleID.ModuleName , cache,
632
737
[&](ModuleDependencyID id) { allModules.insert (id); });
633
738
634
739
if (ScanCompilerInvocation.getSearchPathOptions ().BridgingHeaderChaining ) {
@@ -1230,17 +1335,17 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
1230
1335
cache.setSwiftOverlayDependencies (moduleID, swiftOverlayDependencies.getArrayRef ());
1231
1336
}
1232
1337
1233
- void ModuleDependencyScanner::discoverCrossImportOverlayDependencies (
1234
- StringRef mainModuleName, ArrayRef<ModuleDependencyID> allDependencies,
1338
+ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies (
1339
+ StringRef mainModuleName,
1235
1340
ModuleDependenciesCache &cache,
1236
1341
llvm::function_ref<void (ModuleDependencyID)> action) {
1237
1342
// Modules explicitly imported. Only these can be secondary module.
1238
1343
llvm::SetVector<Identifier> newOverlays;
1239
1344
std::vector<std::pair<std::string, std::string>> overlayFiles;
1240
- discoverCrossImportOverlayFiles (mainModuleName, allDependencies, cache ,
1241
- ScanASTContext, newOverlays, overlayFiles);
1345
+ discoverCrossImportOverlayFiles (mainModuleName, cache, ScanASTContext ,
1346
+ newOverlays, overlayFiles);
1242
1347
1243
- // No new cross-import overlays are found , return.
1348
+ // No new cross-import overlays are ffound , return.
1244
1349
if (newOverlays.empty ())
1245
1350
return ;
1246
1351
@@ -1260,11 +1365,10 @@ void ModuleDependencyScanner::discoverCrossImportOverlayDependencies(
1260
1365
1261
1366
// Record the dummy main module's direct dependencies. The dummy main module
1262
1367
// only directly depend on these newly discovered overlay modules.
1263
- if (cache.findDependency (dummyMainName, ModuleDependencyKind::SwiftSource)) {
1368
+ if (cache.findDependency (dummyMainID))
1264
1369
cache.updateDependency (dummyMainID, dummyMainDependencies);
1265
- } else {
1370
+ else
1266
1371
cache.recordDependency (dummyMainName, dummyMainDependencies);
1267
- }
1268
1372
1269
1373
ModuleDependencyIDSetVector allModules =
1270
1374
resolveImportedModuleDependencies (dummyMainID, cache);
0 commit comments