Skip to content

Commit d228d30

Browse files
committed
[Dependency Scanning] Refactor Clang dependency bridging into a 'ModuleDependencyScanner' utility
This moves the functionality of 'bridgeClangModuleDependency' into a utility in the main scanner class because it relies on various objects whose lifetime is already tied to the scanner itself.
1 parent 5015ba6 commit d228d30

File tree

5 files changed

+276
-307
lines changed

5 files changed

+276
-307
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include "swift/Basic/Assertions.h"
2424
#include "swift/Basic/CXXStdlibKind.h"
2525
#include "swift/Basic/LLVM.h"
26-
#include "swift/ClangImporter/ClangImporter.h"
2726
#include "swift/Serialization/Validation.h"
2827
#include "clang/CAS/CASOptions.h"
2928
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
@@ -165,6 +164,12 @@ using ModuleDependencyIDSetVector =
165164
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
166165
std::set<ModuleDependencyID>>;
167166

167+
/// A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
168+
using LookupModuleOutputCallback = llvm::function_ref<std::string(
169+
const clang::tooling::dependencies::ModuleDeps &,
170+
clang::tooling::dependencies::ModuleOutputKind)>;
171+
using RemapPathCallback = llvm::function_ref<std::string(StringRef)>;
172+
168173
namespace dependencies {
169174
std::string createEncodedModuleKindAndName(ModuleDependencyID id);
170175
bool checkImportNotTautological(const ImportPath::Module, const SourceLoc,
@@ -176,18 +181,6 @@ void registerCxxInteropLibraries(
176181
const llvm::Triple &Target, StringRef mainModuleName, bool hasStaticCxx,
177182
bool hasStaticCxxStdlib, CXXStdlibKind cxxStdlibKind,
178183
std::function<void(const LinkLibrary &)> RegistrationCallback);
179-
180-
using RemapPathCallback = llvm::function_ref<std::string(StringRef)>;
181-
using LookupModuleOutputCallback =
182-
llvm::function_ref<std::string(const clang::tooling::dependencies::ModuleDeps &,
183-
clang::tooling::dependencies::ModuleOutputKind)>;
184-
185-
ModuleDependencyInfo
186-
bridgeClangModuleDependency(
187-
const ASTContext &ctx,
188-
const clang::tooling::dependencies::ModuleDeps &clangDependency,
189-
LookupModuleOutputCallback LookupModuleOutput,
190-
RemapPathCallback remapPath = nullptr);
191184
} // namespace dependencies
192185

193186
struct ScannerImportStatementInfo {
@@ -1042,6 +1035,8 @@ using ModuleNameToDependencyMap = llvm::StringMap<ModuleDependencyInfo>;
10421035
using ModuleDependenciesKindMap =
10431036
std::unordered_map<ModuleDependencyKind, ModuleNameToDependencyMap,
10441037
ModuleDependencyKindHash>;
1038+
using BridgeClangDependencyCallback = llvm::function_ref<ModuleDependencyInfo(
1039+
const clang::tooling::dependencies::ModuleDeps &clangModuleDep)>;
10451040

10461041
// MARK: SwiftDependencyScanningService
10471042
/// A carrier of state shared among possibly multiple invocations of the
@@ -1194,9 +1189,8 @@ class ModuleDependenciesCache {
11941189
/// Record dependencies for the given collection of Clang modules.
11951190
void recordClangDependencies(
11961191
const clang::tooling::dependencies::ModuleDepsGraph &dependencies,
1197-
const ASTContext &ctx,
1198-
dependencies::LookupModuleOutputCallback LookupModuleOutput,
1199-
dependencies::RemapPathCallback remapPath = nullptr);
1192+
DiagnosticEngine &diags,
1193+
BridgeClangDependencyCallback bridgeClangModule);
12001194

12011195
/// Update stored dependencies for the given module.
12021196
void updateDependency(ModuleDependencyID moduleID,

include/swift/DependencyScan/ModuleDependencyScanner.h

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -43,39 +43,23 @@ class ModuleDependencyScanningWorker {
4343
std::optional<clang::tooling::dependencies::TranslationUnitDeps>
4444
scanFilesystemForClangModuleDependency(
4545
Identifier moduleName,
46+
LookupModuleOutputCallback lookupModuleCallback,
4647
const llvm::DenseSet<clang::tooling::dependencies::ModuleID>
4748
&alreadySeenModules);
4849

49-
/// Retrieve the module dependencies for the Swift module with the given name.
50-
SwiftModuleScannerQueryResult scanFilesystemForSwiftModuleDependency(
51-
Identifier moduleName, bool isTestableImport = false);
52-
5350
/// Query dependency information for header dependencies
54-
/// of a binary Swift module.
55-
///
56-
/// \param moduleID the name of the Swift module whose dependency
57-
/// information will be augmented with information about the given
58-
/// textual header inputs.
59-
///
60-
/// \param headerPath the path to the header to be scanned.
61-
///
62-
/// \param clangScanningTool The clang dependency scanner.
63-
///
64-
/// \param cache The module dependencies cache to update, with information
65-
/// about new Clang modules discovered along the way.
66-
///
67-
/// \returns \c true if an error occurred, \c false otherwise
68-
bool scanHeaderDependenciesOfSwiftModule(
69-
const ASTContext &ctx,
51+
/// of a Swift module.
52+
std::optional<clang::tooling::dependencies::TranslationUnitDeps>
53+
scanHeaderDependenciesOfSwiftModule(
7054
ModuleDependencyID moduleID, std::optional<StringRef> headerPath,
7155
std::optional<llvm::MemoryBufferRef> sourceBuffer,
72-
ModuleDependenciesCache &cache,
73-
ModuleDependencyIDSetVector &headerClangModuleDependencies,
74-
std::vector<std::string> &headerFileInputs,
75-
std::vector<std::string> &bridgingHeaderCommandLine,
76-
std::vector<std::string> &visibleClangModules,
77-
std::optional<std::string> &includeTreeID);
56+
LookupModuleOutputCallback lookupModuleCallback,
57+
const llvm::DenseSet<clang::tooling::dependencies::ModuleID>
58+
&alreadySeenModules);
7859

60+
/// Retrieve the module dependencies for the Swift module with the given name.
61+
SwiftModuleScannerQueryResult scanFilesystemForSwiftModuleDependency(
62+
Identifier moduleName, bool isTestableImport = false);
7963

8064
/// Store cache entry for include tree.
8165
llvm::Error
@@ -93,16 +77,9 @@ class ModuleDependencyScanningWorker {
9377
// Swift and Clang module loaders acting as scanners.
9478
std::unique_ptr<SwiftModuleScanner> swiftModuleScannerLoader;
9579

96-
/// The location of where the explicitly-built modules will be output to
97-
std::string moduleOutputPath;
98-
/// The location of where the explicitly-built SDK modules will be output to
99-
std::string sdkModuleOutputPath;
100-
10180
// CAS instance.
10281
std::shared_ptr<llvm::cas::ObjectStore> CAS;
10382
std::shared_ptr<llvm::cas::ActionCache> ActionCache;
104-
/// File prefix mapper.
105-
llvm::PrefixMapper *PrefixMapper;
10683

10784
// Base command line invocation for clang scanner queries (both module and header)
10885
std::vector<std::string> clangScanningBaseCommandLineArgs;
@@ -223,11 +200,7 @@ class ModuleDependencyScanner {
223200
return PrefixMapper && !PrefixMapper->getMappings().empty();
224201
}
225202
llvm::PrefixMapper *getPrefixMapper() const { return PrefixMapper.get(); }
226-
std::string remapPath(StringRef Path) const {
227-
if (!PrefixMapper)
228-
return Path.str();
229-
return PrefixMapper->mapToString(Path);
230-
}
203+
std::string remapPath(StringRef Path) const;
231204

232205
/// CAS options.
233206
llvm::cas::ObjectStore &getCAS() const {
@@ -294,11 +267,22 @@ class ModuleDependencyScanner {
294267
ModuleDependenciesCache &cache,
295268
ModuleDependencyIDSetVector &allModules);
296269

270+
/// Bridge Clang dependency scanner's dependency node
271+
/// to the Swift scanner's `ModuleDependencyInfo`.
272+
ModuleDependencyInfo
273+
bridgeClangModuleDependency(
274+
const clang::tooling::dependencies::ModuleDeps &clangDependency);
275+
297276
/// Perform an operation utilizing one of the Scanning workers
298277
/// available to this scanner.
299278
template <typename Function, typename... Args>
300279
auto withDependencyScanningWorker(Function &&F, Args &&...ArgList);
301280

281+
/// Determine cache-relative output path for a given Clang module
282+
std::string clangModuleOutputPathLookup(
283+
const clang::tooling::dependencies::ModuleDeps &clangDep,
284+
clang::tooling::dependencies::ModuleOutputKind moduleOutputKind) const;
285+
302286
/// Use the scanner's ASTContext to construct an `Identifier`
303287
/// for a given module name.
304288
Identifier getModuleImportIdentifier(StringRef moduleName);
@@ -318,6 +302,11 @@ class ModuleDependencyScanner {
318302
ASTContext &ScanASTContext;
319303
ModuleDependencyIssueReporter IssueReporter;
320304

305+
/// The location of where the explicitly-built modules will be output to
306+
std::string ModuleOutputPath;
307+
/// The location of where the explicitly-built SDK modules will be output to
308+
std::string SDKModuleOutputPath;
309+
321310
/// The available pool of workers for filesystem module search
322311
unsigned NumThreads;
323312
std::list<std::unique_ptr<ModuleDependencyScanningWorker>> Workers;

include/swift/Serialization/ScanningLoaders.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,6 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase {
7777

7878
/// AST delegate to be used for textual interface scanning
7979
InterfaceSubContextDelegate &astDelegate;
80-
/// Location where pre-built modules are to be built into.
81-
std::string moduleOutputPath;
82-
/// Location where pre-built SDK modules are to be built into.
83-
std::string sdkModuleOutputPath;
8480
/// Clang-specific (-Xcc) command-line flags to include on
8581
/// Swift module compilation commands
8682
std::vector<std::string> swiftModuleClangCC1CommandLineArgs;
@@ -96,14 +92,12 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase {
9692
public:
9793
SwiftModuleScanner(
9894
ASTContext &ctx, ModuleLoadingMode LoadMode,
99-
InterfaceSubContextDelegate &astDelegate, StringRef moduleOutputPath,
100-
StringRef sdkModuleOutputPath,
95+
InterfaceSubContextDelegate &astDelegate,
10196
std::vector<std::string> swiftModuleClangCC1CommandLineArgs,
10297
llvm::StringMap<std::string> &explicitSwiftModuleInputs)
10398
: SerializedModuleLoaderBase(ctx, nullptr, LoadMode,
10499
/*IgnoreSwiftSourceInfoFile=*/true),
105-
astDelegate(astDelegate), moduleOutputPath(moduleOutputPath),
106-
sdkModuleOutputPath(sdkModuleOutputPath),
100+
astDelegate(astDelegate),
107101
swiftModuleClangCC1CommandLineArgs(swiftModuleClangCC1CommandLineArgs),
108102
explicitSwiftModuleInputs(explicitSwiftModuleInputs) {
109103
}

lib/AST/ModuleDependencies.cpp

Lines changed: 9 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -599,120 +599,6 @@ void swift::dependencies::registerCxxInteropLibraries(
599599
}
600600
}
601601

602-
ModuleDependencyInfo swift::dependencies::bridgeClangModuleDependency(
603-
const ASTContext &ctx,
604-
const clang::tooling::dependencies::ModuleDeps &clangModuleDep,
605-
LookupModuleOutputCallback lookupModuleOutput, RemapPathCallback callback) {
606-
auto remapPath = [&](StringRef path) {
607-
if (callback)
608-
return callback(path);
609-
return path.str();
610-
};
611-
612-
// File dependencies for this module.
613-
std::vector<std::string> fileDeps;
614-
clangModuleDep.forEachFileDep(
615-
[&fileDeps](StringRef fileDep) { fileDeps.emplace_back(fileDep); });
616-
617-
std::vector<std::string> swiftArgs;
618-
auto addClangArg = [&](Twine arg) {
619-
swiftArgs.push_back("-Xcc");
620-
swiftArgs.push_back(arg.str());
621-
};
622-
623-
// We are using Swift frontend mode.
624-
swiftArgs.push_back("-frontend");
625-
626-
// Swift frontend action: -emit-pcm
627-
swiftArgs.push_back("-emit-pcm");
628-
swiftArgs.push_back("-module-name");
629-
swiftArgs.push_back(clangModuleDep.ID.ModuleName);
630-
631-
auto pcmPath = lookupModuleOutput(
632-
clangModuleDep,
633-
clang::tooling::dependencies::ModuleOutputKind::ModuleFile);
634-
swiftArgs.push_back("-o");
635-
swiftArgs.push_back(pcmPath);
636-
637-
// Ensure that the resulting PCM build invocation uses Clang frontend
638-
// directly
639-
swiftArgs.push_back("-direct-clang-cc1-module-build");
640-
641-
// Swift frontend option for input file path (Foo.modulemap).
642-
swiftArgs.push_back(remapPath(clangModuleDep.ClangModuleMapFile));
643-
644-
auto invocation = clangModuleDep.getUnderlyingCompilerInvocation();
645-
// Clear some options from clang scanner.
646-
invocation.getMutFrontendOpts().ModuleCacheKeys.clear();
647-
invocation.getMutFrontendOpts().PathPrefixMappings.clear();
648-
invocation.getMutFrontendOpts().OutputFile.clear();
649-
650-
// Reset CASOptions since that should be coming from swift.
651-
invocation.getMutCASOpts() = clang::CASOptions();
652-
invocation.getMutFrontendOpts().CASIncludeTreeID.clear();
653-
654-
// FIXME: workaround for rdar://105684525: find the -ivfsoverlay option
655-
// from clang scanner and pass to swift.
656-
if (!ctx.CASOpts.EnableCaching) {
657-
auto &overlayFiles = invocation.getMutHeaderSearchOpts().VFSOverlayFiles;
658-
for (auto overlay : overlayFiles) {
659-
swiftArgs.push_back("-vfsoverlay");
660-
swiftArgs.push_back(overlay);
661-
}
662-
}
663-
664-
// Add args reported by the scanner.
665-
auto clangArgs = invocation.getCC1CommandLine();
666-
llvm::for_each(clangArgs, addClangArg);
667-
668-
// CASFileSystemRootID.
669-
std::string RootID = clangModuleDep.CASFileSystemRootID
670-
? clangModuleDep.CASFileSystemRootID->toString()
671-
: "";
672-
673-
std::string IncludeTree =
674-
clangModuleDep.IncludeTreeID ? *clangModuleDep.IncludeTreeID : "";
675-
676-
ctx.CASOpts.enumerateCASConfigurationFlags(
677-
[&](StringRef Arg) { swiftArgs.push_back(Arg.str()); });
678-
679-
if (!IncludeTree.empty()) {
680-
swiftArgs.push_back("-clang-include-tree-root");
681-
swiftArgs.push_back(IncludeTree);
682-
}
683-
std::string mappedPCMPath = remapPath(pcmPath);
684-
685-
std::vector<LinkLibrary> LinkLibraries;
686-
for (const auto &ll : clangModuleDep.LinkLibraries)
687-
LinkLibraries.emplace_back(ll.Library,
688-
ll.IsFramework ? LibraryKind::Framework
689-
: LibraryKind::Library,
690-
/*static=*/false);
691-
692-
// Module-level dependencies.
693-
llvm::StringSet<> alreadyAddedModules;
694-
auto bridgedDependencyInfo = ModuleDependencyInfo::forClangModule(
695-
pcmPath, mappedPCMPath, clangModuleDep.ClangModuleMapFile,
696-
clangModuleDep.ID.ContextHash, swiftArgs, fileDeps, LinkLibraries, RootID,
697-
IncludeTree, /*module-cache-key*/ "", clangModuleDep.IsSystem);
698-
699-
std::vector<ModuleDependencyID> directDependencyIDs;
700-
for (const auto &moduleName : clangModuleDep.ClangModuleDeps) {
701-
// FIXME: This assumes, conservatively, that all Clang module imports
702-
// are exported. We need to fix this once the clang scanner gains the
703-
// appropriate API to query this.
704-
bridgedDependencyInfo.addModuleImport(
705-
moduleName.ModuleName, /* isExported */ true, AccessLevel::Public,
706-
&alreadyAddedModules);
707-
// It is safe to assume that all dependencies of a Clang module are Clang
708-
// modules.
709-
directDependencyIDs.push_back(
710-
{moduleName.ModuleName, ModuleDependencyKind::Clang});
711-
}
712-
bridgedDependencyInfo.setImportedClangDependencies(directDependencyIDs);
713-
return bridgedDependencyInfo;
714-
}
715-
716602
void
717603
swift::dependencies::registerBackDeployLibraries(
718604
const IRGenOptions &IRGenOpts,
@@ -895,9 +781,8 @@ void ModuleDependenciesCache::recordDependency(
895781

896782
void ModuleDependenciesCache::recordClangDependencies(
897783
const clang::tooling::dependencies::ModuleDepsGraph &dependencies,
898-
const ASTContext &ctx,
899-
dependencies::LookupModuleOutputCallback lookupModuleOutput,
900-
dependencies::RemapPathCallback remapPath) {
784+
DiagnosticEngine &diags,
785+
BridgeClangDependencyCallback bridgeClangModule) {
901786
for (const auto &dep : dependencies) {
902787
auto depID =
903788
ModuleDependencyID{dep.ID.ModuleName, ModuleDependencyKind::Clang};
@@ -917,33 +802,29 @@ void ModuleDependenciesCache::recordClangDependencies(
917802
//
918803
// Emit a failure diagnostic here that is hopefully more actionable
919804
// for the time being.
920-
ctx.Diags.diagnose(SourceLoc(),
805+
diags.diagnose(SourceLoc(),
921806
diag::dependency_scan_unexpected_variant,
922807
dep.ID.ModuleName);
923-
ctx.Diags.diagnose(
808+
diags.diagnose(
924809
SourceLoc(),
925810
diag::dependency_scan_unexpected_variant_context_hash_note,
926811
priorContextHash, newContextHash);
927-
ctx.Diags.diagnose(
812+
diags.diagnose(
928813
SourceLoc(),
929814
diag::dependency_scan_unexpected_variant_module_map_note,
930815
priorClangModuleDetails->moduleMapFile, dep.ClangModuleMapFile);
931816

932-
auto newClangModuleDetails =
933-
dependencies::bridgeClangModuleDependency(
934-
ctx, dep, lookupModuleOutput, remapPath)
935-
.getAsClangModule();
936-
817+
auto newClangModuleDetails = bridgeClangModule(dep).getAsClangModule();
937818
auto diagnoseExtraCommandLineFlags =
938-
[&ctx](const ClangModuleDependencyStorage *checkModuleDetails,
819+
[&diags](const ClangModuleDependencyStorage *checkModuleDetails,
939820
const ClangModuleDependencyStorage *baseModuleDetails,
940821
bool isNewlyDiscovered) -> void {
941822
std::unordered_set<std::string> baseCommandLineSet(
942823
baseModuleDetails->buildCommandLine.begin(),
943824
baseModuleDetails->buildCommandLine.end());
944825
for (const auto &checkArg : checkModuleDetails->buildCommandLine)
945826
if (baseCommandLineSet.find(checkArg) == baseCommandLineSet.end())
946-
ctx.Diags.diagnose(
827+
diags.diagnose(
947828
SourceLoc(),
948829
diag::dependency_scan_unexpected_variant_extra_arg_note,
949830
isNewlyDiscovered, checkArg);
@@ -954,9 +835,7 @@ void ModuleDependenciesCache::recordClangDependencies(
954835
priorClangModuleDetails, false);
955836
}
956837
} else {
957-
recordDependency(dep.ID.ModuleName,
958-
dependencies::bridgeClangModuleDependency(
959-
ctx, dep, lookupModuleOutput, remapPath));
838+
recordDependency(dep.ID.ModuleName, bridgeClangModule(dep));
960839
addSeenClangModule(dep.ID);
961840
}
962841
}

0 commit comments

Comments
 (0)