//===--- ModuleDependencies.h - Module Dependencies -------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines data structures for capturing module dependencies. // //===----------------------------------------------------------------------===// #ifndef SWIFT_AST_MODULE_DEPENDENCIES_H #define SWIFT_AST_MODULE_DEPENDENCIES_H #include "swift/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSet.h" #include #include namespace swift { class ClangModuleDependenciesCacheImpl; class SourceFile; /// Which kind of module dependencies we are looking for. enum class ModuleDependenciesKind : int8_t { Swift, Clang, }; /// Base class for the variant storage of ModuleDependencies. class ModuleDependenciesStorageBase { public: const bool isSwiftModule; ModuleDependenciesStorageBase(bool isSwiftModule, const std::string &compiledModulePath) : isSwiftModule(isSwiftModule), compiledModulePath(compiledModulePath) { } virtual ModuleDependenciesStorageBase *clone() const = 0; virtual ~ModuleDependenciesStorageBase(); /// The path to the compiled module file. const std::string compiledModulePath; /// The set of modules on which this module depends. std::vector moduleDependencies; }; /// Describes the dependencies of a Swift module. class SwiftModuleDependenciesStorage : public ModuleDependenciesStorageBase { public: /// The Swift interface file, if it can be used to generate the module file. const Optional swiftInterfaceFile; /// Bridging header file, if there is one. Optional bridgingHeaderFile; /// Swift source files that are part of the Swift module, when known. std::vector sourceFiles; /// Source files on which the bridging header depends. std::vector bridgingSourceFiles; SwiftModuleDependenciesStorage( const std::string &compiledModulePath, const Optional &swiftInterfaceFile ) : ModuleDependenciesStorageBase(/*isSwiftModule=*/true, compiledModulePath), swiftInterfaceFile(swiftInterfaceFile) { } ModuleDependenciesStorageBase *clone() const override { return new SwiftModuleDependenciesStorage(*this); } static bool classof(const ModuleDependenciesStorageBase *base) { return base->isSwiftModule; } }; class ClangModuleDependenciesStorage : public ModuleDependenciesStorageBase { public: /// The module map file used to generate the Clang module. const std::string moduleMapFile; /// The file dependencies const std::vector fileDependencies; ClangModuleDependenciesStorage( const std::string &compiledModulePath, const std::string &moduleMapFile, const std::vector &fileDependencies ) : ModuleDependenciesStorageBase(/*isSwiftModule=*/false, compiledModulePath), moduleMapFile(moduleMapFile), fileDependencies(fileDependencies) { } ModuleDependenciesStorageBase *clone() const override { return new ClangModuleDependenciesStorage(*this); } static bool classof(const ModuleDependenciesStorageBase *base) { return !base->isSwiftModule; } }; /// Describes the dependencies of a given module. class ModuleDependencies { private: std::unique_ptr storage; ModuleDependencies(std::unique_ptr &&storage) : storage(std::move(storage)) { } public: ModuleDependencies(const ModuleDependencies &other) : storage(other.storage->clone()) { } ModuleDependencies(ModuleDependencies &&other) = default; ModuleDependencies &operator=(const ModuleDependencies &other) { storage.reset(other.storage->clone()); return *this; } ModuleDependencies &operator=(ModuleDependencies &&other) = default; /// Describe the module dependencies for a Swift module that can be /// built from a Swift interface file (\c .swiftinterface). static ModuleDependencies forSwiftInterface( const std::string &compiledModulePath, const std::string &swiftInterfaceFile) { return ModuleDependencies( std::make_unique( compiledModulePath, swiftInterfaceFile)); } /// Describe the module dependencies for a serialized or parsed Swift module. static ModuleDependencies forSwiftModule( const std::string &compiledModulePath) { return ModuleDependencies( std::make_unique( compiledModulePath, None)); } /// Describe the module dependencies for a Clang module that can be /// built from a module map and headers. static ModuleDependencies forClangModule( const std::string &compiledModulePath, const std::string &moduleMapFile, const std::vector &fileDependencies) { return ModuleDependencies( std::make_unique(compiledModulePath, moduleMapFile, fileDependencies)); } /// Retrieve the path to the compiled module. const std::string getCompiledModulePath() const { return storage->compiledModulePath; } /// Retrieve the module-level dependencies. ArrayRef getModuleDependencies() const { return storage->moduleDependencies; } /// Whether the dependencies are for a Swift module. bool isSwiftModule() const; ModuleDependenciesKind getKind() const { return isSwiftModule() ? ModuleDependenciesKind::Swift : ModuleDependenciesKind::Clang; } /// Retrieve the dependencies for a Swift module. const SwiftModuleDependenciesStorage *getAsSwiftModule() const; /// Retrieve the dependencies for a Clang module. const ClangModuleDependenciesStorage *getAsClangModule() const; /// Add a dependency on the given module, if it was not already in the set. void addModuleDependency(StringRef module, llvm::StringSet<> &alreadyAddedModules); /// Add all of the module dependencies for the imports in the given source /// file to the set of module dependencies. void addModuleDependencies(const SourceFile &sf, llvm::StringSet<> &alreadyAddedModules); /// Add a bridging header to a Swift module's dependencies. void addBridgingHeader(StringRef bridgingHeader); }; using ModuleDependencyID = std::pair; /// A cache describing the set of module dependencies that has been queried /// thus far. class ModuleDependenciesCache { /// All cached module dependencies, in the order in which they were /// encountered. std::vector AllModules; /// Dependencies for Swift modules that have already been computed. llvm::StringMap SwiftModuleDependencies; /// Dependencies for Clang modules that have already been computed. llvm::StringMap ClangModuleDependencies; /// Additional information needed for Clang dependency scanning. ClangModuleDependenciesCacheImpl *clangImpl = nullptr; /// Function that will delete \c clangImpl properly. void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *) = nullptr; /// Free up the storage associated with the Clang implementation. void destroyClangImpl() { if (this->clangImplDeleter) this->clangImplDeleter(this->clangImpl); } /// Retrieve the dependencies map that corresponds to the given dependency /// kind. llvm::StringMap &getDependenciesMap( ModuleDependenciesKind kind); const llvm::StringMap &getDependenciesMap( ModuleDependenciesKind kind) const; public: ModuleDependenciesCache() { } ModuleDependenciesCache(const ModuleDependenciesCache &) = delete; ModuleDependenciesCache &operator=(const ModuleDependenciesCache &) = delete; ~ModuleDependenciesCache() { destroyClangImpl(); } /// Set the Clang-specific implementation data. void setClangImpl( ClangModuleDependenciesCacheImpl *clangImpl, void (*clangImplDeleter)(ClangModuleDependenciesCacheImpl *)) { destroyClangImpl(); this->clangImpl = clangImpl; this->clangImplDeleter = clangImplDeleter; } /// Retrieve the Clang-specific implementation data; ClangModuleDependenciesCacheImpl *getClangImpl() const { return clangImpl; } /// Whether we have cached dependency information for the given module. bool hasDependencies(StringRef moduleName, Optional kind) const; /// Look for module dependencies for a module with the given name. /// /// \returns the cached result, or \c None if there is no cached entry. Optional findDependencies( StringRef moduleName, Optional kind) const; /// Record dependencies for the given module. void recordDependencies(StringRef moduleName, ModuleDependencies dependencies, ModuleDependenciesKind kind); /// Reference the list of all module dependencies. const std::vector &getAllModules() const { return AllModules; } }; } #endif /* SWIFT_AST_MODULE_DEPENDENCIES_H */