Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2432,6 +2432,22 @@ WARNING(dependency_scan_module_incompatible, none,
"module file '%0' is incompatible with this Swift compiler: %1",
(StringRef, StringRef))

REMARK(dependency_scan_number_swift_queries, none,
"Number of Swift module queries: '%0'",
(uint32_t))
REMARK(dependency_scan_number_named_clang_queries, none,
"Number of named Clang module queries: '%0'",
(uint32_t))
REMARK(dependency_scan_number_swift_dependencies, none,
"Number of recorded Swift module dependencies: '%0'",
(uint32_t))
REMARK(dependency_scan_number_named_clang_dependencies, none,
"Number of recorded Clang module dependencies queried by-name from a Swift client: '%0'",
(uint32_t))
REMARK(dependency_scan_number_clang_dependencies, none,
"Number of recorded Clang module dependencies: '%0'",
(uint32_t))

ERROR(clang_dependency_scan_error, none, "clang dependency scanning failure: %0", (StringRef))

ERROR(clang_header_dependency_scan_error, none, "bridging header dependency scanning failure: %0", (StringRef))
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/ModuleDependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,11 @@ class ModuleDependenciesCache {
bool hasDependency(StringRef moduleName) const;
/// Whether we have cached dependency information for the given Swift module.
bool hasSwiftDependency(StringRef moduleName) const;
/// Report the number of recorded Clang dependencies
int numberOfClangDependencies() const;
/// Report the number of recorded Swift dependencies
/// (Textual + Binary)
int numberOfSwiftDependencies() const;

const llvm::DenseSet<clang::tooling::dependencies::ModuleID> &
getAlreadySeenClangModules() const {
Expand Down
115 changes: 71 additions & 44 deletions include/swift/DependencyScan/ModuleDependencyScanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,68 @@ using ImportStatementInfoMap =
std::unordered_map<ModuleDependencyID,
std::vector<ScannerImportStatementInfo>>;

struct ScannerMetrics {
/// Number of performed queries for a Swift dependency with a given name
std::atomic<uint32_t> SwiftModuleQueries;
/// Number of performed queries for a Clang dependency with a given name
std::atomic<uint32_t> NamedClangModuleQueries;
/// Number of discovered Clang module dependencies which are directly
/// imported from a Swift module by-name
std::atomic<uint32_t> RecordedNamedClangModuleDependencies;
};

class DependencyScannerDiagnosticReporter {
private:
DependencyScannerDiagnosticReporter(DiagnosticEngine &Diagnostics,
bool EmitScanRemarks);

/// Diagnose scanner failure and attempt to reconstruct the dependency
/// path from the main module to the missing dependency
void diagnoseModuleNotFoundFailure(
const ScannerImportStatementInfo &moduleImport,
const ModuleDependenciesCache &cache,
std::optional<ModuleDependencyID> dependencyOf,
std::optional<std::pair<ModuleDependencyID, std::string>>
resolvingSerializedSearchPath,
std::optional<
std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>>
foundIncompatibleCandidates = std::nullopt);

/// Upon query failure, if incompatible binary module
/// candidates were found, emit a failure diagnostic
void diagnoseFailureOnOnlyIncompatibleCandidates(
const ScannerImportStatementInfo &moduleImport,
const std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>
&candidates,
const ModuleDependenciesCache &cache,
std::optional<ModuleDependencyID> dependencyOf);

/// Emit warnings for each discovered binary Swift module
/// which was incompatible with the current compilation
/// when querying \c moduleName
void warnOnIncompatibleCandidates(
StringRef moduleName,
const std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>
&candidates);

/// If remark emission is enabled, increment the
/// corresponding metric.
void registerSwiftModuleQuery();
void registerNamedClangModuleQuery();
void registerNamedClangDependency();

/// Emit various metrics about the current scannig action
void emitScanMetrics(const ModuleDependenciesCache &cache) const;

DiagnosticEngine &Diagnostics;
bool EmitScanRemarks;
std::unique_ptr<ScannerMetrics> ScanMetrics;
std::unordered_set<std::string> ReportedMissing;
// Restrict access to the parent scanner classes.
friend class ModuleDependencyScanner;
friend class ModuleDependencyScanningWorker;
};

/// A dependency scanning worker which performs filesystem lookup
/// of a named module dependency.
class ModuleDependencyScanningWorker {
Expand All @@ -48,7 +110,8 @@ class ModuleDependencyScanningWorker {
DependencyTracker &DependencyTracker,
std::shared_ptr<llvm::cas::ObjectStore> CAS,
std::shared_ptr<llvm::cas::ActionCache> ActionCache,
llvm::PrefixMapper *mapper, DiagnosticEngine &diags);
DependencyScannerDiagnosticReporter &DiagnosticReporter,
llvm::PrefixMapper *mapper);

private:
/// Query dependency information for a named Clang module
Expand Down Expand Up @@ -128,6 +191,9 @@ class ModuleDependencyScanningWorker {
std::shared_ptr<llvm::cas::ObjectStore> CAS;
std::shared_ptr<llvm::cas::ActionCache> ActionCache;

// The parent scanner's diagnostic reporter
DependencyScannerDiagnosticReporter &diagnosticReporter;

// Base command line invocation for clang scanner queries (both module and header)
std::vector<std::string> clangScanningBaseCommandLineArgs;
// Command line invocation for clang by-name module lookups
Expand Down Expand Up @@ -173,46 +239,6 @@ class SwiftDependencyTracker {
std::map<std::string, FileEntry> TrackedFiles;
};

class ModuleDependencyIssueReporter {
private:
ModuleDependencyIssueReporter(DiagnosticEngine &Diagnostics)
: Diagnostics(Diagnostics) {}

/// Diagnose scanner failure and attempt to reconstruct the dependency
/// path from the main module to the missing dependency
void diagnoseModuleNotFoundFailure(
const ScannerImportStatementInfo &moduleImport,
const ModuleDependenciesCache &cache,
std::optional<ModuleDependencyID> dependencyOf,
std::optional<std::pair<ModuleDependencyID, std::string>>
resolvingSerializedSearchPath,
std::optional<
std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>>
foundIncompatibleCandidates = std::nullopt);

/// Upon query failure, if incompatible binary module
/// candidates were found, emit a failure diagnostic
void diagnoseFailureOnOnlyIncompatibleCandidates(
const ScannerImportStatementInfo &moduleImport,
const std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>
&candidates,
const ModuleDependenciesCache &cache,
std::optional<ModuleDependencyID> dependencyOf);

/// Emit warnings for each discovered binary Swift module
/// which was incompatible with the current compilation
/// when querying \c moduleName
void warnOnIncompatibleCandidates(
StringRef moduleName,
const std::vector<SwiftModuleScannerQueryResult::IncompatibleCandidate>
&candidates);

DiagnosticEngine &Diagnostics;
std::unordered_set<std::string> ReportedMissing;
// Restrict access to the parent scanner class.
friend class ModuleDependencyScanner;
};

class ModuleDependencyScanner {
public:
ModuleDependencyScanner(SwiftDependencyScanningService &ScanningService,
Expand All @@ -223,7 +249,8 @@ class ModuleDependencyScanner {
DependencyTracker &DependencyTracker,
std::shared_ptr<llvm::cas::ObjectStore> CAS,
std::shared_ptr<llvm::cas::ActionCache> ActionCache,
DiagnosticEngine &Diagnostics, bool ParallelScan);
DiagnosticEngine &Diagnostics, bool ParallelScan,
bool EmitScanRemarks);

/// Identify the scanner invocation's main module's dependencies
llvm::ErrorOr<ModuleDependencyInfo>
Expand Down Expand Up @@ -347,7 +374,7 @@ class ModuleDependencyScanner {
/// For the provided collection of unresolved imports
/// belonging to identified Swift dependnecies, execute a parallel
/// query to the Clang dependency scanner for each import's module identifier.
void performParallelClangModuleLookup(
void performClangModuleLookup(
const ImportStatementInfoMap &unresolvedImportsMap,
const ImportStatementInfoMap &unresolvedOptionalImportsMap,
BatchClangModuleLookupResult &result);
Expand Down Expand Up @@ -396,7 +423,7 @@ class ModuleDependencyScanner {
private:
const CompilerInvocation &ScanCompilerInvocation;
ASTContext &ScanASTContext;
ModuleDependencyIssueReporter IssueReporter;
DependencyScannerDiagnosticReporter ScanDiagnosticReporter;

/// The location of where the explicitly-built modules will be output to
std::string ModuleOutputPath;
Expand Down
4 changes: 2 additions & 2 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,8 @@ class FrontendOptions {
/// The path at which to either serialize or deserialize the dependency scanner cache.
std::string SerializedDependencyScannerCachePath;

/// Emit remarks indicating use of the serialized module dependency scanning cache.
bool EmitDependencyScannerCacheRemarks = false;
/// Emit dependency scanning related remarks.
bool EmitDependencyScannerRemarks = false;

/// The path at which the dependency scanner can write generated files.
std::string ScannerOutputDir;
Expand Down
4 changes: 2 additions & 2 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,8 @@ def validate_prior_dependency_scan_cache : Flag<["-"], "validate-prior-dependenc
def dependency_scan_cache_path : Separate<["-"], "dependency-scan-cache-path">,
HelpText<"The path to output the dependency scanner's internal state.">;

def dependency_scan_cache_remarks : Flag<["-"], "Rdependency-scan-cache">,
HelpText<"Emit remarks indicating use of the serialized module dependency scanning cache.">;
def dependency_scan_remarks : Flag<["-"], "Rdependency-scan">,
HelpText<"Emit remarks for various steps taken by the dependency scanner.">;

def parallel_scan : Flag<["-"], "parallel-scan">,
HelpText<"Perform dependency scanning in-parallel.">;
Expand Down
10 changes: 8 additions & 2 deletions lib/AST/ModuleDependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,14 @@ bool ModuleDependenciesCache::hasSwiftDependency(StringRef moduleName) const {
return findSwiftDependency(moduleName).has_value();
}

int ModuleDependenciesCache::numberOfClangDependencies() const {
return ModuleDependenciesMap.at(ModuleDependencyKind::Clang).size();
}
int ModuleDependenciesCache::numberOfSwiftDependencies() const {
return ModuleDependenciesMap.at(ModuleDependencyKind::SwiftInterface).size() +
ModuleDependenciesMap.at(ModuleDependencyKind::SwiftBinary).size();
}

void ModuleDependenciesCache::recordDependency(
StringRef moduleName, ModuleDependencyInfo dependency) {
auto dependenciesKind = dependency.getKind();
Expand Down Expand Up @@ -908,7 +916,6 @@ void ModuleDependenciesCache::setSwiftOverlayDependencies(
ModuleDependencyID moduleID,
const ArrayRef<ModuleDependencyID> dependencyIDs) {
auto dependencyInfo = findKnownDependency(moduleID);
assert(dependencyInfo.getSwiftOverlayDependencies().empty());
#ifndef NDEBUG
for (const auto &depID : dependencyIDs)
assert(depID.Kind != ModuleDependencyKind::Clang);
Expand All @@ -923,7 +930,6 @@ void ModuleDependenciesCache::setCrossImportOverlayDependencies(
ModuleDependencyID moduleID,
const ModuleDependencyIDCollectionView dependencyIDs) {
auto dependencyInfo = findKnownDependency(moduleID);
assert(dependencyInfo.getCrossImportOverlayDependencies().empty());
// Copy the existing info to a mutable one we can then replace it with,
// after setting its overlay dependencies.
auto updatedDependencyInfo = dependencyInfo;
Expand Down
Loading