diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 25 | ||||
-rw-r--r-- | clang/lib/AST/ExternalASTSource.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Basic/Module.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/MultiplexExternalSemaSource.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 9 |
10 files changed, 97 insertions, 21 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 07721b2ba7c..1539a52e7fd 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -8882,8 +8882,22 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { - return adjustGVALinkageForAttributes( + auto L = adjustGVALinkageForAttributes( *this, basicGVALinkageForFunction(*this, FD), FD); + auto EK = ExternalASTSource::EK_ReplyHazy; + if (auto *Ext = getExternalSource()) + EK = Ext->hasExternalDefinitions(FD->getOwningModuleID()); + switch (EK) { + case ExternalASTSource::EK_Never: + if (L == GVA_DiscardableODR) + return GVA_StrongODR; + break; + case ExternalASTSource::EK_Always: + return GVA_AvailableExternally; + case ExternalASTSource::EK_ReplyHazy: + break; + } + return L; } static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, @@ -8968,7 +8982,7 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { *this, basicGVALinkageForVariable(*this, VD), VD); } -bool ASTContext::DeclMustBeEmitted(const Decl *D) { +bool ASTContext::DeclMustBeEmitted(const Decl *D, bool ForModularCodegen) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (!VD->isFileVarDecl()) return false; @@ -9032,10 +9046,15 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { } } + GVALinkage Linkage = GetGVALinkageForFunction(FD); + + if (Linkage == GVA_DiscardableODR && ForModularCodegen) + return true; + // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. // Implicit template instantiations can also be deferred in C++. - return !isDiscardableGVALinkage(GetGVALinkageForFunction(FD)); + return !isDiscardableGVALinkage(Linkage); } const VarDecl *VD = cast<VarDecl>(D); diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp index e3de8c5fefa..26b1aef0a8f 100644 --- a/clang/lib/AST/ExternalASTSource.cpp +++ b/clang/lib/AST/ExternalASTSource.cpp @@ -28,6 +28,11 @@ ExternalASTSource::getSourceDescriptor(unsigned ID) { return None; } +ExternalASTSource::ExtKind +ExternalASTSource::hasExternalDefinitions(unsigned ID) { + return EK_ReplyHazy; +} + ExternalASTSource::ASTSourceDescriptor::ASTSourceDescriptor(const Module &M) : Signature(M.Signature), ClangModule(&M) { if (M.Directory) diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 80bbc24f3db..719ff6709ff 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -33,7 +33,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, IsExplicit(IsExplicit), IsSystem(false), IsExternC(false), IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false), InferExportWildcard(false), ConfigMacrosExhaustive(false), - NoUndeclaredIncludes(false), NameVisibility(Hidden) { + NoUndeclaredIncludes(false), WithCodegen(false), NameVisibility(Hidden) { if (Parent) { if (!Parent->isAvailable()) IsAvailable = false; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index f9866957a14..d8e1d581150 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2796,7 +2796,7 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( // We are guaranteed to have a strong definition somewhere else, // so we can use available_externally linkage. if (Linkage == GVA_AvailableExternally) - return llvm::Function::AvailableExternallyLinkage; + return llvm::GlobalValue::AvailableExternallyLinkage; // Note that Apple's kernel linker doesn't support symbol // coalescing, so we need to avoid linkonce and weak linkages there. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index ee46f921ccb..a8c1e616577 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1955,6 +1955,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse; Opts.ModulesLocalVisibility = Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS; + Opts.ModularCodegen = Args.hasArg(OPT_fmodule_codegen); Opts.ModulesSearchAll = Opts.Modules && !Args.hasArg(OPT_fno_modules_search_all) && Args.hasArg(OPT_fmodules_search_all); diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 1488f624da6..1db5becac4b 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -91,6 +91,7 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr), SourceModule(nullptr), NumCreatedModules(0) { MMapLangOpts.LineComment = true; + MMapLangOpts.ModularCodegen = LangOpts.ModularCodegen; } ModuleMap::~ModuleMap() { @@ -554,16 +555,17 @@ Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ return Context->findSubmodule(Name); } -std::pair<Module *, bool> -ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, - bool IsExplicit) { +std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, + Module *Parent, + bool IsFramework, + bool IsExplicit) { // Try to find an existing module with this name. if (Module *Sub = lookupModuleQualified(Name, Parent)) return std::make_pair(Sub, false); // Create a new module with this name. - Module *Result = new Module(Name, SourceLocation(), Parent, - IsFramework, IsExplicit, NumCreatedModules++); + Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, + IsExplicit, NumCreatedModules++); if (!Parent) { if (LangOpts.CurrentModule == Name) SourceModule = Result; @@ -1499,6 +1501,7 @@ void ModuleMapParser::parseModuleDecl() { (!ActiveModule->Parent && ModuleName == "Darwin")) ActiveModule->NoUndeclaredIncludes = true; ActiveModule->Directory = Directory; + ActiveModule->WithCodegen = L.getLangOpts().ModularCodegen; if (!ActiveModule->Parent) { StringRef MapFileName(ModuleMapFile->getName()); diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 077a56ff8e7..c97e4dfdd6d 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -94,6 +94,15 @@ MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) { return nullptr; } +ExternalASTSource::ExtKind +MultiplexExternalSemaSource::hasExternalDefinitions(unsigned int ID) { + for (const auto &S : Sources) + if (auto EK = S->hasExternalDefinitions(ID)) + if (EK != EK_ReplyHazy) + return EK; + return EK_ReplyHazy; +} + bool MultiplexExternalSemaSource:: FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { bool AnyDeclsFound = false; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 44cef7de312..e3122039c7d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2607,7 +2607,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { break; case SUBMODULE_BLOCK_ID: - if (ASTReadResult Result = ReadSubmoduleBlock(F, ClientLoadCapabilities)) + if (ASTReadResult Result = + ReadSubmoduleBlock(F, ClientLoadCapabilities)) return Result; break; @@ -2772,6 +2773,14 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); break; + case MODULAR_CODEGEN_DECLS: + // FIXME: Skip reading this record if our ASTConsumer doesn't care about + // them (ie: if we're not codegenerating this module). + if (F.Kind == MK_MainFile) + for (unsigned I = 0, N = Record.size(); I != N; ++I) + EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); + break; + case SPECIAL_TYPES: if (SpecialTypes.empty()) { for (unsigned I = 0, N = Record.size(); I != N; ++I) @@ -4628,6 +4637,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { bool InferExplicitSubmodules = Record[Idx++]; bool InferExportWildcard = Record[Idx++]; bool ConfigMacrosExhaustive = Record[Idx++]; + bool WithCodegen = Record[Idx++]; Module *ParentModule = nullptr; if (Parent) @@ -4635,8 +4645,9 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // Retrieve this (sub)module from the module map, creating it if // necessary. - CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, IsFramework, - IsExplicit).first; + CurrentModule = + ModMap.findOrCreateModule(Name, ParentModule, IsFramework, IsExplicit) + .first; // FIXME: set the definition loc for CurrentModule, or call // ModMap.setInferredModuleAllowedBy() @@ -4672,6 +4683,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules; CurrentModule->InferExportWildcard = InferExportWildcard; CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive; + CurrentModule->WithCodegen = WithCodegen; if (DeserializationListener) DeserializationListener->ModuleRead(GlobalID, CurrentModule); @@ -7895,6 +7907,18 @@ ASTReader::getSourceDescriptor(unsigned ID) { return None; } +ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(unsigned ID) { + const Module *M = getSubmodule(ID); + if (!M || !M->WithCodegen) + return EK_ReplyHazy; + + ModuleFile *MF = ModuleMgr.lookup(M->getASTFile()); + assert(MF); // ? + if (MF->Kind == ModuleKind::MK_MainFile) + return EK_Never; + return EK_Always; +} + Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) { return DecodeSelector(getGlobalSelectorID(M, LocalID)); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index a0caca9b26c..cfd4c38888d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1044,6 +1044,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(IDENTIFIER_OFFSET); RECORD(IDENTIFIER_TABLE); RECORD(EAGERLY_DESERIALIZED_DECLS); + RECORD(MODULAR_CODEGEN_DECLS); RECORD(SPECIAL_TYPES); RECORD(STATISTICS); RECORD(TENTATIVE_DEFINITIONS); @@ -2589,6 +2590,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh... + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // WithCodegen Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); @@ -2677,11 +2679,18 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { // Emit the definition of the block. { - RecordData::value_type Record[] = { - SUBMODULE_DEFINITION, ID, ParentID, Mod->IsFramework, Mod->IsExplicit, - Mod->IsSystem, Mod->IsExternC, Mod->InferSubmodules, - Mod->InferExplicitSubmodules, Mod->InferExportWildcard, - Mod->ConfigMacrosExhaustive}; + RecordData::value_type Record[] = {SUBMODULE_DEFINITION, + ID, + ParentID, + Mod->IsFramework, + Mod->IsExplicit, + Mod->IsSystem, + Mod->IsExternC, + Mod->InferSubmodules, + Mod->InferExplicitSubmodules, + Mod->InferExportWildcard, + Mod->ConfigMacrosExhaustive, + Mod->WithCodegen}; Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name); } @@ -4694,6 +4703,9 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, if (!EagerlyDeserializedDecls.empty()) Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); + if (Context.getLangOpts().ModularCodegen) + Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); + // Write the record containing tentative definitions. if (!TentativeDefinitions.empty()) Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 292861755ba..6629036809f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2153,7 +2153,7 @@ void ASTWriter::WriteDeclAbbrevs() { /// relatively painless since they would presumably only do it for top-level /// decls. static bool isRequiredDecl(const Decl *D, ASTContext &Context, - bool WritingModule) { + bool WritingModule, bool ModularCode) { // An ObjCMethodDecl is never considered as "required" because its // implementation container always is. @@ -2169,7 +2169,7 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context, return false; } - return Context.DeclMustBeEmitted(D); + return Context.DeclMustBeEmitted(D, ModularCode); } void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { @@ -2213,8 +2213,11 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { // Note declarations that should be deserialized eagerly so that we can add // them to a record in the AST file later. - if (isRequiredDecl(D, Context, WritingModule)) + if (isRequiredDecl(D, Context, WritingModule, false)) EagerlyDeserializedDecls.push_back(ID); + else if (Context.getLangOpts().ModularCodegen && WritingModule && + isRequiredDecl(D, Context, true, true)) + ModularCodegenDecls.push_back(ID); } void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { |