Skip to content

[frontend] Don't destroy the compiler instance object inside performCompile() #9260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/Frontend/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@ class CompilerInstance {
/// Parses the input file but does no type-checking or module imports.
/// Note that this only supports parsing an invocation with a single file.
void performParseOnly();

/// Frees up the ASTContext and SILModule objects that this instance is
/// holding on.
void freeContextAndSIL();
};

} // namespace swift
Expand Down
5 changes: 5 additions & 0 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -634,3 +634,8 @@ void CompilerInstance::performParseOnly() {
assert(Context->LoadedModules.size() == 1 &&
"Loaded a module during parse-only");
}

void CompilerInstance::freeContextAndSIL() {
Context.reset();
TheSILModule.reset();
}
94 changes: 45 additions & 49 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ static void countStatsPostSILOpt(UnifiedStatsReporter &Stats,
/// \param Instance Will be reset after performIRGeneration when the verifier
/// mode is NoVerify and there were no errors.
/// \returns true on error
static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
static bool performCompile(CompilerInstance &Instance,
CompilerInvocation &Invocation,
ArrayRef<const char *> Args,
int &ReturnValue,
Expand All @@ -439,7 +439,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
// avoid touching any other inputs and just parse, emit and exit.
if (Action == FrontendOptions::EmitPCH) {
auto clangImporter = static_cast<ClangImporter *>(
Instance->getASTContext().getClangModuleLoader());
Instance.getASTContext().getClangModuleLoader());
return clangImporter->emitBridgingPCH(
Invocation.getInputFilenames()[0],
opts.getSingleOutputFilename());
Expand All @@ -457,7 +457,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
llvm::MemoryBuffer::getFileOrSTDIN(Invocation.getInputFilenames()[0]);
if (!FileBufOrErr) {
Instance->getASTContext().Diags.diagnose(SourceLoc(),
Instance.getASTContext().Diags.diagnose(SourceLoc(),
diag::error_open_input_file,
Invocation.getInputFilenames()[0],
FileBufOrErr.getError().message());
Expand All @@ -472,7 +472,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
if (!Module) {
// TODO: Translate from the diagnostic info to the SourceManager location
// if available.
Instance->getASTContext().Diags.diagnose(SourceLoc(),
Instance.getASTContext().Diags.diagnose(SourceLoc(),
diag::error_parse_input_file,
Invocation.getInputFilenames()[0],
Err.getMessage());
Expand All @@ -482,31 +482,31 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
// TODO: remove once the frontend understands what action it should perform
IRGenOpts.OutputKind = getOutputKind(Action);

return performLLVM(IRGenOpts, Instance->getASTContext(), Module.get());
return performLLVM(IRGenOpts, Instance.getASTContext(), Module.get());
}

ReferencedNameTracker nameTracker;
bool shouldTrackReferences = !opts.ReferenceDependenciesFilePath.empty();
if (shouldTrackReferences)
Instance->setReferencedNameTracker(&nameTracker);
Instance.setReferencedNameTracker(&nameTracker);

if (Action == FrontendOptions::Parse ||
Action == FrontendOptions::DumpParse ||
Action == FrontendOptions::DumpInterfaceHash ||
Action == FrontendOptions::EmitImportedModules)
Instance->performParseOnly();
Instance.performParseOnly();
else
Instance->performSema();
Instance.performSema();

if (Action == FrontendOptions::Parse)
return Instance->getASTContext().hadError();
return Instance.getASTContext().hadError();

if (observer) {
observer->performedSemanticAnalysis(*Instance);
observer->performedSemanticAnalysis(Instance);
}

if (Stats) {
countStatsPostSema(*Stats, *Instance);
countStatsPostSema(*Stats, Instance);
}

FrontendOptions::DebugCrashMode CrashMode = opts.CrashMode;
Expand All @@ -515,19 +515,19 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
else if (CrashMode == FrontendOptions::DebugCrashMode::CrashAfterParse)
debugFailWithCrash();

ASTContext &Context = Instance->getASTContext();
ASTContext &Context = Instance.getASTContext();

if (Invocation.getMigratorOptions().shouldRunMigrator()) {
migrator::updateCodeAndEmitRemap(Instance.get(), Invocation);
migrator::updateCodeAndEmitRemap(&Instance, Invocation);
}

if (Action == FrontendOptions::REPL) {
runREPL(*Instance, ProcessCmdLine(Args.begin(), Args.end()),
runREPL(Instance, ProcessCmdLine(Args.begin(), Args.end()),
Invocation.getParseStdlib());
return Context.hadError();
}

SourceFile *PrimarySourceFile = Instance->getPrimarySourceFile();
SourceFile *PrimarySourceFile = Instance.getPrimarySourceFile();

// We've been told to dump the AST (either after parsing or type-checking,
// which is already differentiated in CompilerInstance::performSema()),
Expand All @@ -541,7 +541,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
SourceFile *SF = PrimarySourceFile;
if (!SF) {
SourceFileKind Kind = Invocation.getSourceFileKind();
SF = &Instance->getMainModule()->getMainSourceFile(Kind);
SF = &Instance.getMainModule()->getMainSourceFile(Kind);
}
if (Action == FrontendOptions::PrintAST)
SF->print(llvm::outs(), PrintOptions::printEverything());
Expand All @@ -551,7 +551,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
if (opts.DumpScopeMapLocations.empty()) {
scope.expandAll();
} else if (auto bufferID = SF->getBufferID()) {
SourceManager &sourceMgr = Instance->getSourceMgr();
SourceManager &sourceMgr = Instance.getSourceMgr();
// Probe each of the locations, and dump what we find.
for (auto lineColumn : opts.DumpScopeMapLocations) {
SourceLoc loc = sourceMgr.getLocForLineCol(*bufferID,
Expand Down Expand Up @@ -597,7 +597,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
SF->dump();
return Context.hadError();
} else if (Action == FrontendOptions::EmitImportedModules) {
emitImportedModules(Context, Instance->getMainModule(), opts);
emitImportedModules(Context, Instance.getMainModule(), opts);
return Context.hadError();
}

Expand All @@ -606,15 +606,15 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
Context.getClangModuleLoader()->printStatistics();

if (!opts.DependenciesFilePath.empty())
(void)emitMakeDependencies(Context.Diags, *Instance->getDependencyTracker(),
(void)emitMakeDependencies(Context.Diags, *Instance.getDependencyTracker(),
opts);

if (shouldTrackReferences)
emitReferenceDependencies(Context.Diags, Instance->getPrimarySourceFile(),
*Instance->getDependencyTracker(), opts);
emitReferenceDependencies(Context.Diags, Instance.getPrimarySourceFile(),
*Instance.getDependencyTracker(), opts);

if (!opts.LoadedModuleTracePath.empty())
(void)emitLoadedModuleTrace(Context, *Instance->getDependencyTracker(),
(void)emitLoadedModuleTrace(Context, *Instance.getDependencyTracker(),
opts);

if (Context.hadError())
Expand All @@ -623,39 +623,39 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
// FIXME: This is still a lousy approximation of whether the module file will
// be externally consumed.
bool moduleIsPublic =
!Instance->getMainModule()->hasEntryPoint() &&
!Instance.getMainModule()->hasEntryPoint() &&
opts.ImplicitObjCHeaderPath.empty() &&
!Context.LangOpts.EnableAppExtensionRestrictions;

// We've just been told to perform a typecheck, so we can return now.
if (Action == FrontendOptions::Typecheck) {
if (!opts.ObjCHeaderOutputPath.empty())
return printAsObjC(opts.ObjCHeaderOutputPath, Instance->getMainModule(),
return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(),
opts.ImplicitObjCHeaderPath, moduleIsPublic);
return Context.hadError();
}

if (Action == FrontendOptions::EmitTBD) {
auto hasMultipleIRGenThreads = Invocation.getSILOptions().NumThreads > 1;
return writeTBD(Instance->getMainModule(), hasMultipleIRGenThreads,
return writeTBD(Instance.getMainModule(), hasMultipleIRGenThreads,
opts.getSingleOutputFilename());
}

assert(Action >= FrontendOptions::EmitSILGen &&
"All actions not requiring SILGen must have been handled!");

std::unique_ptr<SILModule> SM = Instance->takeSILModule();
std::unique_ptr<SILModule> SM = Instance.takeSILModule();
if (!SM) {
if (opts.PrimaryInput.hasValue() && opts.PrimaryInput.getValue().isFilename()) {
FileUnit *PrimaryFile = PrimarySourceFile;
if (!PrimaryFile) {
auto Index = opts.PrimaryInput.getValue().Index;
PrimaryFile = Instance->getMainModule()->getFiles()[Index];
PrimaryFile = Instance.getMainModule()->getFiles()[Index];
}
SM = performSILGeneration(*PrimaryFile, Invocation.getSILOptions(),
None, opts.SILSerializeAll);
} else {
SM = performSILGeneration(Instance->getMainModule(), Invocation.getSILOptions(),
SM = performSILGeneration(Instance.getMainModule(), Invocation.getSILOptions(),
opts.SILSerializeAll,
true);
}
Expand All @@ -673,7 +673,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
// If we are asked to link all, link all.
if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
performSILLinking(SM.get(), true);
return writeSIL(*SM, Instance->getMainModule(), opts.EmitVerboseSIL,
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
}

Expand All @@ -683,7 +683,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
performSILLinking(SM.get(), true);

auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) :
Instance->getMainModule();
Instance.getMainModule();
if (!opts.ModuleOutputPath.empty()) {
SerializationOptions serializationOpts;
serializationOpts.OutputPath = opts.ModuleOutputPath.c_str();
Expand Down Expand Up @@ -769,13 +769,13 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
}

if (!opts.ObjCHeaderOutputPath.empty()) {
(void)printAsObjC(opts.ObjCHeaderOutputPath, Instance->getMainModule(),
(void)printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(),
opts.ImplicitObjCHeaderPath, moduleIsPublic);
}

if (Action == FrontendOptions::EmitSIB) {
auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) :
Instance->getMainModule();
Instance.getMainModule();
if (!opts.ModuleOutputPath.empty()) {
SerializationOptions serializationOpts;
serializationOpts.OutputPath = opts.ModuleOutputPath.c_str();
Expand All @@ -789,7 +789,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,

if (!opts.ModuleOutputPath.empty() || !opts.ModuleDocOutputPath.empty()) {
auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) :
Instance->getMainModule();
Instance.getMainModule();
if (!opts.ModuleOutputPath.empty()) {
SerializationOptions serializationOpts;
serializationOpts.OutputPath = opts.ModuleOutputPath.c_str();
Expand Down Expand Up @@ -824,7 +824,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,

// We've been told to write canonical SIL, so write it now.
if (Action == FrontendOptions::EmitSIL) {
return writeSIL(*SM, Instance->getMainModule(), opts.EmitVerboseSIL,
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
}

Expand All @@ -848,14 +848,14 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::Normal;
const ProcessCmdLine &CmdLine = ProcessCmdLine(opts.ImmediateArgv.begin(),
opts.ImmediateArgv.end());
Instance->setSILModule(std::move(SM));
Instance.setSILModule(std::move(SM));

if (observer) {
observer->aboutToRunImmediately(*Instance);
observer->aboutToRunImmediately(Instance);
}

ReturnValue =
RunImmediately(*Instance, CmdLine, IRGenOpts, Invocation.getSILOptions());
RunImmediately(Instance, CmdLine, IRGenOpts, Invocation.getSILOptions());
return Context.hadError();
}

Expand All @@ -869,14 +869,14 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
opts.getSingleOutputFilename(), LLVMContext,
0, &HashGlobal);
} else {
IRModule = performIRGeneration(IRGenOpts, Instance->getMainModule(),
IRModule = performIRGeneration(IRGenOpts, Instance.getMainModule(),
std::move(SM),
opts.getSingleOutputFilename(), LLVMContext,
&HashGlobal);
}

// Just because we had an AST error it doesn't mean we can't performLLVM.
bool HadError = Instance->getASTContext().hadError();
bool HadError = Instance.getASTContext().hadError();

// If the AST Context has no errors but no IRModule is available,
// parallelIRGen happened correctly, since parallel IRGen produces multiple
Expand All @@ -896,7 +896,7 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
error =
validateTBD(PrimarySourceFile, *IRModule, hasMultipleIRGenThreads);
else
error = validateTBD(Instance->getMainModule(), *IRModule,
error = validateTBD(Instance.getMainModule(), *IRModule,
hasMultipleIRGenThreads);
if (error)
return true;
Expand All @@ -906,15 +906,11 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
createTargetMachine(IRGenOpts, Context);
version::Version EffectiveLanguageVersion =
Context.LangOpts.EffectiveLanguageVersion;

// Free up some compiler resources now that we have an IRModule.
Instance.freeContextAndSIL();

DiagnosticEngine &Diags = Context.Diags;
const DiagnosticOptions &DiagOpts = Invocation.getDiagnosticOptions();

// Delete the compiler instance now that we have an IRModule.
if (DiagOpts.VerifyMode == DiagnosticOptions::NoVerify) {
SM.reset();
Instance.reset();
}

// Now that we have a single IR Module, hand it over to performLLVM.
return performLLVM(IRGenOpts, &Diags, nullptr, HashGlobal, IRModule.get(),
TargetMachine.get(), EffectiveLanguageVersion,
Expand Down Expand Up @@ -1189,7 +1185,7 @@ int swift::performFrontend(ArrayRef<const char *> Args,

int ReturnValue = 0;
bool HadError =
performCompile(Instance, Invocation, Args, ReturnValue, observer,
performCompile(*Instance, Invocation, Args, ReturnValue, observer,
StatsReporter.get());

if (!HadError) {
Expand Down