r293456 - Prototype of modules codegen

David Blaikie via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 29 21:00:27 PST 2017


Author: dblaikie
Date: Sun Jan 29 23:00:26 2017
New Revision: 293456

URL: http://llvm.org/viewvc/llvm-project?rev=293456&view=rev
Log:
Prototype of modules codegen

First pass at generating weak definitions of inline functions from module files
(& skipping (-O0) or emitting available_externally (optimizations)
definitions where those modules are used).

External functions defined in modules are emitted into the modular
object file as well (this may turn an existing ODR violation (if that
module were imported into multiple translations) into valid/linkable
code).

Internal symbols (static functions, for example) are not correctly
supported yet. The symbol will be produced, internal, in the modular
object - unreferenceable from the users.

Reviewers: rsmith

Differential Revision: https://reviews.llvm.org/D28845

Added:
    cfe/trunk/test/Modules/Inputs/codegen/
    cfe/trunk/test/Modules/Inputs/codegen/bar.h
    cfe/trunk/test/Modules/Inputs/codegen/bar.modulemap
    cfe/trunk/test/Modules/Inputs/codegen/foo.h
    cfe/trunk/test/Modules/Inputs/codegen/foo.modulemap
    cfe/trunk/test/Modules/Inputs/codegen/use.cpp
    cfe/trunk/test/Modules/codegen.test
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/ExternalASTSource.h
    cfe/trunk/include/clang/Basic/LangOptions.def
    cfe/trunk/include/clang/Basic/Module.h
    cfe/trunk/include/clang/Driver/CC1Options.td
    cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ExternalASTSource.cpp
    cfe/trunk/lib/Basic/Module.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Sun Jan 29 23:00:26 2017
@@ -2494,7 +2494,7 @@ public:
   ///
   /// \returns true if the function/var must be CodeGen'ed/deserialized even if
   /// it is not used.
