Serialization: Break the cycle between Serialization and SymbolGraphGen.

Push the top level logic for writing out swiftmodules and associated files into the frontend library which has access to all the necessary dependencies.
This commit is contained in:
Allan Shortlidge
2022-10-27 11:08:56 -07:00
parent c11647f678
commit af032afb9d
9 changed files with 218 additions and 153 deletions

View File

@@ -0,0 +1,165 @@
//===--- Serialization.cpp - Write Swift modules --------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Serialization/Serialization.h"
#include "swift/APIDigester/ModuleAnalyzerNodes.h"
#include "swift/AST/FileSystem.h"
#include "swift/Subsystems.h"
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
#include "swift/SymbolGraphGen/SymbolGraphOptions.h"
#include "llvm/Support/SmallVectorMemoryBuffer.h"
using namespace swift;
static ModuleDecl *getModule(ModuleOrSourceFile DC) {
if (auto M = DC.dyn_cast<ModuleDecl *>())
return M;
return DC.get<SourceFile *>()->getParentModule();
}
static ASTContext &getContext(ModuleOrSourceFile DC) {
return getModule(DC)->getASTContext();
}
static void emitABIDescriptor(ModuleOrSourceFile DC,
const SerializationOptions &options) {
using namespace swift::ide::api;
if (!options.ABIDescriptorPath.empty()) {
if (DC.is<ModuleDecl *>()) {
dumpModuleContent(DC.get<ModuleDecl *>(), options.ABIDescriptorPath, true,
options.emptyABIDescriptor);
}
}
}
void swift::serializeToBuffers(
ModuleOrSourceFile DC, const SerializationOptions &options,
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
const SILModule *M) {
assert(!options.OutputPath.empty());
{
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftmodule, to buffer");
llvm::SmallString<1024> buf;
llvm::raw_svector_ostream stream(buf);
serialization::writeToStream(stream, DC, M, options,
/*dependency info*/ nullptr);
bool hadError = withOutputFile(getContext(DC).Diags, options.OutputPath,
[&](raw_ostream &out) {
out << stream.str();
return false;
});
if (hadError)
return;
emitABIDescriptor(DC, options);
if (moduleBuffer)
*moduleBuffer = std::make_unique<llvm::SmallVectorMemoryBuffer>(
std::move(buf), options.OutputPath,
/*RequiresNullTerminator=*/false);
}
if (!options.DocOutputPath.empty()) {
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftdoc, to buffer");
llvm::SmallString<1024> buf;
llvm::raw_svector_ostream stream(buf);
serialization::writeDocToStream(stream, DC, options.GroupInfoPath);
(void)withOutputFile(getContext(DC).Diags, options.DocOutputPath,
[&](raw_ostream &out) {
out << stream.str();
return false;
});
if (moduleDocBuffer)
*moduleDocBuffer = std::make_unique<llvm::SmallVectorMemoryBuffer>(
std::move(buf), options.DocOutputPath,
/*RequiresNullTerminator=*/false);
}
if (!options.SourceInfoOutputPath.empty()) {
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftsourceinfo, to buffer");
llvm::SmallString<1024> buf;
llvm::raw_svector_ostream stream(buf);
serialization::writeSourceInfoToStream(stream, DC);
(void)withOutputFile(getContext(DC).Diags, options.SourceInfoOutputPath,
[&](raw_ostream &out) {
out << stream.str();
return false;
});
if (moduleSourceInfoBuffer)
*moduleSourceInfoBuffer = std::make_unique<llvm::SmallVectorMemoryBuffer>(
std::move(buf), options.SourceInfoOutputPath,
/*RequiresNullTerminator=*/false);
}
}
void swift::serialize(
ModuleOrSourceFile DC, const SerializationOptions &options,
const symbolgraphgen::SymbolGraphOptions &symbolGraphOptions,
const SILModule *M,
const fine_grained_dependencies::SourceFileDepGraph *DG) {
assert(!options.OutputPath.empty());
if (options.OutputPath == "-") {
// Special-case writing to stdout.
serialization::writeToStream(llvm::outs(), DC, M, options, DG);
assert(options.DocOutputPath.empty());
return;
}
bool hadError = withOutputFile(getContext(DC).Diags,
options.OutputPath,
[&](raw_ostream &out) {
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftmodule");
serialization::writeToStream(out, DC, M, options, DG);
return false;
});
if (hadError)
return;
if (!options.DocOutputPath.empty()) {
(void)withOutputFile(getContext(DC).Diags,
options.DocOutputPath,
[&](raw_ostream &out) {
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftdoc");
serialization::writeDocToStream(out, DC, options.GroupInfoPath);
return false;
});
}
if (!options.SourceInfoOutputPath.empty()) {
(void)withOutputFile(getContext(DC).Diags,
options.SourceInfoOutputPath,
[&](raw_ostream &out) {
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, swiftsourceinfo");
serialization::writeSourceInfoToStream(out, DC);
return false;
});
}
if (!symbolGraphOptions.OutputDir.empty()) {
if (DC.is<ModuleDecl *>()) {
auto *M = DC.get<ModuleDecl *>();
FrontendStatsTracer tracer(getContext(DC).Stats,
"Serialization, symbolgraph");
symbolgraphgen::emitSymbolGraphForModule(M, symbolGraphOptions);
}
}
emitABIDescriptor(DC, options);
}