[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen

2017-04-11 Thread David Blaikie via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL299982: Modular Codegen: Add/use a bit in serialized 
function definitions to trackā€¦ (authored by dblaikie).

Changed prior to commit:
  https://reviews.llvm.org/D29901?vs=91193=94886#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D29901

Files:
  cfe/trunk/include/clang/AST/ASTContext.h
  cfe/trunk/include/clang/AST/ExternalASTSource.h
  cfe/trunk/include/clang/Basic/Module.h
  cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
  cfe/trunk/include/clang/Serialization/ASTReader.h
  cfe/trunk/lib/AST/ASTContext.cpp
  cfe/trunk/lib/AST/ExternalASTSource.cpp
  cfe/trunk/lib/Basic/Module.cpp
  cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
  cfe/trunk/lib/Serialization/ASTReader.cpp
  cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
  cfe/trunk/lib/Serialization/ASTWriter.cpp
  cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
  cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.h
  cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.modulemap
  cfe/trunk/test/Modules/Inputs/codegen/foo.h
  cfe/trunk/test/Modules/Inputs/codegen/use.cpp
  cfe/trunk/test/Modules/codegen-nodep.test
  cfe/trunk/test/Modules/codegen.test

Index: cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
===
--- cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
+++ cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -90,7 +90,7 @@
   /// initializers themselves.
   CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
 
-  ExtKind hasExternalDefinitions(unsigned ID) override;
+  ExtKind hasExternalDefinitions(const FunctionDecl *FD) override;
 
   /// \brief Find all declarations with the given name in the
   /// given context.
Index: cfe/trunk/include/clang/Basic/Module.h
===
--- cfe/trunk/include/clang/Basic/Module.h
+++ cfe/trunk/include/clang/Basic/Module.h
@@ -215,8 +215,6 @@
   /// 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 {
Index: cfe/trunk/include/clang/Serialization/ASTReader.h
===
--- cfe/trunk/include/clang/Serialization/ASTReader.h
+++ cfe/trunk/include/clang/Serialization/ASTReader.h
@@ -1115,6 +1115,8 @@
   /// predefines buffer may contain additional definitions.
   std::string SuggestedPredefines;
 
+  llvm::DenseMap BodySource;
+
   /// \brief Reads a statement from the specified cursor.
   Stmt *ReadStmtFromStream(ModuleFile );
 
@@ -1997,7 +1999,7 @@
   /// \brief Return a descriptor for the corresponding module.
   llvm::Optional getSourceDescriptor(unsigned ID) override;
 
-  ExtKind hasExternalDefinitions(unsigned ID) override;
+  ExtKind hasExternalDefinitions(const FunctionDecl *FD) override;
 
   /// \brief Retrieve a selector from the given module with its local ID
   /// number.
Index: cfe/trunk/include/clang/AST/ExternalASTSource.h
===
--- cfe/trunk/include/clang/AST/ExternalASTSource.h
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h
@@ -172,7 +172,7 @@
 
   enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
 
-  virtual ExtKind hasExternalDefinitions(unsigned ID);
+  virtual ExtKind hasExternalDefinitions(const FunctionDecl *FD);
 
   /// \brief Finds all declarations lexically contained within the given
   /// DeclContext, after applying an optional filter predicate.
Index: cfe/trunk/include/clang/AST/ASTContext.h
===
--- cfe/trunk/include/clang/AST/ASTContext.h
+++ cfe/trunk/include/clang/AST/ASTContext.h
@@ -2510,7 +2510,7 @@
   ///
   /// \returns true if the function/var must be CodeGen'ed/deserialized even if
   /// it is not used.
-  bool DeclMustBeEmitted(const Decl *D, bool ForModularCodegen = false);
+  bool DeclMustBeEmitted(const Decl *D);
 
   const CXXConstructorDecl *
   getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
Index: cfe/trunk/test/Modules/Inputs/codegen/use.cpp
===
--- cfe/trunk/test/Modules/Inputs/codegen/use.cpp
+++ cfe/trunk/test/Modules/Inputs/codegen/use.cpp
@@ -0,0 +1,8 @@
+#include "foo.h"
+void non_modular_use_of_implicit_dtor() {
+  implicit_dtor d1;
+  uninst_implicit_dtor d2;
+}
+void use_of_instantiated_declaration_without_definition() {
+  inst();
+}
Index: cfe/trunk/test/Modules/Inputs/codegen/foo.h
===
--- cfe/trunk/test/Modules/Inputs/codegen/foo.h
+++ cfe/trunk/test/Modules/Inputs/codegen/foo.h
@@ -2,3 +2,29 @@
   __builtin_va_list args;
   __builtin_va_start(args, fmt);
 }