-  bool DeclMustBeEmitted(const Decl *D);
+  bool DeclMustBeEmitted(const Decl *D, bool ForModularCodegen = false);
 
   const CXXConstructorDecl *
   getCopyConstructorForExceptionObject(CXXRecordDecl *RD);

Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h Sun Jan 29 23:00:26 2017
@@ -16,6 +16,7 @@
 
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclBase.h"
+#include "clang/Basic/Module.h"
 #include "llvm/ADT/DenseMap.h"
 
 namespace clang {
@@ -169,6 +170,10 @@ public:
   /// Return a descriptor for the corresponding module, if one exists.
   virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
 
+  enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
+
+  virtual ExtKind hasExternalDefinitions(unsigned ID);
+
   /// \brief Finds all declarations lexically contained within the given
   /// DeclContext, after applying an optional filter predicate.
   ///

Modified: cfe/trunk/include/clang/Basic/LangOptions.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.def (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.def Sun Jan 29 23:00:26 2017
@@ -201,6 +201,7 @@ LANGOPT(SizedDeallocation , 1, 0, "sized
 LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
 LANGOPT(NewAlignOverride  , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'")
 LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts")
+BENIGN_LANGOPT(ModularCodegen , 1, 0, "Modular codegen")
 BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
 BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records")
 BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form")

Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Sun Jan 29 23:00:26 2017
@@ -205,6 +205,8 @@ public:
   /// and headers from used modules.
   unsigned NoUndeclaredIncludes : 1;
 
+  unsigned WithCodegen : 1;
+
   /// \brief Describes the visibility of the various names within a
   /// particular module.
   enum NameVisibilityKind {

Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Sun Jan 29 23:00:26 2017
@@ -432,6 +432,10 @@ def fmodules_local_submodule_visibility
   Flag<["-"], "fmodules-local-submodule-visibility">,
   HelpText<"Enforce name visibility rules across submodules of the same "
            "top-level module.">;
+def fmodule_codegen :
+  Flag<["-"], "fmodules-codegen">,
+  HelpText<"Generate code for uses of this module that assumes an explicit "
+           "object file will be built for the module">;
 def fmodule_format_EQ : Joined<["-"], "fmodule-format=">,
   HelpText<"Select the container format for clang modules and PCH. "
            "Supported options are 'raw' and 'obj'.">;

Modified: cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h (original)
+++ cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h Sun Jan 29 23:00:26 2017
@@ -90,6 +90,8 @@ public:
   /// initializers themselves.
   CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
 
+  ExtKind hasExternalDefinitions(unsigned ID) override;
+
   /// \brief Find all declarations with the given name in the
   /// given context.
   bool FindExternalVisibleDeclsByName(const DeclContext *DC,

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Sun Jan 29 23:00:26 2017
@@ -591,6 +591,8 @@ namespace clang {
 
       /// \brief Record code for declarations associated with OpenCL extensions.
       OPENCL_EXTENSION_DECLS = 59,
+
+      MODULAR_CODEGEN_DECLS = 60,
     };
 
     /// \brief Record types used within a source manager block.

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Sun Jan 29 23:00:26 2017
@@ -715,6 +715,8 @@ private:
   /// the consumer eagerly.
   SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
 
+  SmallVector<uint64_t, 16> ModularCodegenDecls;
+
   /// \brief The IDs of all tentative definitions stored in the chain.
   ///
   /// Sema keeps track of all tentative definitions in a TU because it has to
@@ -1968,6 +1970,8 @@ public:
   /// \brief Return a descriptor for the corresponding module.
   llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override;
 
+  ExtKind hasExternalDefinitions(unsigned ID) override;
+
   /// \brief Retrieve a selector from the given module with its local ID
   /// number.
   Selector getLocalSelector(ModuleFile &M, unsigned LocalID);

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Sun Jan 29 23:00:26 2017
@@ -365,6 +365,7 @@ private:
   /// IDs, since they will be written out to an EAGERLY_DESERIALIZED_DECLS
   /// record.
   SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
+  SmallVector<uint64_t, 16> ModularCodegenDecls;
 
   /// \brief DeclContexts that have received extensions since their serialized
   /// form.

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sun Jan 29 23:00:26 2017
@@ -8882,8 +8882,22 @@ static GVALinkage adjustGVALinkageForAtt
 }
 
 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::GetGVALinkageForV
       *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
       }
     }
 
+    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);

Modified: cfe/trunk/lib/AST/ExternalASTSource.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExternalASTSource.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExternalASTSource.cpp (original)
+++ cfe/trunk/lib/AST/ExternalASTSource.cpp Sun Jan 29 23:00:26 2017
@@ -28,6 +28,11 @@ ExternalASTSource::getSourceDescriptor(u
   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)

Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Sun Jan 29 23:00:26 2017
@@ -33,7 +33,7 @@ Module::Module(StringRef Name, SourceLoc
       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;

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sun Jan 29 23:00:26 2017
@@ -2796,7 +2796,7 @@ llvm::GlobalValue::LinkageTypes CodeGenM
   // 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.

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Sun Jan 29 23:00:26 2017
@@ -1955,6 +1955,7 @@ static void ParseLangArgs(LangOptions &O
       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);

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Sun Jan 29 23:00:26 2017
@@ -91,6 +91,7 @@ ModuleMap::ModuleMap(SourceManager &Sour
       HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
       SourceModule(nullptr), NumCreatedModules(0) {
   MMapLangOpts.LineComment = true;
+  MMapLangOpts.ModularCodegen = LangOpts.ModularCodegen;
 }
 
 ModuleMap::~ModuleMap() {
@@ -554,16 +555,17 @@ Module *ModuleMap::lookupModuleQualified
   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());

Modified: cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp (original)
+++ cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp Sun Jan 29 23:00:26 2017
@@ -94,6 +94,15 @@ MultiplexExternalSemaSource::GetExternal
   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;

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Sun Jan 29 23:00:26 2017
@@ -2607,7 +2607,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, u
         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, u
         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
       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
 
       // 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
       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
   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));
 }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Sun Jan 29 23:00:26 2017
@@ -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 *
   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 *
 
     // 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 &S
   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);

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=293456&r1=293455&r2=293456&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Sun Jan 29 23:00:26 2017
@@ -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
     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 &Co
 
   // 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) {

Added: cfe/trunk/test/Modules/Inputs/codegen/bar.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen/bar.h?rev=293456&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen/bar.h (added)
+++ cfe/trunk/test/Modules/Inputs/codegen/bar.h Sun Jan 29 23:00:26 2017
@@ -0,0 +1,2 @@
+#include "foo.h"
+inline void bar() { foo(); }

Added: cfe/trunk/test/Modules/Inputs/codegen/bar.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen/bar.modulemap?rev=293456&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen/bar.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/codegen/bar.modulemap Sun Jan 29 23:00:26 2017
@@ -0,0 +1 @@
+module bar { header "bar.h" }

Added: cfe/trunk/test/Modules/Inputs/codegen/foo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen/foo.h?rev=293456&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen/foo.h (added)
+++ cfe/trunk/test/Modules/Inputs/codegen/foo.h Sun Jan 29 23:00:26 2017
@@ -0,0 +1,10 @@
+void f1(int &);
+static void f2() {}
+inline void foo() {
+  static int i;
+  f1(i);
+  f2();
+}
+inline void foo2() {
+}
+void foo_ext() {}

Added: cfe/trunk/test/Modules/Inputs/codegen/foo.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen/foo.modulemap?rev=293456&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen/foo.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/codegen/foo.modulemap Sun Jan 29 23:00:26 2017
@@ -0,0 +1 @@
+module foo { header "foo.h" }

