Files
swift-mirror/lib/Serialization/SerializedModuleLoader.cpp
Doug Gregor 8114ce16f8 Use the list of extensions of a nominal type for name lookup into that type.
This replaces the obscure, inefficient lookup into extensions with
something more straightforward: walk all of the known extensions
(available as a simple list), then eliminate any declarations that
have been shadowed by other declarations. The shadowing rules still
need to consider the module re-export DAG, but we'll leave that for
later.

As part of this, keep track of the last time we loaded extensions for
a given nominal type. If the list of extensions is out-of-date with
respect to the global generation count (which tracks resolved module
imports), ask the modules to load any additional extensions. Only the
Clang module importer can currently load extensions in this manner.


Swift SVN r5223
2013-05-20 18:06:51 +00:00

192 lines
6.5 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;
}
static Module *error(SerializedModuleLoader &owner, ASTContext &ctx,
AccessPathElem moduleID, ModuleStatus reason) {
switch (reason) {
case ModuleStatus::Valid:
case ModuleStatus::FallBackToTranslationUnit:
llvm_unreachable("not an error");
case ModuleStatus::Malformed:
ctx.Diags.diagnose(moduleID.second, diag::serialization_malformed_module);
break;
case ModuleStatus::FormatTooNew:
ctx.Diags.diagnose(moduleID.second, diag::serialization_module_too_new);
break;
}
// Return a dummy module to avoid future errors.
auto comp = new (ctx.Allocate<Component>(1)) Component();
auto module = new (ctx) SerializedModule(ctx, owner, 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;
ModuleStatus err = ModuleFile::load(std::move(inputFile), loadedModuleFile);
switch (err) {
case ModuleStatus::Valid:
Ctx.bumpGeneration();
llvm_unreachable("non-fallback modules not supported yet!");
case ModuleStatus::FallBackToTranslationUnit:
result = makeTU(Ctx, moduleID, loadedModuleFile->getInputSourcePaths());
break;
case ModuleStatus::FormatTooNew:
case ModuleStatus::Malformed:
return error(*this, Ctx, moduleID, err);
}
return result;
}
void SerializedModuleLoader::loadExtensions(NominalTypeDecl *nominal,
unsigned previousGeneration) {
// FIXME: Look for extensions of the given nominal type within the
// serialized module.
}