blob: cb1c18581410bb68ac86133a71456d8c7c1b0741 [file] [log] [blame]
//===--- 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