]> granicus.if.org Git - clang/commitdiff
Use a trivial comdat for inline ctor/dtor when not using C5/D5.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 15 Jan 2015 21:36:08 +0000 (21:36 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 15 Jan 2015 21:36:08 +0000 (21:36 +0000)
When combined with llvm not producing implicit comdats, not doing this would
cause code bloat on ELF and link errors on COFF.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@226211 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/ItaniumCXXABI.cpp
test/CodeGenCXX/ctor-dtor-alias.cpp

index 8981bfe89cb4a1a5dcc6a703e31f545335b23345..7a97aa64ea9bad5509b3ed8f77e395425a70b2cb 100644 (file)
@@ -1953,6 +1953,13 @@ static bool shouldBeInCOMDAT(CodeGenModule &CGM, const Decl &D) {
   llvm_unreachable("No such linkage");
 }
 
+void CodeGenModule::maybeSetTrivialComdat(const Decl &D,
+                                          llvm::GlobalObject &GO) {
+  if (!shouldBeInCOMDAT(*this, D))
+    return;
+  GO.setComdat(TheModule.getOrInsertComdat(GO.getName()));
+}
+
 void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
   llvm::Constant *Init = nullptr;
   QualType ASTTy = D->getType();
@@ -2096,8 +2103,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
     setTLSMode(GV, *D);
   }
 
-  if (shouldBeInCOMDAT(*this, *D))
-    GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
+  maybeSetTrivialComdat(*D, *GV);
 
   // Emit the initializer function if necessary.
   if (NeedsGlobalCtor || NeedsGlobalDtor)
@@ -2433,8 +2439,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
 
   MaybeHandleStaticInExternC(D, Fn);
 
-  if (shouldBeInCOMDAT(*this, *D))
-    Fn->setComdat(TheModule.getOrInsertComdat(Fn->getName()));
+  maybeSetTrivialComdat(*D, *Fn);
 
   CodeGenFunction(*this).GenerateCode(D, Fn, FI);
 
index ddcb414508aa09ec03c788ef50e0a7609e22bf60..4559aecff1233a4b0190196b7a0f235c21a772ad 100644 (file)
@@ -606,6 +606,7 @@ public:
   const TargetInfo &getTarget() const { return Target; }
   const llvm::Triple &getTriple() const;
   bool supportsCOMDAT() const;
+  void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO);
 
   CGCXXABI &getCXXABI() const { return *ABI; }
   llvm::LLVMContext &getLLVMContext() { return VMContext; }
index f2ffabcf3e9dfb7a5031fd23aa091fcab16ed227..7d8ad465bf3ef76e3296e9f100951abed33ecc0f 100644 (file)
@@ -3202,5 +3202,7 @@ void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
       getMangleContext().mangleCXXCtorComdat(CD, Out);
     llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());
     Fn->setComdat(C);
+  } else {
+    CGM.maybeSetTrivialComdat(*MD, *Fn);
   }
 }
index bd60cb88bb259bb9be345c7bb1e1dd96ead78f14..6f8aedc0712cec2a6b5d486601b1d0a242e70c87 100644 (file)
@@ -22,7 +22,10 @@ namespace test1 {
 // CHECK1-NOT: comdat
 
 // COFF doesn't support comdats with arbitrary names (C5/D5).
-// COFF-NOT: comdat
+// COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC2Ev({{.*}} comdat align
+// COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC1Ev({{.*}} comdat align
+// COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvED2Ev({{.*}} comdat align
+// COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvED0Ev({{.*}} comdat align
 
 template <typename T>
 struct foobar {
@@ -39,7 +42,7 @@ namespace test2 {
 
 // CHECK1: define internal void @__cxx_global_var_init()
 // CHECK1: call void @_ZN5test26foobarIvEC2Ev
-// CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev(
+// CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev({{.*}} comdat align
 void g();
 template <typename T> struct foobar {
   foobar() { g(); }
@@ -72,13 +75,13 @@ namespace test4 {
 
   // CHECK1: define internal void @__cxx_global_var_init2()
   // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev
-  // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev(
+  // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev({{.*}} comdat align
 
   // test that we don't do this optimization at -O0 so that the debugger can
   // see both destructors.
   // NOOPT: define internal void @__cxx_global_var_init2()
   // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev
-  // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev
+  // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev({{.*}} comdat align
   struct A {
     virtual ~A() {}
   };
@@ -93,7 +96,7 @@ namespace test5 {
 
   // CHECK2: define internal void @__cxx_global_var_init3()
   // CHECK2: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev
-  // CHECK2: define linkonce_odr void @_ZN5test51AD2Ev(
+  // CHECK2: define linkonce_odr void @_ZN5test51AD2Ev({{.*}} comdat align
   struct A {
     virtual ~A() {}
   };