| //===--- 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; |
| class LazyResolver; |
| |
| /// 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 |
| }; |
| |
| /// Common functionality shared between \c SerializedModuleLoader and |
| /// \c ModuleInterfaceLoader. |
| 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<llvm::MemoryBuffer>, 2> OrphanedMemoryBuffers; |
| |
| protected: |
| ASTContext &Ctx; |
| ModuleLoadingMode LoadMode; |
| SerializedModuleLoaderBase(ASTContext &ctx, DependencyTracker *tracker, |
| ModuleLoadingMode LoadMode); |
| |
| void collectVisibleTopLevelModuleNamesImpl(SmallVectorImpl<Identifier> &names, |
| StringRef extension) const; |
| |
| using AccessPathElem = std::pair<Identifier, SourceLoc>; |
| bool findModule(AccessPathElem moduleID, |
| std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer, |
| 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( |
| AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename, |
| StringRef ModuleDocFilename, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) = 0; |
| |
| std::error_code |
| openModuleFiles(AccessPathElem ModuleID, |
| StringRef ModulePath, StringRef ModuleDocPath, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer); |
| |
| std::error_code |
| openModuleDocFile(AccessPathElem ModuleID, |
| StringRef ModuleDocPath, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer); |
| |
| /// 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, |
| StringRef archName, |
| StringRef directoryPath) { |
| return false; |
| } |
| |
| /// Determines if the provided path is a cached artifact for dependency |
| /// tracking purposes. |
| virtual bool isCached(StringRef DepPath) { |
| return false; |
| } |
| |
| 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.) |
| FileUnit *loadAST(ModuleDecl &M, Optional<SourceLoc> diagLoc, |
| std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer, |
| bool isFramework, bool treatAsPartialModule); |
| |
| /// 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(std::pair<Identifier, SourceLoc> 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, |
| ArrayRef<std::pair<Identifier, SourceLoc>> 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 verifyAllModules() override; |
| }; |
| |
| /// Imports serialized Swift modules into an ASTContext. |
| class SerializedModuleLoader : public SerializedModuleLoaderBase { |
| |
| SerializedModuleLoader(ASTContext &ctx, DependencyTracker *tracker, |
| ModuleLoadingMode loadMode) |
| : SerializedModuleLoaderBase(ctx, tracker, loadMode) |
| {} |
| |
| std::error_code findModuleFilesInDirectory( |
| AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename, |
| StringRef ModuleDocFilename, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) override; |
| |
| bool maybeDiagnoseTargetMismatch(SourceLoc sourceLocation, |
| StringRef moduleName, |
| StringRef archName, |
| StringRef directoryPath) override; |
| |
| public: |
| virtual ~SerializedModuleLoader(); |
| |
| /// 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<SerializedModuleLoader> |
| create(ASTContext &ctx, DependencyTracker *tracker = nullptr, |
| ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized) { |
| return std::unique_ptr<SerializedModuleLoader>{ |
| new SerializedModuleLoader(ctx, tracker, loadMode) |
| }; |
| } |
| }; |
| |
| /// 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) |
| : SerializedModuleLoaderBase(ctx, tracker, loadMode) {} |
| |
| std::error_code findModuleFilesInDirectory( |
| AccessPathElem ModuleID, StringRef DirPath, StringRef ModuleFilename, |
| StringRef ModuleDocFilename, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, |
| std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) override; |
| |
| bool maybeDiagnoseTargetMismatch(SourceLoc sourceLocation, |
| StringRef moduleName, |
| StringRef archName, |
| StringRef directoryPath) override; |
| |
| public: |
| virtual ~MemoryBufferSerializedModuleLoader(); |
| |
| bool canImportModule(std::pair<Identifier, SourceLoc> named) override; |
| ModuleDecl * |
| loadModule(SourceLoc importLoc, |
| ArrayRef<std::pair<Identifier, SourceLoc>> 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 access *path* once submodules are designed. |
| void registerMemoryBuffer(StringRef AccessPath, |
| std::unique_ptr<llvm::MemoryBuffer> input) { |
| MemoryBuffers[AccessPath] = 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) { |
| return std::unique_ptr<MemoryBufferSerializedModuleLoader>{ |
| new MemoryBufferSerializedModuleLoader(ctx, tracker, loadMode)}; |
| } |
| }; |
| |
| |
| /// 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; |
| |
| bool IsSIB; |
| |
| SerializedASTFile(ModuleDecl &M, ModuleFile &file, bool isSIB = false) |
| : LoadedFile(FileUnitKind::SerializedAST, M), File(file), IsSIB(isSIB) {} |
| |
| void |
| collectLinkLibrariesFromImports(ModuleDecl::LinkLibraryCallback callback) const; |
| |
| public: |
| bool isSIB() const { return IsSIB; } |
| |
| /// Returns the language version that was used to compile the contents of this |
| /// file. |
| const version::Version &getLanguageVersionBuiltWith() const; |
| |
| 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; |
| |
| virtual OperatorDecl *lookupOperator(Identifier name, |
| DeclKind fixity) const override; |
| |
| virtual PrecedenceGroupDecl * |
| lookupPrecedenceGroup(Identifier name) const override; |
| |
| virtual void lookupVisibleDecls(ModuleDecl::AccessPathTy accessPath, |
| VisibleDeclConsumer &consumer, |
| NLKind lookupKind) const override; |
| |
| virtual void lookupClassMembers(ModuleDecl::AccessPathTy accessPath, |
| VisibleDeclConsumer &consumer) const override; |
| |
| virtual void |
| lookupClassMember(ModuleDecl::AccessPathTy 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<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; |
| |
| void collectAllGroups(std::vector<StringRef> &Names) const override; |
| |
| virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &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<ModuleDecl::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; |
| |
| ClassDecl *getMainClass() const override; |
| |
| bool hasEntryPoint() const override; |
| |
| virtual const clang::Module *getUnderlyingClangModule() const override; |
| |
| virtual bool getAllGenericSignatures( |
| SmallVectorImpl<GenericSignature> &genericSignatures) |
| override; |
| |
| 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 |