summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp25
-rw-r--r--clang/lib/AST/ExternalASTSource.cpp5
-rw-r--r--clang/lib/Basic/Module.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp1
-rw-r--r--clang/lib/Lex/ModuleMap.cpp13
-rw-r--r--clang/lib/Sema/MultiplexExternalSemaSource.cpp9
-rw-r--r--clang/lib/Serialization/ASTReader.cpp30
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp22
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp9
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) {
OpenPOWER on IntegriCloud