Files
swift-mirror/include/swift/Serialization/SerializedModuleLoader.h
Jordan Rose 6de91151e2 Record whether a file contains a main entry point in the serialized module.
This isn't being used for much yet, but it will allow us to tell whether
something is an app target even at the module-merging stage, which is a
better way to tell if something is an app than whether it has a bridging
header.

We'll also need this if we ever take advantage of reusing "partial modules"
(serialized ASTs for other parts of the module that aren't affected by the
current source file) for compiling source files in incremental builds;
unfortunately that's unlikely given our dependency model.

Swift SVN r24531
2015-01-19 23:08:57 +00:00

225 lines
7.9 KiB
C++

//===--- SerializedModuleLoader.h - Import Swift modules --------*- c++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SERIALIZATION_MODULELOADER_H
#define SWIFT_SERIALIZATION_MODULELOADER_H
#include "swift/AST/Module.h"
#include "swift/AST/ModuleLoader.h"
#include "llvm/Support/MemoryBuffer.h"
#include <map>
namespace swift {
class ModuleFile;
/// Describes whether a loaded module can be used.
enum class ModuleStatus {
/// The module is valid.
Valid,
/// The module file format is too old to be used by this version of the
/// compiler.
FormatTooOld,
/// The module file format is too new to be used by this version of the
/// compiler.
FormatTooNew,
/// The module file depends on another module that can't be loaded.
MissingDependency,
/// The module file is an overlay for a Clang module, which can't be found.
MissingShadowedModule,
/// The module file is malformed in some way.
Malformed,
/// The module documentation file is malformed in some way.
MalformedDocumentation,
/// The module file's name does not match the module it is being loaded into.
NameMismatch,
/// The module file was built for a different target platform.
TargetIncompatible,
/// The module file was built for a target newer than the current target.
TargetTooNew
};
/// \brief Imports serialized Swift modules into an ASTContext.
class SerializedModuleLoader : public ModuleLoader {
private:
ASTContext &Ctx;
std::map<std::string, std::unique_ptr<llvm::MemoryBuffer> > MemoryBuffers;
/// A { module, generation # } pair.
using LoadedModulePair = std::pair<std::unique_ptr<ModuleFile>, unsigned>;
std::vector<LoadedModulePair> LoadedModuleFiles;
explicit SerializedModuleLoader(ASTContext &ctx, DependencyTracker *tracker);
public:
/// \brief 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) {
return std::unique_ptr<SerializedModuleLoader>{
new SerializedModuleLoader(ctx, tracker)
};
}
~SerializedModuleLoader();
SerializedModuleLoader(const SerializedModuleLoader &) = delete;
SerializedModuleLoader(SerializedModuleLoader &&) = delete;
SerializedModuleLoader &operator=(const SerializedModuleLoader &) = delete;
SerializedModuleLoader &operator=(SerializedModuleLoader &&) = delete;
/// \brief 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 Module *
loadModule(SourceLoc importLoc,
ArrayRef<std::pair<Identifier, SourceLoc>> path) override;
/// 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(Module &M, Optional<SourceLoc> diagLoc,
std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer,
std::unique_ptr<llvm::MemoryBuffer> moduleDocInputBuffer,
bool isFramework = false);
/// \brief 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 __apple_ast
/// section of a Mach-O 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].reset(input.release());
}
virtual void loadExtensions(NominalTypeDecl *nominal,
unsigned previousGeneration) override;
virtual void loadObjCMethods(
ClassDecl *classDecl,
ObjCSelector selector,
bool isInstanceMethod,
unsigned previousGeneration,
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods);
/// Returns true if the data looks like it contains a serialized AST.
static bool isSerializedAST(StringRef data);
/// \see validateSerializedAST()
struct ValidationInfo {
StringRef name = {};
StringRef targetTriple = {};
size_t bytes = 0;
ModuleStatus status = ModuleStatus::Malformed;
};
/// Returns info about the serialized AST in the given data.
///
/// If the returned status is anything but ModuleStatus::Valid, the
/// serialized data cannot be loaded by this version of the compiler. If the
/// returned size is non-zero, it's possible to skip over this module's data,
/// in case there is more data in the buffer. The returned name, which may
/// be empty, directly points into the given data buffer.
///
/// Note that this does not actually try to load the module or validate any
/// of its dependencies; it only checks that it /can/ be loaded.
static ValidationInfo validateSerializedAST(StringRef data);
virtual void verifyAllModules() override;
};
/// A file-unit loaded from a serialized AST file.
class SerializedASTFile final : public LoadedFile {
friend class SerializedModuleLoader;
friend class SerializedSILLoader;
ModuleFile &File;
~SerializedASTFile() = default;
SerializedASTFile(Module &M, ModuleFile &file)
: LoadedFile(FileUnitKind::SerializedAST, M), File(file) {}
public:
ModuleFile &getFile() const { return File; }
virtual bool isSystemModule() const override;
virtual void lookupValue(Module::AccessPathTy accessPath,
DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl*> &results) const override;
virtual OperatorDecl *lookupOperator(Identifier name,
DeclKind fixity) const override;
virtual void lookupVisibleDecls(Module::AccessPathTy accessPath,
VisibleDeclConsumer &consumer,
NLKind lookupKind) const override;
virtual void lookupClassMembers(Module::AccessPathTy accessPath,
VisibleDeclConsumer &consumer) const override;
virtual void
lookupClassMember(Module::AccessPathTy accessPath, DeclName name,
SmallVectorImpl<ValueDecl*> &decls) const override;
Optional<BriefAndRawComment> getCommentForDecl(const Decl *D) const override;
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
virtual void getDisplayDecls(SmallVectorImpl<Decl*> &results) const override;
virtual void
getImportedModules(SmallVectorImpl<Module::ImportedModule> &imports,
Module::ImportFilter filter) const override;
virtual void
collectLinkLibraries(Module::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() 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