Skip to content

Commit e84be85

Browse files
authored
Merge pull request #38704 from artemcm/DependencyScanningCherryFarming
[5.5][Dependency Scanning] Cherry-pick dependency scanner changes required for Explicit Module Builds
2 parents e44a4f1 + 0966277 commit e84be85

36 files changed

+2313
-176
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,30 @@ swiftscan_batch_scan_result_create(swiftscan_scanner_t scanner,
337337
SWIFTSCAN_PUBLIC swiftscan_import_set_t swiftscan_import_set_create(
338338
swiftscan_scanner_t scanner, swiftscan_scan_invocation_t invocation);
339339

340+
//=== Scanner Cache Operations --------------------------------------------===//
341+
// The following operations expose an implementation detail of the dependency
342+
// scanner: its module dependencies cache. This is done in order
343+
// to allow clients to perform incremental dependency scans by having the
344+
// scanner's state be serializable and re-usable.
345+
346+
/// For the specified \c scanner instance, serialize its state to the specified file-system \c path .
347+
SWIFTSCAN_PUBLIC void
348+
swiftscan_scanner_cache_serialize(swiftscan_scanner_t scanner,
349+
const char * path);
350+
351+
/// For the specified \c scanner instance, load in scanner state from a file at
352+
/// the specified file-system \c path .
353+
SWIFTSCAN_PUBLIC bool
354+
swiftscan_scanner_cache_load(swiftscan_scanner_t scanner,
355+
const char * path);
356+
357+
/// For the specified \c scanner instance, reset its internal state, ensuring subsequent
358+
/// scanning queries are done "from-scratch".
359+
SWIFTSCAN_PUBLIC void
360+
swiftscan_scanner_cache_reset(swiftscan_scanner_t scanner);
361+
362+
//===----------------------------------------------------------------------===//
363+
340364
SWIFTSCAN_END_DECLS
341365

342366
#endif // SWIFT_C_DEPENDENCY_SCAN_H

include/swift/AST/ASTContext.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "llvm/ADT/PointerIntPair.h"
3838
#include "llvm/ADT/SetVector.h"
3939
#include "llvm/ADT/SmallPtrSet.h"
40+
#include "llvm/ADT/StringSet.h"
4041
#include "llvm/ADT/StringMap.h"
4142
#include "llvm/ADT/TinyPtrVector.h"
4243
#include "llvm/Support/Allocator.h"
@@ -825,6 +826,13 @@ class ASTContext final {
825826
ModuleDependenciesCache &cache,
826827
InterfaceSubContextDelegate &delegate);
827828

829+
/// Compute the extra implicit framework search paths on Apple platforms:
830+
/// $SDKROOT/System/Library/Frameworks/ and $SDKROOT/Library/Frameworks/.
831+
std::vector<std::string> getDarwinImplicitFrameworkSearchPaths() const;
832+
833+
/// Return a set of all possible filesystem locations where modules can be found.
834+
llvm::StringSet<> getAllModuleSearchPathsSet() const;
835+
828836
/// Load extensions to the given nominal type from the external
829837
/// module loaders.
830838
///

include/swift/AST/DiagnosticsCommon.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ ERROR(scanner_find_cycle, none,
192192
ERROR(scanner_arguments_invalid, none,
193193
"dependencies scanner cannot be configured with arguments: '%0'", (StringRef))
194194

195+
WARNING(warn_scaner_deserialize_failed, none,
196+
"Failed to load module scanning dependency cache from: '%0', re-building scanner cache from scratch.", (StringRef))
197+
198+
REMARK(remark_reuse_cache, none,
199+
"Re-using serialized module scanning dependency cache from: '%0'.", (StringRef))
200+
201+
REMARK(remark_save_cache, none,
202+
"Serializing module scanning dependency cache to: '%0'.", (StringRef))
203+
195204
//------------------------------------------------------------------------------
196205
// MARK: custom attribute diagnostics
197206
//------------------------------------------------------------------------------

include/swift/AST/ModuleDependencies.h

Lines changed: 162 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/ADT/StringSet.h"
2626
#include <string>
2727
#include <vector>
28+
#include <unordered_map>
2829

2930
namespace swift {
3031

@@ -35,7 +36,8 @@ class Identifier;
3536

3637
/// Which kind of module dependencies we are looking for.
3738
enum class ModuleDependenciesKind : int8_t {
38-
SwiftTextual,
39+
FirstKind,
40+
SwiftTextual = FirstKind,
3941
SwiftBinary,
4042
// Placeholder dependencies are a kind of dependencies used only by the
4143
// dependency scanner. They are swift modules that the scanner will not be
@@ -61,6 +63,20 @@ enum class ModuleDependenciesKind : int8_t {
6163
// of all targets, individually, have been computed.
6264
SwiftPlaceholder,
6365
Clang,
66+
LastKind = Clang + 1
67+
};
68+
69+
struct ModuleDependenciesKindHash {
70+
std::size_t operator()(ModuleDependenciesKind k) const {
71+
using UnderlyingType = std::underlying_type<ModuleDependenciesKind>::type;
72+
return std::hash<UnderlyingType>{}(static_cast<UnderlyingType>(k));
73+
}
74+
};
75+
76+
/// Details of a given module used for dependency scanner cache queries.
77+
struct ModuleLookupSpecifics {
78+
Optional<ModuleDependenciesKind> kind;
79+
llvm::StringSet<> currentSearchPaths;
6480
};
6581

6682
/// Base class for the variant storage of ModuleDependencies.
@@ -275,8 +291,8 @@ class ModuleDependencies {
275291

276292
/// Describe the module dependencies for a Swift module that can be
277293
/// built from a Swift interface file (\c .swiftinterface).
278-
static ModuleDependencies forSwiftInterface(
279-
const std::string &swiftInterfaceFile,
294+
static ModuleDependencies forSwiftTextualModule(
295+
const Optional<std::string> &swiftInterfaceFile,
280296
ArrayRef<std::string> compiledCandidates,
281297
ArrayRef<StringRef> buildCommands,
282298
ArrayRef<StringRef> extraPCMArgs,
@@ -386,6 +402,9 @@ class ModuleDependencies {
386402
/// Add a bridging header to a Swift module's dependencies.
387403
void addBridgingHeader(StringRef bridgingHeader);
388404

405+
/// Add source files
406+
void addSourceFile(StringRef sourceFile);
407+
389408
/// Add source files that the bridging header depends on.
390409
void addBridgingSourceFile(StringRef bridgingSourceFile);
391410

@@ -400,25 +419,30 @@ class ModuleDependencies {
400419
};
401420

402421
using ModuleDependencyID = std::pair<std::string, ModuleDependenciesKind>;
422+
using ModuleDependenciesVector = llvm::SmallVector<ModuleDependencies, 1>;
403423

404424
/// A cache describing the set of module dependencies that has been queried
405-
/// thus far.
406-
class ModuleDependenciesCache {
425+
/// thus far. This cache records/stores the actual Dependency values and can be
426+
/// preserved across different scanning actions (e.g. in
427+
/// `DependencyScanningTool`). It is not to be queried directly, but is rather
428+
/// meant to be wrapped in an instance of `ModuleDependenciesCache`, responsible
429+
/// for recording new dependencies and answering cache queries in a given scan.
430+
/// Queries to this cache must be disambiguated with a set of search paths to
431+
/// ensure that the returned cached dependency was one that can be found in the
432+
/// current scanning action's filesystem view.
433+
class GlobalModuleDependenciesCache {
407434
/// All cached module dependencies, in the order in which they were
408435
/// encountered.
409436
std::vector<ModuleDependencyID> AllModules;
410437

411-
/// Dependencies for Textual Swift modules that have already been computed.
412-
llvm::StringMap<ModuleDependencies> SwiftTextualModuleDependencies;
413-
414-
/// Dependencies for Binary Swift modules that have already been computed.
415-
llvm::StringMap<ModuleDependencies> SwiftBinaryModuleDependencies;
416-
417-
/// Dependencies for Swift placeholder dependency modules that have already been computed.
418-
llvm::StringMap<ModuleDependencies> SwiftPlaceholderModuleDependencies;
419-
420-
/// Dependencies for Clang modules that have already been computed.
421-
llvm::StringMap<ModuleDependencies> ClangModuleDependencies;
438+
/// Dependencies for modules that have already been computed.
439+
/// This maps a dependency kind to a map of a module's name to a vector of Dependency objects,
440+
/// which correspond to instances of the same module that may have been found
441+
/// in different sets of search paths.
442+
std::unordered_map<ModuleDependenciesKind,
443+
llvm::StringMap<ModuleDependenciesVector>,
444+
ModuleDependenciesKindHash>
445+
ModuleDependenciesKindMap;
422446

423447
/// Additional information needed for Clang dependency scanning.
424448
ClangModuleDependenciesCacheImpl *clangImpl = nullptr;
@@ -434,46 +458,148 @@ class ModuleDependenciesCache {
434458

435459
/// Retrieve the dependencies map that corresponds to the given dependency
436460
/// kind.
437-
llvm::StringMap<ModuleDependencies> &getDependenciesMap(
438-
ModuleDependenciesKind kind);
439-
const llvm::StringMap<ModuleDependencies> &getDependenciesMap(
440-
ModuleDependenciesKind kind) const;
461+
llvm::StringMap<ModuleDependenciesVector> &
462+
getDependenciesMap(ModuleDependenciesKind kind);
463+
const llvm::StringMap<ModuleDependenciesVector> &
464+
getDependenciesMap(ModuleDependenciesKind kind) const;
441465

442466
public:
443-
ModuleDependenciesCache() { }
467+
GlobalModuleDependenciesCache();
468+
GlobalModuleDependenciesCache(const GlobalModuleDependenciesCache &) = delete;
469+
GlobalModuleDependenciesCache &
470+
operator=(const GlobalModuleDependenciesCache &) = delete;
444471

445-
ModuleDependenciesCache(const ModuleDependenciesCache &) = delete;
446-
ModuleDependenciesCache &operator=(const ModuleDependenciesCache &) = delete;
472+
virtual ~GlobalModuleDependenciesCache() { destroyClangImpl(); }
447473

448-
~ModuleDependenciesCache() {
449-
destroyClangImpl();
450-
}
474+
private:
475+
/// Enforce clients not being allowed to query this cache directly, it must be
476+
/// wrapped in an instance of `ModuleDependenciesCache`.
477+
friend class ModuleDependenciesCache;
451478

452479
/// Set the Clang-specific implementation data.
453-
void setClangImpl(
454-
ClangModuleDependenciesCacheImpl *clangImpl,
455-
void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *)) {
480+
virtual void
481+
setClangImpl(ClangModuleDependenciesCacheImpl *clangImpl,
482+
void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *)) {
456483
destroyClangImpl();
457484

458485
this->clangImpl = clangImpl;
459486
this->clangImplDeleter = clangImplDeleter;
460487
}
461488

489+
/// Retrieve the Clang-specific implementation data;
490+
ClangModuleDependenciesCacheImpl *getClangImpl() const { return clangImpl; }
491+
492+
/// Whether we have cached dependency information for the given module.
493+
bool hasDependencies(StringRef moduleName,
494+
ModuleLookupSpecifics details) const;
495+
496+
/// Look for module dependencies for a module with the given name given
497+
/// current search paths.
498+
///
499+
/// \returns the cached result, or \c None if there is no cached entry.
500+
Optional<ModuleDependencies>
501+
findDependencies(StringRef moduleName, ModuleLookupSpecifics details) const;
502+
503+
public:
504+
/// Look for module dependencies for a module with the given name.
505+
/// This method has a deliberately-obtuse name to indicate that it is not to
506+
/// be used for general queries.
507+
///
508+
/// \returns the cached result, or \c None if there is no cached entry.
509+
Optional<ModuleDependenciesVector>
510+
findAllDependenciesIrrespectiveOfSearchPaths(
511+
StringRef moduleName, Optional<ModuleDependenciesKind> kind) const;
512+
513+
/// Record dependencies for the given module.
514+
const ModuleDependencies *recordDependencies(StringRef moduleName,
515+
ModuleDependencies dependencies);
516+
517+
/// Update stored dependencies for the given module.
518+
const ModuleDependencies *updateDependencies(ModuleDependencyID moduleID,
519+
ModuleDependencies dependencies);
520+
521+
/// Reference the list of all module dependencies.
522+
const std::vector<ModuleDependencyID> &getAllModules() const {
523+
return AllModules;
524+
}
525+
};
526+
527+
/// This "local" dependencies cache persists only for the duration of a given
528+
/// scanning action, and wraps an instance of a `GlobalModuleDependenciesCache`
529+
/// which may carry cached scanning information from prior scanning actions.
530+
/// This cache maintains a store of references to all dependencies found within
531+
/// the current scanning action (with their values stored in the global Cache),
532+
/// since these do not require clients to disambiguate them with search paths.
533+
class ModuleDependenciesCache {
534+
private:
535+
GlobalModuleDependenciesCache &globalCache;
536+
537+
/// References to data in `globalCache` for dependencies accimulated during
538+
/// the current scanning action.
539+
std::unordered_map<ModuleDependenciesKind,
540+
llvm::StringMap<const ModuleDependencies *>,
541+
ModuleDependenciesKindHash>
542+
ModuleDependenciesKindMap;
543+
544+
/// Retrieve the dependencies map that corresponds to the given dependency
545+
/// kind.
546+
llvm::StringMap<const ModuleDependencies *> &
547+
getDependencyReferencesMap(ModuleDependenciesKind kind);
548+
const llvm::StringMap<const ModuleDependencies *> &
549+
getDependencyReferencesMap(ModuleDependenciesKind kind) const;
550+
551+
/// Local cache results lookup, only for modules which were discovered during
552+
/// the current scanner invocation.
553+
bool hasDependencies(StringRef moduleName,
554+
Optional<ModuleDependenciesKind> kind) const;
555+
556+
/// Local cache results lookup, only for modules which were discovered during
557+
/// the current scanner invocation.
558+
Optional<const ModuleDependencies *>
559+
findDependencies(StringRef moduleName,
560+
Optional<ModuleDependenciesKind> kind) const;
561+
562+
public:
563+
ModuleDependenciesCache(GlobalModuleDependenciesCache &globalCache);
564+
ModuleDependenciesCache(const ModuleDependenciesCache &) = delete;
565+
ModuleDependenciesCache &operator=(const ModuleDependenciesCache &) = delete;
566+
virtual ~ModuleDependenciesCache() {}
567+
568+
public:
569+
/// Set the Clang-specific implementation data.
570+
void
571+
setClangImpl(ClangModuleDependenciesCacheImpl *clangImpl,
572+
void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *)) {
573+
globalCache.setClangImpl(clangImpl, clangImplDeleter);
574+
}
575+
462576
/// Retrieve the Clang-specific implementation data;
463577
ClangModuleDependenciesCacheImpl *getClangImpl() const {
464-
return clangImpl;
578+
return globalCache.getClangImpl();
465579
}
466580

467581
/// Whether we have cached dependency information for the given module.
468582
bool hasDependencies(StringRef moduleName,
469-
Optional<ModuleDependenciesKind> kind) const;
583+
ModuleLookupSpecifics details) const;
584+
585+
/// Look for module dependencies for a module with the given name given
586+
/// current search paths.
587+
///
588+
/// \returns the cached result, or \c None if there is no cached entry.
589+
Optional<ModuleDependencies>
590+
findDependencies(StringRef moduleName, ModuleLookupSpecifics details) const;
470591

471592
/// Look for module dependencies for a module with the given name.
593+
/// This method has a deliberately-obtuse name to indicate that it is not to
594+
/// be used for general queries.
472595
///
473596
/// \returns the cached result, or \c None if there is no cached entry.
474-
Optional<ModuleDependencies> findDependencies(
475-
StringRef moduleName,
476-
Optional<ModuleDependenciesKind> kind) const;
597+
Optional<ModuleDependenciesVector>
598+
findAllDependenciesIrrespectiveOfSearchPaths(
599+
StringRef moduleName, Optional<ModuleDependenciesKind> kind) const {
600+
return globalCache.findAllDependenciesIrrespectiveOfSearchPaths(moduleName,
601+
kind);
602+
}
477603

478604
/// Record dependencies for the given module.
479605
void recordDependencies(StringRef moduleName,
@@ -485,10 +611,10 @@ class ModuleDependenciesCache {
485611

486612
/// Reference the list of all module dependencies.
487613
const std::vector<ModuleDependencyID> &getAllModules() const {
488-
return AllModules;
614+
return globalCache.getAllModules();
489615
}
490616
};
491617

492-
}
618+
} // namespace swift
493619

494620
#endif /* SWIFT_AST_MODULE_DEPENDENCIES_H */

include/swift/DependencyScan/DependencyScanningTool.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ class DependencyScanningTool {
5757
const std::vector<BatchScanInput> &BatchInput,
5858
const llvm::StringSet<> &PlaceholderModules);
5959

60+
/// Writes the current `SharedCache` instance to a specified FileSystem path.
61+
void serializeCache(llvm::StringRef path);
62+
/// Loads an instance of a `GlobalModuleDependenciesCache` to serve as the `SharedCache`
63+
/// from a specified FileSystem path.
64+
bool loadCache(llvm::StringRef path);
65+
/// Discard the tool's current `SharedCache` and start anew.
66+
void resetCache();
67+
6068
private:
6169
/// Using the specified invocation command, instantiate a CompilerInstance
6270
/// that will be used for this scan.
@@ -65,7 +73,7 @@ class DependencyScanningTool {
6573

6674
/// Shared cache of module dependencies, re-used by individual full-scan queries
6775
/// during the lifetime of this Tool.
68-
std::unique_ptr<ModuleDependenciesCache> SharedCache;
76+
std::unique_ptr<GlobalModuleDependenciesCache> SharedCache;
6977

7078
/// Shared cache of compiler instances created during batch scanning, corresponding to
7179
/// command-line options specified in the batch scan input entry.

include/swift/DependencyScan/ScanDependencies.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,18 @@ namespace swift {
2727
class CompilerInvocation;
2828
class CompilerInstance;
2929
class ModuleDependenciesCache;
30+
class GlobalModuleDependenciesCache;
3031

3132
namespace dependencies {
3233

34+
//using CompilerArgInstanceCacheMap =
35+
// llvm::StringMap<std::pair<std::unique_ptr<CompilerInstance>,
36+
// std::unique_ptr<ModuleDependenciesCache>>>;
37+
3338
using CompilerArgInstanceCacheMap =
34-
llvm::StringMap<std::pair<std::unique_ptr<CompilerInstance>,
35-
std::unique_ptr<ModuleDependenciesCache>>>;
39+
llvm::StringMap<std::tuple<std::unique_ptr<CompilerInstance>,
40+
std::unique_ptr<GlobalModuleDependenciesCache>,
41+
std::unique_ptr<ModuleDependenciesCache>>>;
3642

3743
struct BatchScanInput {
3844
llvm::StringRef moduleName;

0 commit comments

Comments
 (0)