SIL: Share TypeConverter between SILModules in batch mode

This commit is contained in:
Slava Pestov
2019-08-27 21:58:38 -04:00
parent d434188157
commit 01e65e18c4
16 changed files with 71 additions and 37 deletions

View File

@@ -55,6 +55,10 @@ class SerializedModuleLoader;
class MemoryBufferSerializedModuleLoader;
class SILModule;
namespace Lowering {
class TypeConverter;
}
/// The abstract configuration of the compiler, including:
/// - options for all stages of translation,
/// - information about the build environment,
@@ -372,6 +376,7 @@ class CompilerInstance {
SourceManager SourceMgr;
DiagnosticEngine Diagnostics{SourceMgr};
std::unique_ptr<ASTContext> Context;
std::unique_ptr<Lowering::TypeConverter> TheSILTypes;
std::unique_ptr<SILModule> TheSILModule;
std::unique_ptr<PersistentParserState> PersistentState;
@@ -422,8 +427,6 @@ class CompilerInstance {
bool isWholeModuleCompilation() { return PrimaryBufferIDs.empty(); }
void createSILModule();
public:
// Out of line to avoid having to import SILModule.h.
CompilerInstance();
@@ -448,6 +451,10 @@ public:
SILOptions &getSILOptions() { return Invocation.getSILOptions(); }
const SILOptions &getSILOptions() const { return Invocation.getSILOptions(); }
Lowering::TypeConverter &getSILTypes();
void createSILModule();
void addDiagnosticConsumer(DiagnosticConsumer *DC) {
Diagnostics.addConsumer(*DC);
}

View File

@@ -260,7 +260,8 @@ private:
// Intentionally marked private so that we need to use 'constructSIL()'
// to construct a SILModule.
SILModule(ModuleDecl *M, SILOptions &Options, const DeclContext *associatedDC,
SILModule(ModuleDecl *M, Lowering::TypeConverter &TC,
SILOptions &Options, const DeclContext *associatedDC,
bool wholeModule);
SILModule(const SILModule&) = delete;
@@ -313,7 +314,7 @@ public:
void serialize();
/// This converts Swift types to SILTypes.
mutable Lowering::TypeConverter Types;
Lowering::TypeConverter &Types;
/// Invalidate cached entries in SIL Loader.
void invalidateSILLoaderCaches();
@@ -340,12 +341,14 @@ public:
/// If a source file is provided, SIL will only be emitted for decls in that
/// source file.
static std::unique_ptr<SILModule>
constructSIL(ModuleDecl *M, SILOptions &Options, FileUnit *sf = nullptr);
constructSIL(ModuleDecl *M, Lowering::TypeConverter &TC,
SILOptions &Options, FileUnit *sf = nullptr);
/// Create and return an empty SIL module that we can
/// later parse SIL bodies directly into, without converting from an AST.
static std::unique_ptr<SILModule>
createEmptyModule(ModuleDecl *M, SILOptions &Options,
createEmptyModule(ModuleDecl *M, Lowering::TypeConverter &TC,
SILOptions &Options,
bool WholeModule = false);
/// Get the Swift module associated with this SIL module.

View File

@@ -69,6 +69,10 @@ namespace swift {
class UnifiedStatsReporter;
enum class SourceFileKind;
namespace Lowering {
class TypeConverter;
}
/// Used to optionally maintain SIL parsing context for the parser.
///
/// When not parsing SIL, this has no overhead.
@@ -254,11 +258,13 @@ namespace swift {
/// The module must contain source files. The optimizer will assume that the
/// SIL of all files in the module is present in the SILModule.
std::unique_ptr<SILModule>
performSILGeneration(ModuleDecl *M, SILOptions &options);
performSILGeneration(ModuleDecl *M, Lowering::TypeConverter &TC,
SILOptions &options);
/// Turn a source file into SIL IR.
std::unique_ptr<SILModule>
performSILGeneration(FileUnit &SF, SILOptions &options);
performSILGeneration(FileUnit &SF, Lowering::TypeConverter &TC,
SILOptions &options);
using ModuleOrSourceFile = PointerUnion<ModuleDecl *, SourceFile *>;

View File

@@ -148,11 +148,20 @@ SerializationOptions CompilerInvocation::computeSerializationOptions(
return serializationOpts;
}
Lowering::TypeConverter &CompilerInstance::getSILTypes() {
if (auto *tc = TheSILTypes.get())
return *tc;
auto *tc = new Lowering::TypeConverter(*getMainModule());
TheSILTypes.reset(tc);
return *tc;
}
void CompilerInstance::createSILModule() {
assert(MainModule && "main module not created yet");
// Assume WMO if a -primary-file option was not provided.
TheSILModule = SILModule::createEmptyModule(
getMainModule(), Invocation.getSILOptions(),
getMainModule(), getSILTypes(), Invocation.getSILOptions(),
Invocation.getFrontendOptions().InputsAndOutputs.isWholeModule());
}
@@ -1074,6 +1083,7 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
void CompilerInstance::freeASTContext() {
PersistentState.reset();
TheSILTypes.reset();
Context.reset();
MainModule = nullptr;
SML = nullptr;

View File

@@ -592,7 +592,8 @@ public:
SILOptions &SILOpts = subInvocation.getSILOptions();
auto Mod = SubInstance.getMainModule();
auto SILMod = performSILGeneration(Mod, SILOpts);
auto &TC = SubInstance.getSILTypes();
auto SILMod = performSILGeneration(Mod, TC, SILOpts);
if (!SILMod) {
LLVM_DEBUG(llvm::dbgs() << "SILGen did not produce a module\n");
SubError = true;

View File

@@ -917,7 +917,7 @@ generateSILModules(CompilerInvocation &Invocation, CompilerInstance &Instance) {
if (!opts.InputsAndOutputs.hasPrimaryInputs()) {
// If there are no primary inputs the compiler is in WMO mode and builds one
// SILModule for the entire module.
auto SM = performSILGeneration(mod, SILOpts);
auto SM = performSILGeneration(mod, Instance.getSILTypes(), SILOpts);
std::deque<PostSILGenInputs> PSGIs;
const PrimarySpecificPaths PSPs =
Instance.getPrimarySpecificPathsForWholeModuleOptimizationMode();
@@ -930,7 +930,7 @@ generateSILModules(CompilerInvocation &Invocation, CompilerInstance &Instance) {
// once for each such input.
std::deque<PostSILGenInputs> PSGIs;
for (auto *PrimaryFile : Instance.getPrimarySourceFiles()) {
auto SM = performSILGeneration(*PrimaryFile, SILOpts);
auto SM = performSILGeneration(*PrimaryFile, Instance.getSILTypes(), SILOpts);
const PrimarySpecificPaths PSPs =
Instance.getPrimarySpecificPathsForSourceFile(*PrimaryFile);
PSGIs.push_back(PostSILGenInputs{std::move(SM), true, PrimaryFile, PSPs});
@@ -944,7 +944,7 @@ generateSILModules(CompilerInvocation &Invocation, CompilerInstance &Instance) {
if (Invocation.getFrontendOptions().InputsAndOutputs.isInputPrimary(
SASTF->getFilename())) {
assert(PSGIs.empty() && "Can only handle one primary AST input");
auto SM = performSILGeneration(*SASTF, SILOpts);
auto SM = performSILGeneration(*SASTF, Instance.getSILTypes(), SILOpts);
const PrimarySpecificPaths &PSPs =
Instance.getPrimarySpecificPathsForPrimary(SASTF->getFilename());
PSGIs.push_back(

View File

@@ -874,7 +874,8 @@ private:
if (!CI.getASTContext().hadError()) {
// We don't want anything to get stripped, so pretend we're doing a
// non-whole-module generation.
sil = performSILGeneration(*M->getFiles().front(), CI.getSILOptions());
sil = performSILGeneration(*M->getFiles().front(), CI.getSILTypes(),
CI.getSILOptions());
runSILDiagnosticPasses(*sil);
runSILOwnershipEliminatorPass(*sil);
runSILLoweringPasses(*sil);

View File

@@ -61,6 +61,7 @@ namespace {
struct IRGenContext {
IRGenOptions IROpts;
SILOptions SILOpts;
Lowering::TypeConverter TC;
std::unique_ptr<SILModule> SILMod;
llvm::LLVMContext LLVMContext;
irgen::IRGenerator IRGen;
@@ -69,7 +70,8 @@ struct IRGenContext {
private:
IRGenContext(ASTContext &ctx, ModuleDecl *module)
: IROpts(createIRGenOptions()),
SILMod(SILModule::createEmptyModule(module, SILOpts)),
TC(*module),
SILMod(SILModule::createEmptyModule(module, TC, SILOpts)),
IRGen(IROpts, *SILMod),
IGM(IRGen, IRGen.createTargetMachine(), LLVMContext) {}

View File

@@ -89,11 +89,13 @@ class SILModule::SerializationCallback final
}
};
SILModule::SILModule(ModuleDecl *SwiftModule, SILOptions &Options,
const DeclContext *associatedDC, bool wholeModule)
: TheSwiftModule(SwiftModule), AssociatedDeclContext(associatedDC),
SILModule::SILModule(ModuleDecl *SwiftModule, TypeConverter &TC,
SILOptions &Options, const DeclContext *associatedDC,
bool wholeModule)
: TheSwiftModule(SwiftModule),
AssociatedDeclContext(associatedDC),
Stage(SILStage::Raw), wholeModule(wholeModule), Options(Options),
serialized(false), SerializeSILAction(), Types(*SwiftModule) {
serialized(false), SerializeSILAction(), Types(TC) {
// We always add the base SILModule serialization callback.
std::unique_ptr<DeserializationNotificationHandler> callback(
new SILModule::SerializationCallback());
@@ -118,10 +120,10 @@ SILModule::~SILModule() {
}
std::unique_ptr<SILModule>
SILModule::createEmptyModule(ModuleDecl *M, SILOptions &Options,
SILModule::createEmptyModule(ModuleDecl *M, TypeConverter &TC, SILOptions &Options,
bool WholeModule) {
return std::unique_ptr<SILModule>(
new SILModule(M, Options, M, WholeModule));
new SILModule(M, TC, Options, M, WholeModule));
}
ASTContext &SILModule::getASTContext() const {

View File

@@ -1662,7 +1662,8 @@ void SILGenModule::emitSourceFile(SourceFile *sf) {
//===----------------------------------------------------------------------===//
std::unique_ptr<SILModule>
SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF) {
SILModule::constructSIL(ModuleDecl *mod, TypeConverter &tc,
SILOptions &options, FileUnit *SF) {
SharedTimer timer("SILGen");
const DeclContext *DC;
if (SF) {
@@ -1672,7 +1673,7 @@ SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF) {
}
std::unique_ptr<SILModule> M(
new SILModule(mod, options, DC, /*wholeModule*/ SF == nullptr));
new SILModule(mod, tc, options, DC, /*wholeModule*/ SF == nullptr));
SILGenModule SGM(*M, mod);
if (SF) {
@@ -1721,11 +1722,13 @@ SILModule::constructSIL(ModuleDecl *mod, SILOptions &options, FileUnit *SF) {
}
std::unique_ptr<SILModule>
swift::performSILGeneration(ModuleDecl *mod, SILOptions &options) {
return SILModule::constructSIL(mod, options, nullptr);
swift::performSILGeneration(ModuleDecl *mod, Lowering::TypeConverter &tc,
SILOptions &options) {
return SILModule::constructSIL(mod, tc, options, nullptr);
}
std::unique_ptr<SILModule>
swift::performSILGeneration(FileUnit &sf, SILOptions &options) {
return SILModule::constructSIL(sf.getParentModule(), options, &sf);
swift::performSILGeneration(FileUnit &sf, Lowering::TypeConverter &tc,
SILOptions &options) {
return SILModule::constructSIL(sf.getParentModule(), tc, options, &sf);
}

View File

@@ -1000,7 +1000,8 @@ ASTUnitRef ASTProducer::createASTUnit(
if (auto SF = CompIns.getPrimarySourceFile()) {
SILOptions SILOpts = Invocation.getSILOptions();
std::unique_ptr<SILModule> SILMod = performSILGeneration(*SF, SILOpts);
auto &TC = CompIns.getSILTypes();
std::unique_ptr<SILModule> SILMod = performSILGeneration(*SF, TC, SILOpts);
runSILDiagnosticPasses(*SILMod);
}
}

View File

@@ -24,6 +24,7 @@
#include "swift/Option/Options.h"
#include "swift/Serialization/Validation.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/TypeLowering.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Bitcode/BitstreamReader.h"
@@ -177,7 +178,8 @@ int modulewrap_main(ArrayRef<const char *> Args, const char *Argv0,
true);
ModuleDecl *M = ModuleDecl::create(ASTCtx.getIdentifier("swiftmodule"), ASTCtx);
SILOptions SILOpts;
std::unique_ptr<SILModule> SM = SILModule::createEmptyModule(M, SILOpts);
std::unique_ptr<Lowering::TypeConverter> TC(new Lowering::TypeConverter(*M));
std::unique_ptr<SILModule> SM = SILModule::createEmptyModule(M, *TC, SILOpts);
createSwiftModuleObjectFile(*SM, (*ErrOrBuf)->getBuffer(),
Invocation.getOutputFilename());
return 0;

View File

@@ -277,8 +277,7 @@ int main(int argc, char **argv) {
if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(
SILModule::createEmptyModule(CI.getMainModule(), CI.getSILOptions()));
CI.createSILModule();
std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create(
CI.getASTContext(), CI.getSILModule(), nullptr);

View File

@@ -189,8 +189,7 @@ int main(int argc, char **argv) {
if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(SILModule::createEmptyModule(
CI.getMainModule(), CI.getSILOptions(), PerformWMO));
CI.createSILModule();
std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create(
CI.getASTContext(), CI.getSILModule(), nullptr);

View File

@@ -191,8 +191,7 @@ int main(int argc, char **argv) {
if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(
SILModule::createEmptyModule(CI.getMainModule(), CI.getSILOptions()));
CI.createSILModule();
std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create(
CI.getASTContext(), CI.getSILModule(), nullptr);

View File

@@ -389,8 +389,7 @@ int main(int argc, char **argv) {
if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(SILModule::createEmptyModule(
CI.getMainModule(), CI.getSILOptions(), PerformWMO));
CI.createSILModule();
std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create(
CI.getASTContext(), CI.getSILModule(), nullptr);