Added: cfe/trunk/test/Modules/Inputs/codegen/use.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen/use.cpp?rev=293456&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen/use.cpp (added)
+++ cfe/trunk/test/Modules/Inputs/codegen/use.cpp Sun Jan 29 23:00:26 2017
@@ -0,0 +1,2 @@
+#include "bar.h"
+int main() { bar(); }

Added: cfe/trunk/test/Modules/codegen.test
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/codegen.test?rev=293456&view=auto
==============================================================================
--- cfe/trunk/test/Modules/codegen.test (added)
+++ cfe/trunk/test/Modules/codegen.test Sun Jan 29 23:00:26 2017
@@ -0,0 +1,64 @@
+RUN: rm -rf %t
+
+RUN: %clang_cc1 -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm
+RUN: %clang_cc1 -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=bar %S/Inputs/codegen/bar.modulemap -o %t/bar.pcm -fmodule-file=%t/foo.pcm
+
+RUN: %clang_cc1 -emit-llvm %t/foo.pcm -o - | FileCheck --check-prefix=FOO %s
+RUN: %clang_cc1 -emit-llvm %t/bar.pcm -o - -fmodule-file=%t/foo.pcm | FileCheck --check-prefix=BAR-CMN --check-prefix=BAR %s
+RUN: %clang_cc1 -fmodules -fmodule-file=%t/foo.pcm -fmodule-file=%t/bar.pcm %S/Inputs/codegen/use.cpp -emit-llvm -o - | FileCheck --check-prefix=USE-CMN --check-prefix=USE %s
+
+RUN: %clang_cc1 -O2 -disable-llvm-passes -emit-llvm %t/foo.pcm -o - | FileCheck --check-prefix=FOO %s
+RUN: %clang_cc1 -O2 -disable-llvm-passes -emit-llvm %t/bar.pcm -o - -fmodule-file=%t/foo.pcm | FileCheck --check-prefix=BAR-CMN --check-prefix=BAR-OPT %s
+RUN: %clang_cc1 -O2 -disable-llvm-passes -fmodules -fmodule-file=%t/foo.pcm -fmodule-file=%t/bar.pcm %S/Inputs/codegen/use.cpp -emit-llvm -o - | FileCheck --check-prefix=USE-CMN --check-prefix=USE-OPT %s
+
+FOO-NOT: comdat
+FOO: $_Z3foov = comdat any
+FOO: $_Z4foo2v = comdat any
+FOO: $_ZZ3foovE1i = comdat any
+FOO: @_ZZ3foovE1i = linkonce_odr global i32 0, comdat
+FOO-NOT: {{comdat|define|declare}}
+FOO: define void @_Z7foo_extv()
+FOO-NOT: {{define|declare}}
+FOO: define weak_odr void @_Z3foov() #{{[0-9]+}} comdat
+FOO-NOT: {{define|declare}}
+FOO: declare void @_Z2f1Ri(i32*
+FOO-NOT: {{define|declare}}
+
+FIXME: this internal function should be weak_odr, comdat, and with a new mangling
+FOO: define internal void @_ZL2f2v() #{{[0-9]+}}
+FOO-NOT: {{define|declare}}
+
+FOO: define weak_odr void @_Z4foo2v() #{{[0-9]+}} comdat
+FOO-NOT: {{define|declare}}
+
+
+BAR-CMN-NOT: comdat
+BAR-CMN: $_Z3barv = comdat any
+BAR-OPT: @_ZZ3foovE1i = linkonce_odr global i32 0, comdat
+BAR-CMN-NOT: {{comdat|define|declare}}
+BAR-CMN: define weak_odr void @_Z3barv() #{{[0-9]+}} comdat
+BAR-CMN-NOT: {{define|declare}}
+BAR: declare void @_Z3foov()
+Include all the available_externally definitions required for bar (foo -> f2)
+BAR-OPT: define available_externally void @_Z3foov()
+BAR-CMN-NOT: {{define|declare}}
+BAR-OPT: declare void @_Z2f1Ri(i32*
+BAR-OPT-NOT: {{define|declare}}
+BAR-OPT: define available_externally void @_ZL2f2v()
+BAR-OPT-NOT: {{define|declare}}
+
+
+USE-OPT: @_ZZ3foovE1i = linkonce_odr global i32 0, comdat
+USE-CMN-NOT: {{comdat|define|declare}}
+USE-CMN: define i32 @main()
+USE-CMN-NOT: {{define|declare}}
+USE: declare void @_Z3barv()
+Include all the available_externally definitions required for main (bar -> foo -> f2)
+USE-OPT: define available_externally void @_Z3barv()
+USE-CMN-NOT: {{define|declare}}
+USE-OPT: define available_externally void @_Z3foov()
+USE-OPT-NOT: {{define|declare}}
+USE-OPT: declare void @_Z2f1Ri(i32*
+USE-OPT-NOT: {{define|declare}}
+USE-OPT: define available_externally void @_ZL2f2v()
+USE-OPT-NOT: {{define|declare}}




More information about the cfe-commits mailing list