+
+struct 

[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen

2017-03-09 Thread David Blaikie via Phabricator via cfe-commits
dblaikie added a comment.

Ping

I've got a relatively small patch to add support for debug info types after 
this one & working on a patch on top of that to enable one/the other/both of 
these (to test their value independently/together). Might be more expedient to 
sit down & push through them all together side-by-side? Or not, not sure.


https://reviews.llvm.org/D29901



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen

2017-03-09 Thread David Blaikie via Phabricator via cfe-commits
dblaikie updated this revision to Diff 91193.
dblaikie added a comment.

sync/resolve


https://reviews.llvm.org/D29901

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/ExternalASTSource.h
  include/clang/Sema/MultiplexExternalSemaSource.h
  include/clang/Serialization/ASTReader.h
  lib/AST/ASTContext.cpp
  lib/AST/ExternalASTSource.cpp
  lib/Sema/MultiplexExternalSemaSource.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTReaderDecl.cpp
  lib/Serialization/ASTWriterDecl.cpp
  test/Modules/Inputs/codegen/foo.h
  test/Modules/Inputs/codegen/use.cpp
  test/Modules/codegen.test

Index: test/Modules/codegen.test
===
--- test/Modules/codegen.test
+++ test/Modules/codegen.test
@@ -3,8 +3,23 @@
 
 RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm
 
-RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s
 
-CHECK: $_Z2f1PKcz = comdat any
-CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
-CHECK:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+FOO: $_Z2f1PKcz = comdat any
+FOO: $_ZN13implicit_dtorD1Ev = comdat any
+USE: $_Z4instIiEvv = comdat any
+FOO: $_ZN13implicit_dtorD2Ev = comdat any
+FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
+FOO:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+
+Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user.
+FIXME: Proactively instantiate any valid implicit special members to emit them into the module object.
+
+FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+FOO: define weak_odr void @_Z4instIfEvv() #0 comdat {
+FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat {
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
Index: test/Modules/Inputs/codegen/use.cpp
===
--- /dev/null
+++ test/Modules/Inputs/codegen/use.cpp
@@ -0,0 +1,8 @@
+#include "foo.h"
+void non_modular_use_of_implicit_dtor() {
+  implicit_dtor d1;
+  uninst_implicit_dtor d2;
+}
+void use_of_instantiated_declaration_without_definition() {
+  inst();
+}
Index: test/Modules/Inputs/codegen/foo.h
===
--- test/Modules/Inputs/codegen/foo.h
+++ test/Modules/Inputs/codegen/foo.h
@@ -2,3 +2,29 @@
   __builtin_va_list args;
   __builtin_va_start(args, fmt);
 }
+
+struct non_trivial_dtor {
+  ~non_trivial_dtor();
+};
+
+struct implicit_dtor {
+  non_trivial_dtor d;
+};
+
+struct uninst_implicit_dtor {
+  non_trivial_dtor d;
+};
+
+inline void use_implicit_dtor() {
+  implicit_dtor d;
+}
+
+template
+void inst() {
+}
+
+inline void inst_decl() {
+  // cause inst's declaration to be instantiated, without a definition.
+  (void)sizeof();
+  inst();
+}
Index: lib/Serialization/ASTWriterDecl.cpp
===
--- lib/Serialization/ASTWriterDecl.cpp
+++ lib/Serialization/ASTWriterDecl.cpp
@@ -2157,7 +2157,7 @@
 /// relatively painless since they would presumably only do it for top-level
 /// decls.
 static bool isRequiredDecl(const Decl *D, ASTContext ,
-   bool WritingModule, bool ModularCode) {
+   bool WritingModule) {
   // An ObjCMethodDecl is never considered as "required" because its
   // implementation container always is.
 
@@ -2173,7 +2173,7 @@
 return false;
   }
 
-  return Context.DeclMustBeEmitted(D, ModularCode);
+  return Context.DeclMustBeEmitted(D);
 }
 
 void ASTWriter::WriteDecl(ASTContext , Decl *D) {
@@ -2217,18 +2217,20 @@
 
   // 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, false))
+  if (isRequiredDecl(D, Context, WritingModule))
 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) {
   // Switch case IDs are per function 

[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen

2017-02-27 Thread David Blaikie via Phabricator via cfe-commits
dblaikie updated this revision to Diff 89931.
dblaikie added a comment.

- Simplify ModuleFile lookup
- Build ModularCodegenDecls list from the same place the modular codegen bit is 
set on the decl
- Cleanup no-longer-needed changes to DeclMustBeEmitted/isRequiredDecl


https://reviews.llvm.org/D29901

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/ExternalASTSource.h
  include/clang/Sema/MultiplexExternalSemaSource.h
  include/clang/Serialization/ASTReader.h
  lib/AST/ASTContext.cpp
  lib/AST/ExternalASTSource.cpp
  lib/Sema/MultiplexExternalSemaSource.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTReaderDecl.cpp
  lib/Serialization/ASTWriterDecl.cpp
  test/Modules/Inputs/codegen/foo.h
  test/Modules/Inputs/codegen/use.cpp
  test/Modules/codegen.test

Index: test/Modules/codegen.test
===
--- test/Modules/codegen.test
+++ test/Modules/codegen.test
@@ -3,8 +3,23 @@
 
 RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm
 
-RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s
 
-CHECK: $_Z2f1PKcz = comdat any
-CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
-CHECK:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+FOO: $_Z2f1PKcz = comdat any
+FOO: $_ZN13implicit_dtorD1Ev = comdat any
+USE: $_Z4instIiEvv = comdat any
+FOO: $_ZN13implicit_dtorD2Ev = comdat any
+FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
+FOO:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+
+Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user.
+FIXME: Proactively instantiate any valid implicit special members to emit them into the module object.
+
+FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+FOO: define weak_odr void @_Z4instIfEvv() #0 comdat {
+FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat {
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
Index: test/Modules/Inputs/codegen/use.cpp
===
--- /dev/null
+++ test/Modules/Inputs/codegen/use.cpp
@@ -0,0 +1,8 @@
+#include "foo.h"
+void non_modular_use_of_implicit_dtor() {
+  implicit_dtor d1;
+  uninst_implicit_dtor d2;
+}
+void use_of_instantiated_declaration_without_definition() {
+  inst();
+}
Index: test/Modules/Inputs/codegen/foo.h
===
--- test/Modules/Inputs/codegen/foo.h
+++ test/Modules/Inputs/codegen/foo.h
@@ -2,3 +2,29 @@
   __builtin_va_list args;
   __builtin_va_start(args, fmt);
 }
+
+struct non_trivial_dtor {
+  ~non_trivial_dtor();
+};
+
+struct implicit_dtor {
+  non_trivial_dtor d;
+};
+
+struct uninst_implicit_dtor {
+  non_trivial_dtor d;
+};
+
+inline void use_implicit_dtor() {
+  implicit_dtor d;
+}
+
+template
+void inst() {
+}
+
+inline void inst_decl() {
+  // cause inst's declaration to be instantiated, without a definition.
+  (void)sizeof();
+  inst();
+}
Index: lib/Serialization/ASTWriterDecl.cpp
===
--- lib/Serialization/ASTWriterDecl.cpp
+++ lib/Serialization/ASTWriterDecl.cpp
@@ -2158,7 +2158,7 @@
 /// relatively painless since they would presumably only do it for top-level
 /// decls.
 static bool isRequiredDecl(const Decl *D, ASTContext ,
-   bool WritingModule, bool ModularCode) {
+   bool WritingModule) {
   // An ObjCMethodDecl is never considered as "required" because its
   // implementation container always is.
 
@@ -2174,7 +2174,7 @@
 return false;
   }
 
-  return Context.DeclMustBeEmitted(D, ModularCode);
+  return Context.DeclMustBeEmitted(D);
 }
 
 void ASTWriter::WriteDecl(ASTContext , Decl *D) {
@@ -2218,18 +2218,20 @@
 
   // 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, false))
+  if (isRequiredDecl(D, Context, WritingModule))
 EagerlyDeserializedDecls.push_back(ID);
-  else if (Context.getLangOpts().ModularCodegen && WritingModule &&
-   

[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen

2017-02-16 Thread David Blaikie via Phabricator via cfe-commits
dblaikie updated this revision to Diff 88792.
dblaikie added a comment.

- Simplify ModuleFile lookup


https://reviews.llvm.org/D29901

Files:
  include/clang/AST/ExternalASTSource.h
  include/clang/Sema/MultiplexExternalSemaSource.h
  include/clang/Serialization/ASTReader.h
  lib/AST/ASTContext.cpp
  lib/AST/ExternalASTSource.cpp
  lib/Sema/MultiplexExternalSemaSource.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTReaderDecl.cpp
  lib/Serialization/ASTWriterDecl.cpp
  test/Modules/Inputs/codegen/foo.h
  test/Modules/Inputs/codegen/use.cpp
  test/Modules/codegen.test

Index: test/Modules/codegen.test
===
--- test/Modules/codegen.test
+++ test/Modules/codegen.test
@@ -3,8 +3,23 @@
 
 RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm
 
-RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s
 
-CHECK: $_Z2f1PKcz = comdat any
-CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
-CHECK:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+FOO: $_Z2f1PKcz = comdat any
+FOO: $_ZN13implicit_dtorD1Ev = comdat any
+USE: $_Z4instIiEvv = comdat any
+FOO: $_ZN13implicit_dtorD2Ev = comdat any
+FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
+FOO:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+
+Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user.
+FIXME: Proactively instantiate any valid implicit special members to emit them into the module object.
+
+FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+FOO: define weak_odr void @_Z4instIfEvv() #0 comdat {
+FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat {
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
Index: test/Modules/Inputs/codegen/use.cpp
===
--- /dev/null
+++ test/Modules/Inputs/codegen/use.cpp
@@ -0,0 +1,8 @@
+#include "foo.h"
+void non_modular_use_of_implicit_dtor() {
+  implicit_dtor d1;
+  uninst_implicit_dtor d2;
+}
+void use_of_instantiated_declaration_without_definition() {
+  inst();
+}
Index: test/Modules/Inputs/codegen/foo.h
===
--- test/Modules/Inputs/codegen/foo.h
+++ test/Modules/Inputs/codegen/foo.h
@@ -2,3 +2,29 @@
   __builtin_va_list args;
   __builtin_va_start(args, fmt);
 }
+
+struct non_trivial_dtor {
+  ~non_trivial_dtor();
+};
+
+struct implicit_dtor {
+  non_trivial_dtor d;
+};
+
+struct uninst_implicit_dtor {
+  non_trivial_dtor d;
+};
+
+inline void use_implicit_dtor() {
+  implicit_dtor d;
+}
+
+template
+void inst() {
+}
+
+inline void inst_decl() {
+  // cause inst's declaration to be instantiated, without a definition.
+  (void)sizeof();
+  inst();
+}
Index: lib/Serialization/ASTWriterDecl.cpp
===
--- lib/Serialization/ASTWriterDecl.cpp
+++ lib/Serialization/ASTWriterDecl.cpp
@@ -2224,6 +2224,8 @@
   Writer->ClearSwitchCaseIDs();
 
   assert(FD->doesThisDeclarationHaveABody());
+  Record->push_back(Writer->Context->getLangOpts().ModularCodegen &&
+Writer->WritingModule);
   if (auto *CD = dyn_cast(FD)) {
 Record->push_back(CD->getNumCtorInitializers());
 if (CD->getNumCtorInitializers())
Index: lib/Serialization/ASTReaderDecl.cpp
===
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -423,6 +423,11 @@
 }
 
 void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) {
+  if (Record.readInt()) {
+Reader.BodySource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile
+? ExternalASTSource::EK_Never
+: ExternalASTSource::EK_Always;
+  }
   if (auto *CD = dyn_cast(FD)) {
 CD->NumCtorInitializers = Record.readInt();
 if (CD->NumCtorInitializers)
Index: lib/Serialization/ASTReader.cpp
===
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -7911,16 +7911,11 @@
   return None;
 }
 

[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen

2017-02-13 Thread David Blaikie via Phabricator via cfe-commits
dblaikie created this revision.

Some decls are created not where they are written, but in other module
files/users (implicit special members and function template implicit
specializations). To correctly identify them, use a bit next to the definition
to track the modular codegen property.

Possible improvement would be to store this bit on the Decl itself, rather than
a sidemap - happy to give that a whirl if it seems better. (actually it'd be
two bits, since 3 states are required - currently reflected by "not in the
map", "in the map with Always", "in the map with Never")

Discussed whether the module file bit could be omitted in favor of
reconstituting from the modular codegen decls list - best guess today is that
the efficiency improvement of not having to deserialize the whole list whenever
any function is queried by a module user is worth it for the small size
increase of this redundant (list + bit-on-def) representation.


https://reviews.llvm.org/D29901

Files:
  include/clang/AST/ExternalASTSource.h
  include/clang/Sema/MultiplexExternalSemaSource.h
  include/clang/Serialization/ASTReader.h
  lib/AST/ASTContext.cpp
  lib/AST/ExternalASTSource.cpp
  lib/Sema/MultiplexExternalSemaSource.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTReaderDecl.cpp
  lib/Serialization/ASTWriterDecl.cpp
  test/Modules/Inputs/codegen/foo.h
  test/Modules/Inputs/codegen/use.cpp
  test/Modules/codegen.test

Index: test/Modules/codegen.test
===
--- test/Modules/codegen.test
+++ test/Modules/codegen.test
@@ -3,8 +3,23 @@
 
 RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm
 
-RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s
 
-CHECK: $_Z2f1PKcz = comdat any
-CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
-CHECK:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+FOO: $_Z2f1PKcz = comdat any
+FOO: $_ZN13implicit_dtorD1Ev = comdat any
+USE: $_Z4instIiEvv = comdat any
+FOO: $_ZN13implicit_dtorD2Ev = comdat any
+FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
+FOO:   call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+
+Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user.
+FIXME: Proactively instantiate any valid implicit special members to emit them into the module object.
+
+FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+FOO: define weak_odr void @_Z4instIfEvv() #0 comdat {
+FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
+USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat {
+USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 {
Index: test/Modules/Inputs/codegen/use.cpp
===
--- /dev/null
+++ test/Modules/Inputs/codegen/use.cpp
@@ -0,0 +1,8 @@
+#include "foo.h"
+void non_modular_use_of_implicit_dtor() {
+  implicit_dtor d1;
+  uninst_implicit_dtor d2;
+}
+void use_of_instantiated_declaration_without_definition() {
+  inst();
+}
Index: test/Modules/Inputs/codegen/foo.h
===
--- test/Modules/Inputs/codegen/foo.h
+++ test/Modules/Inputs/codegen/foo.h
@@ -2,3 +2,29 @@
   __builtin_va_list args;
   __builtin_va_start(args, fmt);
 }
+
+struct non_trivial_dtor {
+  ~non_trivial_dtor();
+};
+
+struct implicit_dtor {
+  non_trivial_dtor d;
+};
+
+struct uninst_implicit_dtor {
+  non_trivial_dtor d;
+};
+
+inline void use_implicit_dtor() {
+  implicit_dtor d;
+}
+
+template
+void inst() {
+}
+
+inline void inst_decl() {
+  // cause inst's declaration to be instantiated, without a definition.
+  (void)sizeof();
+  inst();
+}
Index: lib/Serialization/ASTWriterDecl.cpp
===
--- lib/Serialization/ASTWriterDecl.cpp
+++ lib/Serialization/ASTWriterDecl.cpp
@@ -2224,6 +2224,8 @@
   Writer->ClearSwitchCaseIDs();
 
   assert(FD->doesThisDeclarationHaveABody());
+  Record->push_back(Writer->Context->getLangOpts().ModularCodegen &&
+Writer->WritingModule);
   if (auto *CD = dyn_cast(FD)) {
 Record->push_back(CD->getNumCtorInitializers());
 if (CD->getNumCtorInitializers())
Index: