Implement SerializedModuleLoader::addASTSection() to parse AST sections as

created by IrGen/SwiftASTStreamerPass.

Swift SVN r7851
This commit is contained in:
Adrian Prantl
2013-09-03 18:09:53 +00:00
parent 07da340eef
commit d929050173
5 changed files with 111 additions and 65 deletions

View File

@@ -16,11 +16,13 @@
#include "swift/AST/AST.h"
#include "swift/AST/Component.h"
#include "swift/AST/Diagnostics.h"
#include "swift/Basic/Dwarf.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/system_error.h"
using namespace swift;
@@ -80,6 +82,66 @@ static llvm::error_code findModule(ASTContext &ctx, AccessPathElem moduleID,
}
bool SerializedModuleLoader::
addASTSection(std::unique_ptr<llvm::MemoryBuffer> MemoryBuffer,
SmallVectorImpl<std::string> &foundModules) {
struct apple_ast_hdr {
uint32_t version;
uint32_t nmods;
};
struct module_header {
uint64_t bitstream_ofs;
uint64_t bitstream_size;
uint64_t name_ofs;
uint32_t language;
uint32_t flags;
};
if (MemoryBuffer->getBufferSize() < sizeof(struct apple_ast_hdr)
+ sizeof(struct module_header)) {
llvm::dbgs() << "__apple_ast section is too small.\n";
return false;
}
size_t size = MemoryBuffer->getBufferSize();
const char *data = MemoryBuffer->getBufferStart();
auto apple_ast_hdr = reinterpret_cast<const struct apple_ast_hdr *>(data);
if (apple_ast_hdr->version != 1) {
llvm::dbgs() << "Unsupported __apple_ast section version.\n";
return false;
}
// Iterate over all AST modules.
for (uint32_t i = 0; i < apple_ast_hdr->nmods; ++i) {
auto mh = reinterpret_cast<const struct module_header *>
(data+sizeof(apple_ast_hdr));
if (mh->language != dwarf::DW_LANG_Swift)
continue;
// Get the access path.
if (mh->name_ofs + 4 > size) return false;
auto nchars = *reinterpret_cast<const uint32_t *>(data + mh->name_ofs);
if (mh->name_ofs+sizeof(nchars) > size) return false;
assert(nchars < (2 << 10) && "path failed sanity check");
llvm::StringRef AccessPath(data+mh->name_ofs+sizeof(nchars), nchars);
// loadModule() wants to take ownership of the input memory buffer.
// Copy the bitstream into a new memory buffer.
if (mh->bitstream_ofs + mh->bitstream_size > size) return false;
auto mem = llvm::StringRef(data+mh->bitstream_ofs, mh->bitstream_size);
auto bitstream = llvm::MemoryBuffer::getMemBufferCopy(mem, AccessPath);
// Register the memory buffer.
registerMemoryBuffer(AccessPath,
std::unique_ptr<llvm::MemoryBuffer>(bitstream));
foundModules.push_back(AccessPath);
}
return true;
}
Module *SerializedModuleLoader::loadModule(SourceLoc importLoc,
Module::AccessPathTy path) {
// FIXME: Swift submodules?
@@ -89,18 +151,18 @@ Module *SerializedModuleLoader::loadModule(SourceLoc importLoc,
auto moduleID = path[0];
llvm::OwningPtr<llvm::MemoryBuffer> inputFile;
// First see if we find it in the registered bitstreams.
// First see if we find it in the registered memory buffers.
if (!MemoryBuffers.empty()) {
// FIXME: Right now this works only with fully-qualified absolute
// pathnames, which is incidentally what LLDB uses. Fix this to
// support suffix matching and a search path.
// FIXME: Right now this works only with access paths of length 1.
// Once submodules are designed, this needs to support suffix
// matching and a search path.
llvm::SmallString<256> spath;
for (auto el : path)
llvm::sys::path::append(spath, el.first.str());
auto bs = MemoryBuffers.find(spath.str());
if (bs != MemoryBuffers.end())
inputFile.reset(bs->second.take());
inputFile.reset(bs->second.release());
}
// Otherwise look on disk.
@@ -236,7 +298,7 @@ SerializedModuleLoader::lookupVisibleDecls(const Module *module,
ModuleFile *moduleFile = cast<SerializedModule>(module)->File;
if (!moduleFile)
return;
moduleFile->lookupVisibleDecls(accessPath, consumer, lookupKind);
}