Files
swift-mirror/lib/Serialization/SerializedModuleLoader.cpp
Jordan Rose 3109d8c830 [serialization] Pull bitstream processing of modules into its own file.
Like Clang, ModuleFile contains state about reading the serialized module,
while SerializedModuleLoader takes the place of ASTReader in tracking
cross-module data. I'm diverging from Clang's architecture a bit here by
pushing the actual deserialization logic into ModuleFile.

No functionality change.

Swift SVN r5174
2013-05-16 00:23:11 +00:00

175 lines
5.9 KiB
C++

//===--- SerializedModuleLoader.cpp - 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
//
//===----------------------------------------------------------------------===//
#include "swift/Serialization/SerializedModuleLoader.h"
#include "ModuleFile.h"
#include "swift/Subsystems.h"
#include "swift/AST/AST.h"
#include "swift/AST/Component.h"
#include "swift/AST/Diagnostics.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/system_error.h"
using namespace swift;
namespace {
class SerializedModule : public LoadedModule {
public:
SerializedModule(ASTContext &ctx, SerializedModuleLoader &owner,
Identifier name, Component *comp)
: LoadedModule(DeclContextKind::SerializedModule, name, comp, ctx, owner) {}
static bool classof(const DeclContext *DC) {
return DC->getContextKind() == DeclContextKind::SerializedModule;
}
};
typedef std::pair<Identifier, SourceLoc> AccessPathElem;
}
// FIXME: Copied from SourceLoader. Not bothering to fix until we decide that
// the source loader search path should be the same as the module loader search
// path.
static llvm::error_code findModule(ASTContext &ctx, AccessPathElem moduleID,
llvm::OwningPtr<llvm::MemoryBuffer> &buffer){
llvm::SmallString<64> moduleFilename(moduleID.first.str());
moduleFilename += ".sm";
llvm::SmallString<128> inputFilename;
// First, search in the directory corresponding to the import location.
// FIXME: This screams for a proper FileManager abstraction.
llvm::SMLoc rawLoc = moduleID.second.Value;
int currentBufferID = ctx.SourceMgr.FindBufferContainingLoc(rawLoc);
if (currentBufferID >= 0) {
const llvm::MemoryBuffer *importingBuffer
= ctx.SourceMgr.getBufferInfo(currentBufferID).Buffer;
StringRef currentDirectory
= llvm::sys::path::parent_path(importingBuffer->getBufferIdentifier());
if (!currentDirectory.empty()) {
inputFilename = currentDirectory;
llvm::sys::path::append(inputFilename, moduleFilename.str());
llvm::error_code err = llvm::MemoryBuffer::getFile(inputFilename, buffer);
if (!err)
return err;
}
}
// Second, search in the current directory.
llvm::error_code err = llvm::MemoryBuffer::getFile(moduleFilename, buffer);
if (!err)
return err;
// If we fail, search each import search path.
for (auto Path : ctx.ImportSearchPaths) {
inputFilename = Path;
llvm::sys::path::append(inputFilename, moduleFilename.str());
err = llvm::MemoryBuffer::getFile(inputFilename, buffer);
if (!err)
return err;
}
return err;
}
static Module *makeTU(ASTContext &ctx, AccessPathElem moduleID,
ArrayRef<StringRef> inputPaths) {
Component *comp = new (ctx.Allocate<Component>(1)) Component();
TranslationUnit *TU = new (ctx) TranslationUnit(moduleID.first, comp, ctx,
/*IsMainModule=*/false,
/*IsReplModule=*/false);
ctx.LoadedModules[moduleID.first.str()] = TU;
std::vector<unsigned> BufferIDs;
for (auto &path : inputPaths) {
// Open the input file.
llvm::OwningPtr<llvm::MemoryBuffer> InputFile;
if (llvm::MemoryBuffer::getFileOrSTDIN(path, InputFile))
return nullptr;
// Transfer ownership of the MemoryBuffer to the SourceMgr.
// FIXME: include location
llvm::SMLoc rawLoc = moduleID.second.Value;
BufferIDs.push_back(ctx.SourceMgr.AddNewSourceBuffer(InputFile.take(),
rawLoc));
}
for (auto &BufferID : BufferIDs) {
unsigned BufferOffset = 0;
const llvm::MemoryBuffer *Buffer =
ctx.SourceMgr.getMemoryBuffer(BufferID);
do {
parseIntoTranslationUnit(TU, BufferID, &BufferOffset, 0, /*SIL=*/nullptr);
} while (BufferOffset != Buffer->getBufferSize());
}
performNameBinding(TU);
performTypeChecking(TU);
return TU;
}
Module *SerializedModuleLoader::error(AccessPathElem moduleID) {
Ctx.Diags.diagnose(moduleID.second, diag::serialization_malformed_module);
// Return a dummy module to avoid future errors.
auto comp = new (Ctx.Allocate<Component>(1)) Component();
auto module = new (Ctx) SerializedModule(Ctx, *this, moduleID.first, comp);
Ctx.LoadedModules[moduleID.first.str()] = module;
return module;
}
Module *SerializedModuleLoader::loadModule(SourceLoc importLoc,
Module::AccessPathTy path) {
// FIXME: Swift submodules?
if (path.size() > 1)
return nullptr;
auto moduleID = path[0];
llvm::OwningPtr<llvm::MemoryBuffer> inputFile;
if (llvm::error_code err = findModule(Ctx, moduleID, inputFile)) {
if (err.value() != llvm::errc::no_such_file_or_directory) {
Ctx.Diags.diagnose(moduleID.second, diag::sema_opening_import,
moduleID.first.str(), err.message());
}
return nullptr;
}
assert(inputFile);
Module *result;
llvm::OwningPtr<ModuleFile> loadedModuleFile;
switch (ModuleFile::load(std::move(inputFile), loadedModuleFile)) {
case ModuleStatus::Valid:
llvm_unreachable("non-fallback modules not supported yet!");
case ModuleStatus::FallBackToTranslationUnit:
result = makeTU(Ctx, moduleID, loadedModuleFile->getInputSourcePaths());
break;
case ModuleStatus::FormatTooNew:
// FIXME: "version mismatch" should have a different error from "malformed".
return error(moduleID);
case ModuleStatus::Malformed:
return error(moduleID);
}
return result;
}