Skip to content

Commit ff170df

Browse files
committed
[Frontend] Populate files in getMainModule
Rather than waiting until one of the performXXX methods are called, make sure all the main module's files have been populated up-front by `getMainModule`.
1 parent 00dd637 commit ff170df

File tree

2 files changed

+85
-50
lines changed

2 files changed

+85
-50
lines changed

include/swift/Frontend/Frontend.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,9 @@ class CompilerInstance {
441441
std::vector<unsigned> InputSourceCodeBufferIDs;
442442

443443
/// Contains \c MemoryBuffers for partial serialized module files and
444-
/// corresponding partial serialized module documentation files.
445-
std::vector<ModuleBuffers> PartialModules;
444+
/// corresponding partial serialized module documentation files. This is
445+
/// \c mutable as it is consumed by \c loadPartialModulesAndImplicitImports.
446+
mutable std::vector<ModuleBuffers> PartialModules;
446447

447448
enum : unsigned { NO_SUCH_BUFFER = ~0U };
448449
unsigned MainBufferID = NO_SUCH_BUFFER;
@@ -630,9 +631,15 @@ class CompilerInstance {
630631
bool performSILProcessing(SILModule *silModule);
631632

632633
private:
633-
SourceFile *
634-
createSourceFileForMainModule(SourceFileKind FileKind,
635-
Optional<unsigned> BufferID);
634+
/// Creates a new source file for the main module.
635+
SourceFile *createSourceFileForMainModule(ModuleDecl *mod,
636+
SourceFileKind FileKind,
637+
Optional<unsigned> BufferID) const;
638+
639+
/// Creates all the files to be added to the main module, appending them to
640+
/// \p files. If a loading error occurs, returns \c true.
641+
bool createFilesForMainModule(ModuleDecl *mod,
642+
SmallVectorImpl<FileUnit *> &files) const;
636643

637644
public:
638645
void freeASTContext();
@@ -650,8 +657,11 @@ class CompilerInstance {
650657

651658
void performSemaUpTo(SourceFile::ASTStage_t LimitStage);
652659

653-
/// Return true if had load error
654-
bool loadPartialModulesAndImplicitImports();
660+
/// For any serialized AST inputs, loads them in as partial module files,
661+
/// appending them to \p partialModules. If a loading error occurs, returns
662+
/// \c true.
663+
bool loadPartialModulesAndImplicitImports(
664+
ModuleDecl *mod, SmallVectorImpl<FileUnit *> &partialModules) const;
655665

656666
void forEachFileToTypeCheck(llvm::function_ref<void(SourceFile &)> fn);
657667

lib/Frontend/Frontend.cpp

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,37 @@ ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const {
705705
return imports;
706706
}
707707

708+
bool CompilerInstance::createFilesForMainModule(
709+
ModuleDecl *mod, SmallVectorImpl<FileUnit *> &files) const {
710+
// Make sure the main file is the first file in the module.
711+
if (MainBufferID != NO_SUCH_BUFFER) {
712+
auto *mainFile = createSourceFileForMainModule(
713+
mod, Invocation.getSourceFileKind(), MainBufferID);
714+
files.push_back(mainFile);
715+
}
716+
717+
// If we have partial modules to load, do so now, bailing if any failed to
718+
// load.
719+
if (!PartialModules.empty()) {
720+
if (loadPartialModulesAndImplicitImports(mod, files))
721+
return true;
722+
}
723+
724+
// Finally add the library files.
725+
// FIXME: This is the only demand point for InputSourceCodeBufferIDs. We
726+
// should compute this list of source files lazily.
727+
for (auto BufferID : InputSourceCodeBufferIDs) {
728+
// Skip the main buffer, we've already handled it.
729+
if (BufferID == MainBufferID)
730+
continue;
731+
732+
auto *libraryFile =
733+
createSourceFileForMainModule(mod, SourceFileKind::Library, BufferID);
734+
files.push_back(libraryFile);
735+
}
736+
return false;
737+
}
738+
708739
ModuleDecl *CompilerInstance::getMainModule() const {
709740
if (!MainModule) {
710741
Identifier ID = Context->getIdentifier(Invocation.getModuleName());
@@ -719,6 +750,22 @@ ModuleDecl *CompilerInstance::getMainModule() const {
719750

720751
if (Invocation.getFrontendOptions().EnableLibraryEvolution)
721752
MainModule->setResilienceStrategy(ResilienceStrategy::Resilient);
753+
754+
Context->LoadedModules[MainModule->getName()] = MainModule;
755+
756+
// Create and add the module's files.
757+
SmallVector<FileUnit *, 16> files;
758+
if (!createFilesForMainModule(MainModule, files)) {
759+
for (auto *file : files)
760+
MainModule->addFile(*file);
761+
} else {
762+
// If we failed to load a partial module, mark the main module as having
763+
// "failed to load", as it will contain no files. Note that we don't try
764+
// to add any of the successfully loaded partial modules. This ensures
765+
// that we don't encounter cases where we try to resolve a cross-reference
766+
// into a partial module that failed to load.
767+
MainModule->setFailedToLoad();
768+
}
722769
}
723770
return MainModule;
724771
}
@@ -753,37 +800,13 @@ void CompilerInstance::performSemaUpTo(SourceFile::ASTStage_t LimitStage) {
753800
FrontendStatsTracer tracer(getStatsReporter(), "perform-sema");
754801

755802
ModuleDecl *mainModule = getMainModule();
756-
Context->LoadedModules[mainModule->getName()] = mainModule;
757-
758-
// Make sure the main file is the first file in the module, so do this now.
759-
if (MainBufferID != NO_SUCH_BUFFER) {
760-
auto *mainFile = createSourceFileForMainModule(
761-
Invocation.getSourceFileKind(), MainBufferID);
762-
mainFile->SyntaxParsingCache = Invocation.getMainFileSyntaxParsingCache();
763-
}
764-
765-
// If we aren't in a parse-only context, load the remaining serialized inputs
766-
// and resolve implicit imports.
767-
if (LimitStage > SourceFile::Unprocessed &&
768-
loadPartialModulesAndImplicitImports()) {
769-
// If we failed to load a partial module, mark the main module as having
770-
// "failed to load", as it may contain no files.
771-
mainModule->setFailedToLoad();
772-
return;
773-
}
774803

775804
// Then parse all the input files.
776-
// FIXME: This is the only demand point for InputSourceCodeBufferIDs. We
777-
// should compute this list of source files lazily.
778-
for (auto BufferID : InputSourceCodeBufferIDs) {
779-
SourceFile *SF;
780-
if (BufferID == MainBufferID) {
781-
// If this is the main file, we've already created it.
782-
SF = &getMainModule()->getMainSourceFile(Invocation.getSourceFileKind());
783-
} else {
784-
// Otherwise create a library file.
785-
SF = createSourceFileForMainModule(SourceFileKind::Library, BufferID);
786-
}
805+
for (auto *file : mainModule->getFiles()) {
806+
auto *SF = dyn_cast<SourceFile>(file);
807+
if (!SF)
808+
continue;
809+
787810
// Trigger parsing of the file.
788811
if (LimitStage == SourceFile::Unprocessed) {
789812
(void)SF->getTopLevelDecls();
@@ -795,15 +818,15 @@ void CompilerInstance::performSemaUpTo(SourceFile::ASTStage_t LimitStage) {
795818
if (LimitStage == SourceFile::Unprocessed)
796819
return;
797820

798-
assert(llvm::all_of(MainModule->getFiles(), [](const FileUnit *File) -> bool {
821+
assert(llvm::all_of(mainModule->getFiles(), [](const FileUnit *File) -> bool {
799822
auto *SF = dyn_cast<SourceFile>(File);
800823
if (!SF)
801824
return true;
802825
return SF->ASTStage >= SourceFile::ImportsResolved;
803826
}) && "some files have not yet had their imports resolved");
804-
MainModule->setHasResolvedImports();
827+
mainModule->setHasResolvedImports();
805828

806-
bindExtensions(*MainModule);
829+
bindExtensions(*mainModule);
807830

808831
// If the limiting AST stage is import resolution, we're done.
809832
if (LimitStage == SourceFile::ImportsResolved)
@@ -839,26 +862,27 @@ bool CompilerInstance::loadStdlibIfNeeded() {
839862
return false;
840863
}
841864

842-
bool CompilerInstance::loadPartialModulesAndImplicitImports() {
865+
bool CompilerInstance::loadPartialModulesAndImplicitImports(
866+
ModuleDecl *mod, SmallVectorImpl<FileUnit *> &partialModules) const {
843867
FrontendStatsTracer tracer(getStatsReporter(),
844868
"load-partial-modules-and-implicit-imports");
845869
// Force loading implicit imports. This is currently needed to allow
846870
// deserialization to resolve cross references into bridging headers.
847871
// FIXME: Once deserialization loads all the modules it needs for cross
848872
// references, this can be removed.
849-
(void)MainModule->getImplicitImports();
873+
(void)mod->getImplicitImports();
850874

875+
// Load in the partial modules.
851876
bool hadLoadError = false;
852-
// Parse all the partial modules first.
853877
for (auto &PM : PartialModules) {
854878
assert(PM.ModuleBuffer);
855879
auto *file =
856-
SML->loadAST(*MainModule, SourceLoc(), /*moduleInterfacePath*/ "",
880+
SML->loadAST(*mod, /*diagLoc*/ SourceLoc(), /*moduleInterfacePath*/ "",
857881
std::move(PM.ModuleBuffer), std::move(PM.ModuleDocBuffer),
858882
std::move(PM.ModuleSourceInfoBuffer),
859883
/*isFramework*/ false);
860884
if (file) {
861-
MainModule->addFile(*file);
885+
partialModules.push_back(file);
862886
} else {
863887
hadLoadError = true;
864888
}
@@ -869,7 +893,7 @@ bool CompilerInstance::loadPartialModulesAndImplicitImports() {
869893
void CompilerInstance::forEachFileToTypeCheck(
870894
llvm::function_ref<void(SourceFile &)> fn) {
871895
if (isWholeModuleCompilation()) {
872-
for (auto fileName : MainModule->getFiles()) {
896+
for (auto fileName : getMainModule()->getFiles()) {
873897
auto *SF = dyn_cast<SourceFile>(fileName);
874898
if (!SF) {
875899
continue;
@@ -928,15 +952,16 @@ CompilerInstance::getSourceFileParsingOptions(bool forPrimary) const {
928952
}
929953

930954
SourceFile *CompilerInstance::createSourceFileForMainModule(
931-
SourceFileKind fileKind, Optional<unsigned> bufferID) {
932-
ModuleDecl *mainModule = getMainModule();
933-
955+
ModuleDecl *mod, SourceFileKind fileKind,
956+
Optional<unsigned> bufferID) const {
934957
auto isPrimary = bufferID && isPrimaryInput(*bufferID);
935958
auto opts = getSourceFileParsingOptions(isPrimary);
936959

937960
auto *inputFile = new (*Context)
938-
SourceFile(*mainModule, fileKind, bufferID, opts, isPrimary);
939-
MainModule->addFile(*inputFile);
961+
SourceFile(*mod, fileKind, bufferID, opts, isPrimary);
962+
963+
if (bufferID == MainBufferID)
964+
inputFile->SyntaxParsingCache = Invocation.getMainFileSyntaxParsingCache();
940965

941966
return inputFile;
942967
}

0 commit comments

Comments
 (0)