| //===--- SerializedModuleLoader.h - Import Swift modules --------*- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SERIALIZATION_MODULELOADER_H |
| #define SWIFT_SERIALIZATION_MODULELOADER_H |
| |
| #include "swift/AST/FileUnit.h" |
| #include "swift/AST/Module.h" |
| #include "swift/AST/ModuleLoader.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| |
| namespace swift { |
| class ModuleFile; |
| namespace file_types { |
| enum ID : uint8_t; |
| } |
| |
| /// Spceifies how to load modules when both a module interface and serialized |
| /// AST are present, or whether to disallow one format or the other altogether. |
| enum class ModuleLoadingMode { |
| PreferInterface, |
| PreferSerialized, |
| OnlyInterface, |
| OnlySerialized |
| }; |
| |
| /// Helper type used to pass and compute the sets of related filenames used by |
| /// \c SerializedModuleLoader subclasses. |
| struct SerializedModuleBaseName { |
| /// The base filename, wtihout any extension. |
| SmallString<256> baseName; |
| |
| /// Creates a \c SerializedModuleBaseName. |
| SerializedModuleBaseName(StringRef baseName) : baseName(baseName) { } |
| |
| /// Creates a \c SerializedModuleBaseName by contextualizing an existing one |
| /// with a \c parentDir. |
| SerializedModuleBaseName(StringRef parentDir, |
| const SerializedModuleBaseName &name); |
| |
| /// Gets the filename with a particular extension appended to it. |
| std::string getName(file_types::ID fileTy) const; |
| }; |
| |
| /// Common functionality shared between \c ImplicitSerializedModuleLoader, |
| /// \c ModuleInterfaceLoader, \c ExplicitSwiftModuleLoader |
| /// and \c MemoryBufferSerializedModuleLoader. |
| class SerializedModuleLoaderBase : public ModuleLoader { |
| /// A { module, generation # } pair. |
| using LoadedModulePair = std::pair<std::unique_ptr<ModuleFile>, unsigned>; |
| std::vector<LoadedModulePair> LoadedModuleFiles; |
| |
| SmallVector<std::unique_ptr<ModuleFile>, 2> OrphanedModuleFiles; |
| |
| protected: |
| ASTContext &Ctx; |
| ModuleLoadingMode LoadMode; |
| bool IgnoreSwiftSourceInfoFile; |
| SerializedModuleLoaderBase(ASTContext &ctx, DependencyTracker *tracker, |
| ModuleLoadingMode LoadMode, |
| bool IgnoreSwiftSourceInfoFile); |
| |
| void collectVisibleTopLevelModuleNamesImpl(SmallVectorImpl<Identifier> &names, |
| StringRef extension) const; |
| |
| virtual bool findModule(ImportPath::Element moduleID, |
| SmallVectorImpl<char> *moduleInterfacePath, |
| std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer, |
| bool &isFramework, bool &isSystemModule); |
| |
| /// Attempts to search the provided directory for a loadable serialized |
| /// .swiftmodule with the provided `ModuleFilename`. Subclasses must |
| /// override this method to perform their custom module lookup behavior. |
| /// |
| /// If such a module could not be loaded, the subclass must return a |
| /// `std::error_code` indicating the failure. There are two specific error |
| /// codes that will be treated specially: |
| /// - `errc::no_such_file_or_directory`: The module loader will stop looking |
| /// for loadable modules and will diagnose the lookup failure. |
| /// - `errc::not_supported`: The module loader will stop looking for loadable |
| /// modules and will defer to the remaining module loaders to look up this |
| /// module. |
| virtual std::error_code findModuleFilesInDirectory( |
| ImportPath::Element ModuleID, |
| const SerializedModuleBaseName &BaseName, |
| SmallVectorImpl<char> *ModuleInterfacePath, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer, |
| bool IsFramework) = 0; |
| |
| std::error_code |
| openModuleFile( |
| ImportPath::Element ModuleID, |
| const SerializedModuleBaseName &BaseName, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer); |
| |
| std::error_code |
| openModuleDocFileIfPresent( |
| ImportPath::Element ModuleID, |
| const SerializedModuleBaseName &BaseName, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer); |
| |
| std::error_code |
| openModuleSourceInfoFileIfPresent( |
| ImportPath::Element ModuleID, |
| const SerializedModuleBaseName &BaseName, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer); |
| |
| /// If the module loader subclass knows that all options have been tried for |
| /// loading an architecture-specific file out of a swiftmodule bundle, try |
| /// to list the architectures that \e are present. |
| /// |
| /// \returns true if an error diagnostic was emitted |
| virtual bool maybeDiagnoseTargetMismatch( |
| SourceLoc sourceLocation, |
| StringRef moduleName, |
| const SerializedModuleBaseName &BaseName) { |
| return false; |
| } |
| |
| /// Determines if the provided path is a cached artifact for dependency |
| /// tracking purposes. |
| virtual bool isCached(StringRef DepPath) { |
| return false; |
| } |
| |
| /// Scan the given serialized module file to determine dependencies. |
| llvm::ErrorOr<ModuleDependencies> scanModuleFile(Twine modulePath); |
| |
| /// Load the module file into a buffer and also collect its module name. |
| static std::unique_ptr<llvm::MemoryBuffer> |
| getModuleName(ASTContext &Ctx, StringRef modulePath, std::string &Name); |
| public: |
| virtual ~SerializedModuleLoaderBase(); |
| SerializedModuleLoaderBase(const SerializedModuleLoaderBase &) = delete; |
| SerializedModuleLoaderBase(SerializedModuleLoaderBase &&) = delete; |
| SerializedModuleLoaderBase &operator=(const SerializedModuleLoaderBase &) = delete; |
| SerializedModuleLoaderBase &operator=(SerializedModuleLoaderBase &&) = delete; |
| |
| /// Attempt to load a serialized AST into the given module. |
| /// |
| /// If the AST cannot be loaded and \p diagLoc is present, a diagnostic is |
| /// printed. (Note that \p diagLoc is allowed to be invalid.) |
| LoadedFile * |
| loadAST(ModuleDecl &M, Optional<SourceLoc> diagLoc, |
| StringRef moduleInterfacePath, |
| std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> moduleSourceInfoInputBuffer, |
| bool isFramework); |
| |
| /// Check whether the module with a given name can be imported without |
| /// importing it. |
| /// |
| /// Note that even if this check succeeds, errors may still occur if the |
| /// module is loaded in full. |
| virtual bool canImportModule(ImportPath::Element named) override; |
| |
| /// Import a module with the given module path. |
| /// |
| /// \param importLoc The location of the 'import' keyword. |
| /// |
| /// \param path A sequence of (identifier, location) pairs that denote |
| /// the dotted module name to load, e.g., AppKit.NSWindow. |
| /// |
| /// \returns the module referenced, if it could be loaded. Otherwise, |
| /// emits a diagnostic and returns a FailedImportModule object. |
| virtual ModuleDecl * |
| loadModule(SourceLoc importLoc, |
| ImportPath::Module path) override; |
| |
| |
| virtual void loadExtensions(NominalTypeDecl *nominal, |
| unsigned previousGeneration) override; |
| |
| virtual void loadObjCMethods( |
| ClassDecl *classDecl, |
| ObjCSelector selector, |
| bool isInstanceMethod, |
| unsigned previousGeneration, |
| llvm::TinyPtrVector<AbstractFunctionDecl *> &methods) override; |
| |
| virtual void loadDerivativeFunctionConfigurations( |
| AbstractFunctionDecl *originalAFD, unsigned previousGeneration, |
| llvm::SetVector<AutoDiffConfig> &results) override; |
| |
| virtual void verifyAllModules() override; |
| |
| virtual Optional<ModuleDependencies> getModuleDependencies( |
| StringRef moduleName, ModuleDependenciesCache &cache, |
| InterfaceSubContextDelegate &delegate) override; |
| }; |
| |
| /// Imports serialized Swift modules into an ASTContext. |
| class ImplicitSerializedModuleLoader : public SerializedModuleLoaderBase { |
| |
| ImplicitSerializedModuleLoader(ASTContext &ctx, DependencyTracker *tracker, |
| ModuleLoadingMode loadMode, bool IgnoreSwiftSourceInfo) |
| : SerializedModuleLoaderBase(ctx, tracker, loadMode, IgnoreSwiftSourceInfo) |
| {} |
| |
| std::error_code findModuleFilesInDirectory( |
| ImportPath::Element ModuleID, |
| const SerializedModuleBaseName &BaseName, |
| SmallVectorImpl<char> *ModuleInterfacePath, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer, |
| bool IsFramework) override; |
| |
| bool maybeDiagnoseTargetMismatch( |
| SourceLoc sourceLocation, |
| StringRef moduleName, |
| const SerializedModuleBaseName &BaseName) override; |
| |
| public: |
| virtual ~ImplicitSerializedModuleLoader(); |
| |
| /// Append visible module names to \p names. Note that names are possibly |
| /// duplicated, and not guaranteed to be ordered in any way. |
| void collectVisibleTopLevelModuleNames( |
| SmallVectorImpl<Identifier> &names) const override; |
| |
| /// Create a new importer that can load serialized Swift modules |
| /// into the given ASTContext. |
| static std::unique_ptr<ImplicitSerializedModuleLoader> |
| create(ASTContext &ctx, DependencyTracker *tracker = nullptr, |
| ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized, |
| bool IgnoreSwiftSourceInfo = false) { |
| return std::unique_ptr<ImplicitSerializedModuleLoader>{ |
| new ImplicitSerializedModuleLoader(ctx, tracker, loadMode, IgnoreSwiftSourceInfo) |
| }; |
| } |
| }; |
| |
| /// Imports serialized Swift modules from a MemoryBuffer into an ASTContext. |
| /// This interface is primarily used by LLDB. |
| class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase { |
| llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> MemoryBuffers; |
| |
| MemoryBufferSerializedModuleLoader(ASTContext &ctx, |
| DependencyTracker *tracker, |
| ModuleLoadingMode loadMode, |
| bool IgnoreSwiftSourceInfo) |
| : SerializedModuleLoaderBase(ctx, tracker, loadMode, |
| IgnoreSwiftSourceInfo) {} |
| |
| std::error_code findModuleFilesInDirectory( |
| ImportPath::Element ModuleID, |
| const SerializedModuleBaseName &BaseName, |
| SmallVectorImpl<char> *ModuleInterfacePath, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer, |
| bool IsFramework) override; |
| |
| bool maybeDiagnoseTargetMismatch( |
| SourceLoc sourceLocation, |
| StringRef moduleName, |
| const SerializedModuleBaseName &BaseName) override; |
| |
| public: |
| virtual ~MemoryBufferSerializedModuleLoader(); |
| |
| bool canImportModule(ImportPath::Element named) override; |
| ModuleDecl * |
| loadModule(SourceLoc importLoc, |
| ImportPath::Module path) override; |
| |
| /// Register a memory buffer that contains the serialized module for the given |
| /// access path. This API is intended to be used by LLDB to add swiftmodules |
| /// discovered in the __swift_ast section of a Mach-O file (or the .swift_ast |
| /// section of an ELF file) to the search path. |
| /// |
| /// FIXME: make this an actual import *path* once submodules are designed. |
| void registerMemoryBuffer(StringRef importPath, |
| std::unique_ptr<llvm::MemoryBuffer> input) { |
| MemoryBuffers[importPath] = std::move(input); |
| } |
| |
| void collectVisibleTopLevelModuleNames( |
| SmallVectorImpl<Identifier> &names) const override {} |
| |
| /// Create a new importer that can load serialized Swift modules |
| /// into the given ASTContext. |
| static std::unique_ptr<MemoryBufferSerializedModuleLoader> |
| create(ASTContext &ctx, DependencyTracker *tracker = nullptr, |
| ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized, |
| bool IgnoreSwiftSourceInfo = false) { |
| return std::unique_ptr<MemoryBufferSerializedModuleLoader>{ |
| new MemoryBufferSerializedModuleLoader(ctx, tracker, loadMode, |
| IgnoreSwiftSourceInfo)}; |
| } |
| }; |
| |
| |
| /// A file-unit loaded from a serialized AST file. |
| class SerializedASTFile final : public LoadedFile { |
| friend class SerializedModuleLoaderBase; |
| friend class SerializedSILLoader; |
| friend class ModuleFile; |
| |
| ModuleFile &File; |
| |
| SerializedASTFile(ModuleDecl &M, ModuleFile &file) |
| : LoadedFile(FileUnitKind::SerializedAST, M), File(file) {} |
| |
| void |
| collectLinkLibrariesFromImports(ModuleDecl::LinkLibraryCallback callback) const; |
| |
| public: |
| /// Whether this represents a '.sib' file. |
| bool isSIB() const; |
| |
| /// Returns the language version that was used to compile the contents of this |
| /// file. |
| const version::Version &getLanguageVersionBuiltWith() const; |
| |
| virtual bool hadLoadError() const override; |
| |
| virtual bool isSystemModule() const override; |
| |
| virtual void lookupValue(DeclName name, NLKind lookupKind, |
| SmallVectorImpl<ValueDecl*> &results) const override; |
| |
| virtual StringRef |
| getFilenameForPrivateDecl(const ValueDecl *decl) const override; |
| |
| virtual TypeDecl *lookupLocalType(StringRef MangledName) const override; |
| |
| virtual OpaqueTypeDecl * |
| lookupOpaqueResultType(StringRef MangledName) override; |
| |
| virtual TypeDecl * |
| lookupNestedType(Identifier name, |
| const NominalTypeDecl *parent) const override; |
| |
| protected: |
| virtual void |
| lookupOperatorDirect(Identifier name, OperatorFixity fixity, |
| TinyPtrVector<OperatorDecl *> &results) const override; |
| |
| virtual void lookupPrecedenceGroupDirect( |
| Identifier name, |
| TinyPtrVector<PrecedenceGroupDecl *> &results) const override; |
| |
| public: |
| virtual void lookupVisibleDecls(ImportPath::Access accessPath, |
| VisibleDeclConsumer &consumer, |
| NLKind lookupKind) const override; |
| |
| virtual void lookupClassMembers(ImportPath::Access accessPath, |
| VisibleDeclConsumer &consumer) const override; |
| |
| virtual void |
| lookupClassMember(ImportPath::Access accessPath, DeclName name, |
| SmallVectorImpl<ValueDecl*> &decls) const override; |
| |
| /// Find all Objective-C methods with the given selector. |
| void lookupObjCMethods( |
| ObjCSelector selector, |
| SmallVectorImpl<AbstractFunctionDecl *> &results) const override; |
| |
| Optional<Fingerprint> |
| loadFingerprint(const IterableDeclContext *IDC) const override; |
| |
| virtual void |
| lookupImportedSPIGroups( |
| const ModuleDecl *importedModule, |
| llvm::SmallSetVector<Identifier, 4> &spiGroups) const override; |
| |
| Optional<CommentInfo> getCommentForDecl(const Decl *D) const override; |
| |
| Optional<StringRef> getGroupNameForDecl(const Decl *D) const override; |
| |
| |
| Optional<StringRef> getSourceFileNameForDecl(const Decl *D) const override; |
| |
| Optional<unsigned> getSourceOrderForDecl(const Decl *D) const override; |
| |
| Optional<StringRef> getGroupNameByUSR(StringRef USR) const override; |
| |
| Optional<BasicDeclLocs> getBasicLocsForDecl(const Decl *D) const override; |
| |
| void collectAllGroups(std::vector<StringRef> &Names) const override; |
| |
| virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override; |
| |
| virtual void getExportedPrespecializations( |
| SmallVectorImpl<Decl *> &results) const override; |
| |
| virtual void |
| getTopLevelDeclsWhereAttributesMatch( |
| SmallVectorImpl<Decl*> &Results, |
| llvm::function_ref<bool(DeclAttributes)> matchAttributes) const override; |
| |
| virtual void |
| getOperatorDecls(SmallVectorImpl<OperatorDecl *> &results) const override; |
| |
| virtual void |
| getPrecedenceGroups(SmallVectorImpl<PrecedenceGroupDecl*> &Results) const override; |
| |
| virtual void |
| getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &results) const override; |
| virtual void |
| getOpaqueReturnTypeDecls(SmallVectorImpl<OpaqueTypeDecl*> &results) const override; |
| |
| virtual void getDisplayDecls(SmallVectorImpl<Decl*> &results) const override; |
| |
| virtual void |
| getImportedModules(SmallVectorImpl<ImportedModule> &imports, |
| ModuleDecl::ImportFilter filter) const override; |
| |
| virtual void |
| collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const override; |
| |
| Identifier getDiscriminatorForPrivateValue(const ValueDecl *D) const override; |
| |
| virtual StringRef getFilename() const override; |
| |
| virtual StringRef getModuleDefiningPath() const override; |
| |
| Decl *getMainDecl() const override; |
| |
| bool hasEntryPoint() const override; |
| |
| virtual const clang::Module *getUnderlyingClangModule() const override; |
| |
| virtual ModuleDecl *getUnderlyingModuleIfOverlay() const override; |
| |
| virtual bool getAllGenericSignatures( |
| SmallVectorImpl<GenericSignature> &genericSignatures) |
| override; |
| |
| StringRef getTargetTriple() const; |
| |
| static bool classof(const FileUnit *file) { |
| return file->getKind() == FileUnitKind::SerializedAST; |
| } |
| static bool classof(const DeclContext *DC) { |
| return isa<FileUnit>(DC) && classof(cast<FileUnit>(DC)); |
| } |
| }; |
| |
| |
| } // end namespace swift |
| |
| #endif |