Files
swift-mirror/lib/Serialization/Serialization.cpp
Jordan Rose 476c4d4f48 [serialization] -emit-module: write out input file paths.
Eventually this will include both modules and source files that the
emitted module depends on, but for now it's just going to be used for
testing purposes to forward to normal source loaders.

Swift SVN r5108
2013-05-09 00:19:09 +00:00

143 lines
4.2 KiB
C++

//===--- Serialization.cpp - Read and write Swift modules -----------------===//
//
// 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/Serialization.h"
#include "swift/AST/AST.h"
#include "swift/AST/Diagnostics.h"
#include "swift/Serialization/BCRecordLayout.h"
#include "swift/Subsystems.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Config/Config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
using namespace swift::serialization;
namespace {
typedef ArrayRef<unsigned> FileBufferIDs;
class Serializer {
SmallVector<char, 0> Buffer;
llvm::BitstreamWriter Out;
/// A reusable buffer for emitting records.
SmallVector<uint64_t, 64> ScratchRecord;
/// Writes the Swift module file header and BLOCKINFO block.
void writeHeader();
/// Writes the input file paths.
void writeInputFiles(llvm::SourceMgr &sourceMgr, FileBufferIDs inputFiles);
/// Top-level entry point for serializing a translation unit module.
void writeTranslationUnit(const TranslationUnit *TU);
public:
Serializer() : Out(Buffer) {}
/// Serialize a translation unit to the given stream.
void writeToStream(raw_ostream &os, const TranslationUnit *TU,
FileBufferIDs inputFiles);
};
} // end anonymous namespace
void Serializer::writeHeader() {
// Swift module file type: 'SMod'.
Out.Emit((unsigned)'S', 8);
Out.Emit((unsigned)'M', 8);
Out.Emit((unsigned)'o', 8);
Out.Emit((unsigned)'d', 8);
{
BCBlockRAII restoreBlock(Out, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
}
{
BCBlockRAII restoreBlock(Out, CONTROL_BLOCK_ID, 3);
BCRecordLayout<
BCLiteral<METADATA>, // ID
BCFixed<16>, // Module format major version
BCFixed<16>, // Module format minor version
BCBlob // misc. version information
> Metadata(Out);
// FIXME: put a real version in here.
#ifdef LLVM_VERSION_INFO
# define EXTRA_VERSION_STRING PACKAGE_STRING LLVM_VERSION_INFO
#else
# define EXTRA_VERSION_STRING PACKAGE_STRING
#endif
Metadata.emit(ScratchRecord,
METADATA, VERSION_MAJOR, VERSION_MINOR, EXTRA_VERSION_STRING);
#undef EXTRA_VERSION_STRING
}
}
void Serializer::writeInputFiles(llvm::SourceMgr &sourceMgr,
FileBufferIDs inputFiles) {
BCBlockRAII restoreBlock(Out, INPUT_BLOCK_ID, 3);
BCRecordLayout<
BCLiteral<SOURCE_FILE>, // ID
BCBlob // path
> SourceFile(Out);
for (auto bufferID : inputFiles) {
// FIXME: We could really use a real FileManager here.
auto buffer = sourceMgr.getMemoryBuffer(bufferID);
llvm::SmallString<128> path(buffer->getBufferIdentifier());
llvm::error_code err;
err = llvm::sys::fs::make_absolute(path);
if (err)
continue;
SourceFile.emit(ScratchRecord, SOURCE_FILE, path);
}
}
void Serializer::writeTranslationUnit(const TranslationUnit *TU) {
(void)TU;
}
void Serializer::writeToStream(raw_ostream &os, const TranslationUnit *TU,
FileBufferIDs inputFiles){
writeHeader();
writeInputFiles(TU->Ctx.SourceMgr, inputFiles);
writeTranslationUnit(TU);
os.write(Buffer.data(), Buffer.size());
os.flush();
Buffer.clear();
}
void swift::serialize(const TranslationUnit *TU, const char *outputPath,
FileBufferIDs inputFiles) {
std::string errorInfo;
llvm::raw_fd_ostream out(outputPath, errorInfo,
llvm::raw_fd_ostream::F_Binary);
if (out.has_error() || !errorInfo.empty()) {
TU->Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_output, outputPath,
errorInfo);
out.clear_error();
return;
}
Serializer S;
S.writeToStream(out, TU, inputFiles);
}