@@ -561,42 +561,141 @@ ModuleDependencyScanner::getNamedSwiftModuleDependencyInfo(
561561 return cache.findDependency (moduleName);
562562}
563563
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.
564581static 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,
568584 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+ };
574616
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);
596644 }
597645 }
646+ for (const auto &directClangDepID :
647+ cache.getImportedClangDependencies (moduleID)) {
648+ if (perSourceFileDependencies[bufferIdentifier].count (directClangDepID))
649+ continue ;
650+ worklist.push_back (directClangDepID);
651+ }
598652 }
599653 }
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 );
600699}
601700
602701std::vector<ModuleDependencyID>
@@ -627,8 +726,8 @@ ModuleDependencyScanner::performDependencyScan(
627726 // binary Swift modules already encode their dependencies on cross-import overlays
628727 // with explicit imports.
629728 if (ScanCompilerInvocation.getLangOptions ().EnableCrossImportOverlays )
630- discoverCrossImportOverlayDependencies (
631- rootModuleID.ModuleName , allModules. getArrayRef (). slice ( 1 ), cache,
729+ resolveCrossImportOverlayDependencies (
730+ rootModuleID.ModuleName , cache,
632731 [&](ModuleDependencyID id) { allModules.insert (id); });
633732
634733 if (ScanCompilerInvocation.getSearchPathOptions ().BridgingHeaderChaining ) {
@@ -1230,15 +1329,15 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
12301329 cache.setSwiftOverlayDependencies (moduleID, swiftOverlayDependencies.getArrayRef ());
12311330}
12321331
1233- void ModuleDependencyScanner::discoverCrossImportOverlayDependencies (
1234- StringRef mainModuleName, ArrayRef<ModuleDependencyID> allDependencies,
1332+ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies (
1333+ StringRef mainModuleName,
12351334 ModuleDependenciesCache &cache,
12361335 llvm::function_ref<void (ModuleDependencyID)> action) {
12371336 // Modules explicitly imported. Only these can be secondary module.
12381337 llvm::SetVector<Identifier> newOverlays;
12391338 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);
12421341
12431342 // No new cross-import overlays are found, return.
12441343 if (newOverlays.empty ())
@@ -1260,11 +1359,10 @@ void ModuleDependencyScanner::discoverCrossImportOverlayDependencies(
12601359
12611360 // Record the dummy main module's direct dependencies. The dummy main module
12621361 // only directly depend on these newly discovered overlay modules.
1263- if (cache.findDependency (dummyMainName, ModuleDependencyKind::SwiftSource)) {
1362+ if (cache.findDependency (dummyMainID))
12641363 cache.updateDependency (dummyMainID, dummyMainDependencies);
1265- } else {
1364+ else
12661365 cache.recordDependency (dummyMainName, dummyMainDependencies);
1267- }
12681366
12691367 ModuleDependencyIDSetVector allModules =
12701368 resolveImportedModuleDependencies (dummyMainID, cache);
0 commit comments