diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 5c49c843fa3..9f471af6c74 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -27,6 +27,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/TinyPtrVector.h" namespace clang { class Module; @@ -361,19 +362,8 @@ public: template using IdentifierMap = llvm::DenseMap; - /// A map of operator names to InfixOperatorDecls. - /// Populated during name binding; the mapping will be incomplete until name - /// binding is complete. IdentifierMap InfixOperators; - - /// A map of operator names to PostfixOperatorDecls. - /// Populated during name binding; the mapping will be incomplete until name - /// binding is complete. IdentifierMap PostfixOperators; - - /// A map of operator names to PrefixOperatorDecls. - /// Populated during name binding; the mapping will be incomplete until name - /// binding is complete. IdentifierMap PrefixOperators; enum SourceKind { @@ -399,8 +389,10 @@ public: }; /// Defines what phases of parsing and semantic analysis are complete for a - /// source file. This should only be used for assertions and verification - /// purposes. + /// source file. + /// + /// Only files that have been fully processed (i.e. type-checked) will be + /// forwarded on to IRGen. ASTStage_t ASTStage = Parsing; SourceFile(TranslationUnit &tu, SourceKind K, Optional ImportID, @@ -497,14 +489,36 @@ class TranslationUnit : public Module { /// lookups. ExternalNameLookup *ExternalLookup = nullptr; -public: - // FIXME: Make private or eliminate altogether. - SourceFile *MainSourceFile; + TinyPtrVector SourceFiles; +public: TranslationUnit(Identifier Name, ASTContext &C) : Module(ModuleKind::TranslationUnit, Name, C) { } + ArrayRef getSourceFiles() { + return SourceFiles; + } + ArrayRef getSourceFiles() const { + return { SourceFiles.begin(), SourceFiles.size() }; + } + + void addSourceFile(SourceFile &newFile) { + // Require Main and REPL files to be the first file added. + assert(SourceFiles.empty() || + newFile.Kind == SourceFile::Library || + newFile.Kind == SourceFile::SIL); + SourceFiles.push_back(&newFile); + } + + /// Convenience accessor for clients that know what kind of file they're + /// dealing with. + SourceFile &getMainSourceFile(SourceFile::SourceKind expectedKind) const { + assert(!SourceFiles.empty() && "No files added yet"); + assert(SourceFiles.front()->Kind == expectedKind); + return *SourceFiles.front(); + } + ExternalNameLookup *getExternalLookup() const { return ExternalLookup; } void setExternalLookup(ExternalNameLookup *R) { assert(!ExternalLookup && "Name resolver already set"); diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 37e2cff20cd..eed2cc931b9 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -276,8 +276,10 @@ void Module::lookupValue(AccessPathTy AccessPath, Identifier Name, } if (auto TU = dyn_cast(this)) { - const SourceFile &SF = *TU->MainSourceFile; - return SF.getCache().lookupValue(AccessPath, Name, LookupKind, Result); + // FIXME: Access control. + for (const SourceFile *SF : TU->getSourceFiles()) + SF->getCache().lookupValue(AccessPath, Name, LookupKind, Result); + return; } ModuleLoader &owner = cast(this)->getOwner(); @@ -294,8 +296,10 @@ void Module::lookupVisibleDecls(AccessPathTy AccessPath, } if (auto TU = dyn_cast(this)) { - const SourceFile &SF = *TU->MainSourceFile; - return SF.getCache().lookupVisibleDecls(AccessPath, Consumer, LookupKind); + // FIXME: Access control. + for (const SourceFile *SF : TU->getSourceFiles()) + SF->getCache().lookupVisibleDecls(AccessPath, Consumer, LookupKind); + return; } ModuleLoader &owner = cast(this)->getOwner(); @@ -310,8 +314,10 @@ void Module::lookupClassMembers(AccessPathTy accessPath, } if (auto TU = dyn_cast(this)) { - const SourceFile &SF = *TU->MainSourceFile; - return SF.getCache().lookupClassMembers(accessPath, consumer, SF); + // FIXME: Access control. + for (const SourceFile *SF : TU->getSourceFiles()) + SF->getCache().lookupClassMembers(accessPath, consumer, *SF); + return; } ModuleLoader &owner = cast(this)->getOwner(); @@ -327,8 +333,10 @@ void Module::lookupClassMember(AccessPathTy accessPath, } if (auto TU = dyn_cast(this)) { - const SourceFile &SF = *TU->MainSourceFile; - return SF.getCache().lookupClassMember(accessPath, name, results, SF); + // FIXME: Access control. + for (const SourceFile *SF : TU->getSourceFiles()) + SF->getCache().lookupClassMember(accessPath, name, results, *SF); + return; } ModuleLoader &owner = cast(this)->getOwner(); @@ -341,8 +349,9 @@ void Module::getTopLevelDecls(SmallVectorImpl &Results) { } if (auto TU = dyn_cast(this)) { - Results.append(TU->MainSourceFile->Decls.begin(), - TU->MainSourceFile->Decls.end()); + // FIXME: Access control. + for (const SourceFile *SF : TU->getSourceFiles()) + Results.append(SF->Decls.begin(), SF->Decls.end()); return; } @@ -807,8 +816,9 @@ void Module::getDisplayDecls(SmallVectorImpl &results) { } if (auto TU = dyn_cast(this)) { - results.append(TU->MainSourceFile->Decls.begin(), - TU->MainSourceFile->Decls.end()); + // FIXME: Access control. + for (const SourceFile *SF : TU->getSourceFiles()) + results.append(SF->Decls.begin(), SF->Decls.end()); return; } @@ -830,11 +840,13 @@ Optional lookupOperatorDeclForName(Module *M, // Returns Nothing on error, Optional(nullptr) if no operator decl found, or // Optional(decl) if decl was found. template -Optional lookupOperatorDeclForName(SourceFile &SF, +Optional lookupOperatorDeclForName(const SourceFile &SF, SourceLoc Loc, Identifier Name, IdentifierMap SourceFile::*OP_MAP) { + assert(SF.ASTStage >= SourceFile::NameBound); + // Look for an operator declaration in the current module. auto found = (SF.*OP_MAP).find(Name); if (found != (SF.*OP_MAP).end()) @@ -852,11 +864,15 @@ Optional lookupOperatorDeclForName(SourceFile &SF, if (OP_DECL *op = *maybeOp) importedOperators.insert(op); } + + // FIXME: By caching our lookup, we are implicitly re-exporting the operator, + // and in a non-predictable way. Yuck. + auto &mutableOpMap = const_cast &>(SF.*OP_MAP); // Return early if we didn't find anything. if (importedOperators.empty()) { // Cache the mapping so we don't need to troll imports next time. - (SF.*OP_MAP)[Name] = nullptr; + mutableOpMap[Name] = nullptr; return nullptr; } @@ -875,7 +891,7 @@ Optional lookupOperatorDeclForName(SourceFile &SF, } } // Cache the mapping so we don't need to troll imports next time. - (SF.*OP_MAP)[Name] = first; + mutableOpMap[Name] = first; return first; } @@ -891,7 +907,21 @@ Optional lookupOperatorDeclForName(Module *M, auto *TU = dyn_cast(M); if (!TU) return nullptr; - return lookupOperatorDeclForName(*TU->MainSourceFile, Loc, Name, OP_MAP); + + // FIXME: Access control. + OP_DECL *result = nullptr; + for (const SourceFile *SF : TU->getSourceFiles()) { + auto next = lookupOperatorDeclForName(*SF, Loc, Name, OP_MAP); + if (!next.hasValue()) + return next; + + // FIXME: Diagnose ambiguity. + if (*next && result) + return Nothing; + if (*next) + result = *next; + } + return result; } } // end anonymous namespace @@ -925,9 +955,10 @@ Module::getImportedModules(SmallVectorImpl &modules, return; if (auto TU = dyn_cast(this)) { - for (auto importPair : TU->MainSourceFile->getImports()) - if (includePrivate || importPair.second) - modules.push_back(importPair.first); + for (auto SF : TU->getSourceFiles()) + for (auto importPair : SF->getImports()) + if (includePrivate || importPair.second) + modules.push_back(importPair.first); return; } @@ -969,8 +1000,10 @@ StringRef Module::getModuleFilename() const { return StringRef(); if (auto TU = dyn_cast(this)) { - if (auto ID = TU->MainSourceFile->getImportBufferID()) - return Ctx.SourceMgr->getMemoryBuffer(*ID)->getBufferIdentifier(); + // FIXME: Figure out what the right intent is here. + if (TU->getSourceFiles().size() == 1) + if (auto ID = TU->getSourceFiles().front()->getImportBufferID()) + return Ctx.SourceMgr->getMemoryBuffer(*ID)->getBufferIdentifier(); return StringRef(); } @@ -1083,7 +1116,11 @@ SourceFile::getCachedVisibleDecls() const { } bool TranslationUnit::walk(ASTWalker &Walker) { - return MainSourceFile->walk(Walker); + llvm::SaveAndRestore SAR(Walker.Parent, this); + for (auto SF : getSourceFiles()) + if (SF->walk(Walker)) + return true; + return false; } static void performAutoImport(SourceFile &SF, bool hasBuiltinModuleAccess) { diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index a98d796ca66..3bd878f8a76 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -125,7 +125,7 @@ void swift::CompilerInstance::doIt() { auto *SingleInputFile = new (*Context) SourceFile(*TU, Kind, Invocation.getParseStdlib()); - TU->MainSourceFile = SingleInputFile; + TU->addSourceFile(*SingleInputFile); if (Kind == SourceFile::REPL) return; diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index bc865edaf5a..2e4b2d149f7 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -169,7 +169,10 @@ static void performIRGeneration(Options &Opts, llvm::Module *Module, IGM.emitSourceFile(*SF, StartElem); } else { assert(StartElem == 0 && "no explicit source file provided"); - IGM.emitSourceFile(*TU->MainSourceFile, 0); + for (auto *SF : TU->getSourceFiles()) { + if (SF->ASTStage == SourceFile::TypeChecked) + IGM.emitSourceFile(*SF, 0); + } } // Objective-C image information. diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index 1e34a97ac26..0e1332c5b48 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -1152,8 +1152,9 @@ void SILModule::print(llvm::raw_ostream &OS, bool Verbose, Options.VarInitializers = true; Options.SkipImplicit = true; - for (auto ID = TU->MainSourceFile->Decls.begin(), - ED = TU->MainSourceFile->Decls.end(); ID != ED; ++ID) { + // FIXME: What about the rest of the files in the TU? + for (auto ID = TU->getSourceFiles().front()->Decls.begin(), + ED = TU->getSourceFiles().front()->Decls.end(); ID != ED; ++ID) { const Decl *D = *ID; if ((isa(D) || isa(D)) && !emittedFunctions.count(D) && diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 24b5e23a62d..037f3cb6bda 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -583,10 +583,12 @@ std::unique_ptr SILModule::constructSIL(TranslationUnit *tu, sgm.visit(D); } else { assert(startElem == 0 && "no explicit source file"); - // FIXME: Construct SIL for all source files, once there is more than one. - sf = tu->MainSourceFile; - for (Decl *D : llvm::makeArrayRef(sf->Decls).slice(startElem)) - sgm.visit(D); + for (auto nextSF : tu->getSourceFiles()) { + if (nextSF->ASTStage != SourceFile::TypeChecked) + continue; + for (Decl *D : llvm::makeArrayRef(nextSF->Decls).slice(startElem)) + sgm.visit(D); + } } // Emit external definitions used by this translation unit. diff --git a/lib/Sema/SourceLoader.cpp b/lib/Sema/SourceLoader.cpp index b2662176fdf..fd937d9f005 100644 --- a/lib/Sema/SourceLoader.cpp +++ b/lib/Sema/SourceLoader.cpp @@ -119,7 +119,7 @@ Module *SourceLoader::loadModule(SourceLoc importLoc, auto *importFile = new (Ctx) SourceFile(*importTU, SourceFile::Library, bufferID); - importTU->MainSourceFile = importFile; + importTU->addSourceFile(*importFile); bool done; PersistentParserState persistentState; diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 4ffa0eef3fc..dd4c55cbd21 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -135,7 +135,7 @@ Module *TypeChecker::getStdlibModule() { // module. for (auto &entry : Context.LoadedModules) { if (auto TU = dyn_cast_or_null(entry.getValue())) - if (!TU->MainSourceFile->getImportBufferID().hasValue()) + if (!TU->getSourceFiles().front()->getImportBufferID().hasValue()) StdlibModule = TU; } assert(StdlibModule && "no main module found"); @@ -481,14 +481,16 @@ void swift::performTypeChecking(SourceFile &SF, unsigned StartElem) { if (!importTU) return; // FIXME: Respect the access path? - for (auto D : importTU->MainSourceFile->Decls) { - if (auto ED = dyn_cast(D)) { - bindExtensionDecl(ED, TC); - if (mayConformToKnownProtocol(ED)) - TC.validateDecl(ED->getExtendedType()->getAnyNominal()); - } else if (auto nominal = dyn_cast(D)) { - if (mayConformToKnownProtocol(nominal)) - TC.validateDecl(nominal); + for (auto SF : importTU->getSourceFiles()) { + for (auto D : SF->Decls) { + if (auto ED = dyn_cast(D)) { + bindExtensionDecl(ED, TC); + if (mayConformToKnownProtocol(ED)) + TC.validateDecl(ED->getExtendedType()->getAnyNominal()); + } else if (auto nominal = dyn_cast(D)) { + if (mayConformToKnownProtocol(nominal)) + TC.validateDecl(nominal); + } } } }); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 3b100ae2f0b..91c0103df37 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -390,13 +390,16 @@ void Serializer::writeInputFiles(const TranslationUnit *TU, SourceFile.emit(ScratchRecord, path); } - for (auto import : TU->MainSourceFile->getImports()) { - if (import.first.second == TU->Ctx.TheBuiltinModule) - continue; + for (auto SF : TU->getSourceFiles()) { + // FIXME: Do some uniquing. + for (auto import : SF->getImports()) { + if (import.first.second == TU->Ctx.TheBuiltinModule) + continue; - ImportPathBlob importPath; - flattenImportPath(import.first, importPath); - ImportedModule.emit(ScratchRecord, import.second, importPath); + ImportPathBlob importPath; + flattenImportPath(import.first, importPath); + ImportedModule.emit(ScratchRecord, import.second, importPath); + } } if (!moduleLinkName.empty()) { @@ -2008,24 +2011,26 @@ void Serializer::writeTranslationUnit(const TranslationUnit *TU, writeSILFunctions(M); DeclTable topLevelDecls, extensionDecls, operatorDecls; - for (auto D : TU->MainSourceFile->Decls) { - if (isa(D)) - continue; - else if (auto VD = dyn_cast(D)) { - if (VD->getName().empty()) + for (auto SF : TU->getSourceFiles()) { + for (auto D : SF->Decls) { + if (isa(D)) continue; - topLevelDecls[VD->getName()] - .push_back({ getKindForTable(D), addDeclRef(D) }); + else if (auto VD = dyn_cast(D)) { + if (VD->getName().empty()) + continue; + topLevelDecls[VD->getName()] + .push_back({ getKindForTable(D), addDeclRef(D) }); - } else if (auto ED = dyn_cast(D)) { - Type extendedTy = ED->getExtendedType(); - const NominalTypeDecl *extendedNominal = extendedTy->getAnyNominal(); - extensionDecls[extendedNominal->getName()] - .push_back({ getKindForTable(extendedNominal), addDeclRef(D) }); + } else if (auto ED = dyn_cast(D)) { + Type extendedTy = ED->getExtendedType(); + const NominalTypeDecl *extendedNominal = extendedTy->getAnyNominal(); + extensionDecls[extendedNominal->getName()] + .push_back({ getKindForTable(extendedNominal), addDeclRef(D) }); - } else if (auto OD = dyn_cast(D)) { - operatorDecls[OD->getName()] - .push_back({ getStableFixity(OD->getKind()), addDeclRef(D) }); + } else if (auto OD = dyn_cast(D)) { + operatorDecls[OD->getName()] + .push_back({ getStableFixity(OD->getKind()), addDeclRef(D) }); + } } } diff --git a/tools/swift/Immediate.cpp b/tools/swift/Immediate.cpp index fa2598f3525..2edad58a507 100644 --- a/tools/swift/Immediate.cpp +++ b/tools/swift/Immediate.cpp @@ -1025,7 +1025,7 @@ public: REPLEnvironment(CompilerInstance &CI, bool ShouldRunREPLApplicationMain, const ProcessCmdLine &CmdLine) - : CI(CI), REPLInputFile(*CI.getTU()->MainSourceFile), + : CI(CI), REPLInputFile(CI.getTU()->getMainSourceFile(SourceFile::REPL)), ShouldRunREPLApplicationMain(ShouldRunREPLApplicationMain), CmdLine(CmdLine), RanGlobalInitializers(false),