Skip to content

Commit 89b43dc

Browse files
authored
Merge pull request #83600 from artemcm/NoRedundantClangDepBridging
[Dependency Scanning] Bridge Clang dependency scanner results on-demand
2 parents d2691dc + 9f0083c commit 89b43dc

File tree

7 files changed

+344
-341
lines changed

7 files changed

+344
-341
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/Serialization/Validation.h"
2727
#include "clang/CAS/CASOptions.h"
2828
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
29+
#include "clang/Tooling/DependencyScanning/DependencyScanningTool.h"
2930
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
3031
#include "llvm/ADT/ArrayRef.h"
3132
#include "llvm/ADT/DenseSet.h"
@@ -1028,6 +1029,8 @@ using ModuleNameToDependencyMap = llvm::StringMap<ModuleDependencyInfo>;
10281029
using ModuleDependenciesKindMap =
10291030
std::unordered_map<ModuleDependencyKind, ModuleNameToDependencyMap,
10301031
ModuleDependencyKindHash>;
1032+
using BridgeClangDependencyCallback = llvm::function_ref<ModuleDependencyInfo(
1033+
const clang::tooling::dependencies::ModuleDeps &clangModuleDep)>;
10311034

10321035
// MARK: SwiftDependencyScanningService
10331036
/// A carrier of state shared among possibly multiple invocations of the
@@ -1178,8 +1181,10 @@ class ModuleDependenciesCache {
11781181
ModuleDependencyInfo dependencies);
11791182

11801183
/// Record dependencies for the given collection of Clang modules.
1181-
void recordClangDependencies(ModuleDependencyVector moduleDependencies,
1182-
DiagnosticEngine &diags);
1184+
void recordClangDependencies(
1185+
const clang::tooling::dependencies::ModuleDepsGraph &dependencies,
1186+
DiagnosticEngine &diags,
1187+
BridgeClangDependencyCallback bridgeClangModule);
11831188

11841189
/// Update stored dependencies for the given module.
11851190
void updateDependency(ModuleDependencyID moduleID,

include/swift/ClangImporter/ClangImporter.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -492,19 +492,6 @@ class ClangImporter final : public ClangModuleLoader {
492492

493493
void verifyAllModules() override;
494494

495-
using RemapPathCallback = llvm::function_ref<std::string(StringRef)>;
496-
using LookupModuleOutputCallback =
497-
llvm::function_ref<std::string(const clang::tooling::dependencies::ModuleDeps &,
498-
clang::tooling::dependencies::ModuleOutputKind)>;
499-
500-
static llvm::SmallVector<std::pair<ModuleDependencyID, ModuleDependencyInfo>, 1>
501-
bridgeClangModuleDependencies(
502-
const ASTContext &ctx,
503-
clang::tooling::dependencies::DependencyScanningTool &clangScanningTool,
504-
clang::tooling::dependencies::ModuleDepsGraph &clangDependencies,
505-
LookupModuleOutputCallback LookupModuleOutput,
506-
RemapPathCallback remapPath = nullptr);
507-
508495
static void getBridgingHeaderOptions(
509496
const ASTContext &ctx,
510497
const clang::tooling::dependencies::TranslationUnitDeps &deps,

include/swift/DependencyScan/ModuleDependencyScanner.h

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ class DependencyTracker;
2525

2626
namespace swift {
2727

28+
/// A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
29+
using LookupModuleOutputCallback = llvm::function_ref<std::string(
30+
const clang::tooling::dependencies::ModuleDeps &,
31+
clang::tooling::dependencies::ModuleOutputKind)>;
32+
using RemapPathCallback = llvm::function_ref<std::string(StringRef)>;
33+
2834
/// A dependency scanning worker which performs filesystem lookup
2935
/// of a named module dependency.
3036
class ModuleDependencyScanningWorker {
@@ -39,42 +45,60 @@ class ModuleDependencyScanningWorker {
3945
llvm::PrefixMapper *mapper, DiagnosticEngine &diags);
4046

4147
private:
42-
/// Retrieve the module dependencies for the Clang module with the given name.
43-
ClangModuleScannerQueryResult scanFilesystemForClangModuleDependency(
48+
/// Query dependency information for a named Clang module
49+
///
50+
/// \param moduleName moduel identifier for the query
51+
///
52+
/// \param lookupModuleCallback a callback to compute a client-specific
53+
/// module-cache-relative output path for discovered Clang module dependencies.
54+
///
55+
/// \param alreadySeenModules a set of module dependencies previously seen
56+
/// by the scanner, as to avoid processing them all over again
57+
///
58+
/// \returns Clang dependency scanner's \c TranslationUnitDeps result
59+
std::optional<clang::tooling::dependencies::TranslationUnitDeps>
60+
scanFilesystemForClangModuleDependency(
4461
Identifier moduleName,
62+
LookupModuleOutputCallback lookupModuleCallback,
4563
const llvm::DenseSet<clang::tooling::dependencies::ModuleID>
4664
&alreadySeenModules);
4765

48-
/// Retrieve the module dependencies for the Swift module with the given name.
49-
SwiftModuleScannerQueryResult scanFilesystemForSwiftModuleDependency(
50-
Identifier moduleName, bool isTestableImport = false);
51-
5266
/// Query dependency information for header dependencies
5367
/// of a binary Swift module.
5468
///
5569
/// \param moduleID the name of the Swift module whose dependency
5670
/// information will be augmented with information about the given
5771
/// textual header inputs.
5872
///
59-
/// \param headerPath the path to the header to be scanned.
73+
/// \param headerPath optional path to the header to be scanned.
74+
///
75+
/// \param sourceBuffer optional in-memory buffer of a header to be scanned.
6076
///
61-
/// \param clangScanningTool The clang dependency scanner.
77+
/// \param lookupModuleCallback a callback to compute a client-specific
78+
/// module-cache-relative output path for discovered Clang module dependencies.
6279
///
63-
/// \param cache The module dependencies cache to update, with information
64-
/// about new Clang modules discovered along the way.
80+
/// \param alreadySeenModules a set of module dependencies previously seen
81+
/// by the scanner, as to avoid processing them all over again
6582
///
66-
/// \returns \c true if an error occurred, \c false otherwise
67-
bool scanHeaderDependenciesOfSwiftModule(
68-
const ASTContext &ctx,
83+
/// \returns Clang dependency scanner's \c TranslationUnitDeps result
84+
std::optional<clang::tooling::dependencies::TranslationUnitDeps>
85+
scanHeaderDependenciesOfSwiftModule(
6986
ModuleDependencyID moduleID, std::optional<StringRef> headerPath,
7087
std::optional<llvm::MemoryBufferRef> sourceBuffer,
71-
ModuleDependenciesCache &cache,
72-
ModuleDependencyIDSetVector &headerClangModuleDependencies,
73-
std::vector<std::string> &headerFileInputs,
74-
std::vector<std::string> &bridgingHeaderCommandLine,
75-
std::vector<std::string> &visibleClangModules,
76-
std::optional<std::string> &includeTreeID);
88+
LookupModuleOutputCallback lookupModuleCallback,
89+
const llvm::DenseSet<clang::tooling::dependencies::ModuleID>
90+
&alreadySeenModules);
7791

92+
/// Query dependency information for a named Swift module
93+
///
94+
/// \param moduleName moduel identifier for the query
95+
///
96+
/// \param isTestableImport a boolean flag which indicates whether
97+
/// this is an @testable dependency
98+
///
99+
/// \returns a struct containing query results
100+
SwiftModuleScannerQueryResult scanFilesystemForSwiftModuleDependency(
101+
Identifier moduleName, bool isTestableImport = false);
78102

79103
/// Store cache entry for include tree.
80104
llvm::Error
@@ -92,16 +116,9 @@ class ModuleDependencyScanningWorker {
92116
// Swift and Clang module loaders acting as scanners.
93117
std::unique_ptr<SwiftModuleScanner> swiftModuleScannerLoader;
94118

95-
/// The location of where the explicitly-built modules will be output to
96-
std::string moduleOutputPath;
97-
/// The location of where the explicitly-built SDK modules will be output to
98-
std::string sdkModuleOutputPath;
99-
100119
// CAS instance.
101120
std::shared_ptr<llvm::cas::ObjectStore> CAS;
102121
std::shared_ptr<llvm::cas::ActionCache> ActionCache;
103-
/// File prefix mapper.
104-
llvm::PrefixMapper *PrefixMapper;
105122

106123
// Base command line invocation for clang scanner queries (both module and header)
107124
std::vector<std::string> clangScanningBaseCommandLineArgs;
@@ -222,11 +239,7 @@ class ModuleDependencyScanner {
222239
return PrefixMapper && !PrefixMapper->getMappings().empty();
223240
}
224241
llvm::PrefixMapper *getPrefixMapper() const { return PrefixMapper.get(); }
225-
std::string remapPath(StringRef Path) const {
226-
if (!PrefixMapper)
227-
return Path.str();
228-
return PrefixMapper->mapToString(Path);
229-
}
242+
std::string remapPath(StringRef Path) const;
230243

231244
/// CAS options.
232245
llvm::cas::ObjectStore &getCAS() const {
@@ -293,11 +306,22 @@ class ModuleDependencyScanner {
293306
ModuleDependenciesCache &cache,
294307
ModuleDependencyIDSetVector &allModules);
295308

309+
/// Bridge Clang dependency scanner's dependency node
310+
/// to the Swift scanner's `ModuleDependencyInfo`.
311+
ModuleDependencyInfo
312+
bridgeClangModuleDependency(
313+
const clang::tooling::dependencies::ModuleDeps &clangDependency);
314+
296315
/// Perform an operation utilizing one of the Scanning workers
297316
/// available to this scanner.
298317
template <typename Function, typename... Args>
299318
auto withDependencyScanningWorker(Function &&F, Args &&...ArgList);
300319

320+
/// Determine cache-relative output path for a given Clang module
321+
std::string clangModuleOutputPathLookup(
322+
const clang::tooling::dependencies::ModuleDeps &clangDep,
323+
clang::tooling::dependencies::ModuleOutputKind moduleOutputKind) const;
324+
301325
/// Use the scanner's ASTContext to construct an `Identifier`
302326
/// for a given module name.
303327
Identifier getModuleImportIdentifier(StringRef moduleName);
@@ -317,6 +341,11 @@ class ModuleDependencyScanner {
317341
ASTContext &ScanASTContext;
318342
ModuleDependencyIssueReporter IssueReporter;
319343

344+
/// The location of where the explicitly-built modules will be output to
345+
std::string ModuleOutputPath;
346+
/// The location of where the explicitly-built SDK modules will be output to
347+
std::string SDKModuleOutputPath;
348+
320349
/// The available pool of workers for filesystem module search
321350
unsigned NumThreads;
322351
std::list<std::unique_ptr<ModuleDependencyScanningWorker>> Workers;

include/swift/Serialization/ScanningLoaders.h

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,6 @@ struct SwiftModuleScannerQueryResult {
4040
std::vector<IncompatibleCandidate> incompatibleCandidates;
4141
};
4242

43-
/// Result of looking up a Clang module on the current filesystem
44-
/// search paths.
45-
struct ClangModuleScannerQueryResult {
46-
ClangModuleScannerQueryResult(const ModuleDependencyVector &dependencyModuleGraph,
47-
const std::vector<std::string> &visibleModuleIdentifiers)
48-
: foundDependencyModuleGraph(dependencyModuleGraph),
49-
visibleModuleIdentifiers(visibleModuleIdentifiers) {}
50-
51-
ModuleDependencyVector foundDependencyModuleGraph;
52-
std::vector<std::string> visibleModuleIdentifiers;
53-
};
54-
5543
/// A module "loader" that looks for .swiftinterface and .swiftmodule files
5644
/// for the purpose of determining dependencies, but does not attempt to
5745
/// load the module files.
@@ -89,10 +77,6 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase {
8977

9078
/// AST delegate to be used for textual interface scanning
9179
InterfaceSubContextDelegate &astDelegate;
92-
/// Location where pre-built modules are to be built into.
93-
std::string moduleOutputPath;
94-
/// Location where pre-built SDK modules are to be built into.
95-
std::string sdkModuleOutputPath;
9680
/// Clang-specific (-Xcc) command-line flags to include on
9781
/// Swift module compilation commands
9882
std::vector<std::string> swiftModuleClangCC1CommandLineArgs;
@@ -108,14 +92,12 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase {
10892
public:
10993
SwiftModuleScanner(
11094
ASTContext &ctx, ModuleLoadingMode LoadMode,
111-
InterfaceSubContextDelegate &astDelegate, StringRef moduleOutputPath,
112-
StringRef sdkModuleOutputPath,
95+
InterfaceSubContextDelegate &astDelegate,
11396
std::vector<std::string> swiftModuleClangCC1CommandLineArgs,
11497
llvm::StringMap<std::string> &explicitSwiftModuleInputs)
11598
: SerializedModuleLoaderBase(ctx, nullptr, LoadMode,
11699
/*IgnoreSwiftSourceInfoFile=*/true),
117-
astDelegate(astDelegate), moduleOutputPath(moduleOutputPath),
118-
sdkModuleOutputPath(sdkModuleOutputPath),
100+
astDelegate(astDelegate),
119101
swiftModuleClangCC1CommandLineArgs(swiftModuleClangCC1CommandLineArgs),
120102
explicitSwiftModuleInputs(explicitSwiftModuleInputs) {
121103
}

lib/AST/ModuleDependencies.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/SourceFile.h"
2424
#include "swift/Frontend/Frontend.h"
2525
#include "swift/Strings.h"
26+
#include "clang/Lex/HeaderSearchOptions.h"
2627
#include "llvm/Config/config.h"
2728
#include "llvm/Support/Path.h"
2829
using namespace swift;
@@ -779,16 +780,18 @@ void ModuleDependenciesCache::recordDependency(
779780
}
780781

781782
void ModuleDependenciesCache::recordClangDependencies(
782-
ModuleDependencyVector dependencies, DiagnosticEngine &diags) {
783+
const clang::tooling::dependencies::ModuleDepsGraph &dependencies,
784+
DiagnosticEngine &diags,
785+
BridgeClangDependencyCallback bridgeClangModule) {
783786
for (const auto &dep : dependencies) {
784-
ASSERT(dep.first.Kind == ModuleDependencyKind::Clang);
785-
auto newClangModuleDetails = dep.second.getAsClangModule();
786-
if (hasDependency(dep.first)) {
787+
auto depID =
788+
ModuleDependencyID{dep.ID.ModuleName, ModuleDependencyKind::Clang};
789+
if (hasDependency(depID)) {
787790
auto priorClangModuleDetails =
788-
findKnownDependency(dep.first).getAsClangModule();
789-
DEBUG_ASSERT(priorClangModuleDetails && newClangModuleDetails);
791+
findKnownDependency(depID).getAsClangModule();
792+
DEBUG_ASSERT(priorClangModuleDetails);
790793
auto priorContextHash = priorClangModuleDetails->contextHash;
791-
auto newContextHash = newClangModuleDetails->contextHash;
794+
auto newContextHash = dep.ID.ContextHash;
792795
if (priorContextHash != newContextHash) {
793796
// This situation means that within the same scanning action, Clang
794797
// Dependency Scanner has produced two different variants of the same
@@ -799,22 +802,23 @@ void ModuleDependenciesCache::recordClangDependencies(
799802
//
800803
// Emit a failure diagnostic here that is hopefully more actionable
801804
// for the time being.
802-
diags.diagnose(SourceLoc(), diag::dependency_scan_unexpected_variant,
803-
dep.first.ModuleName);
805+
diags.diagnose(SourceLoc(),
806+
diag::dependency_scan_unexpected_variant,
807+
dep.ID.ModuleName);
804808
diags.diagnose(
805809
SourceLoc(),
806810
diag::dependency_scan_unexpected_variant_context_hash_note,
807811
priorContextHash, newContextHash);
808812
diags.diagnose(
809813
SourceLoc(),
810814
diag::dependency_scan_unexpected_variant_module_map_note,
811-
priorClangModuleDetails->moduleMapFile,
812-
newClangModuleDetails->moduleMapFile);
815+
priorClangModuleDetails->moduleMapFile, dep.ClangModuleMapFile);
813816

817+
auto newClangModuleDetails = bridgeClangModule(dep).getAsClangModule();
814818
auto diagnoseExtraCommandLineFlags =
815819
[&diags](const ClangModuleDependencyStorage *checkModuleDetails,
816-
const ClangModuleDependencyStorage *baseModuleDetails,
817-
bool isNewlyDiscovered) -> void {
820+
const ClangModuleDependencyStorage *baseModuleDetails,
821+
bool isNewlyDiscovered) -> void {
818822
std::unordered_set<std::string> baseCommandLineSet(
819823
baseModuleDetails->buildCommandLine.begin(),
820824
baseModuleDetails->buildCommandLine.end());
@@ -831,9 +835,8 @@ void ModuleDependenciesCache::recordClangDependencies(
831835
priorClangModuleDetails, false);
832836
}
833837
} else {
834-
recordDependency(dep.first.ModuleName, dep.second);
835-
addSeenClangModule(clang::tooling::dependencies::ModuleID{
836-
dep.first.ModuleName, newClangModuleDetails->contextHash});
838+
recordDependency(dep.ID.ModuleName, bridgeClangModule(dep));
839+
addSeenClangModule(dep.ID);
837840
}
838841
}
839842
}

0 commit comments

Comments
 (0)