From 8a91585a7208986181e58e4055f57534e62471bc Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 15 Jan 2015 21:36:08 +0000 Subject: [PATCH] Use a trivial comdat for inline ctor/dtor when not using C5/D5. 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 | 13 +++++++++---- lib/CodeGen/CodeGenModule.h | 1 + lib/CodeGen/ItaniumCXXABI.cpp | 2 ++ test/CodeGenCXX/ctor-dtor-alias.cpp | 13 ++++++++----- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 8981bfe89c..7a97aa64ea 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ddcb414508..4559aecff1 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -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; } diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index f2ffabcf3e..7d8ad465bf 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -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); } } diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index bd60cb88bb..6f8aedc071 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -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 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 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() {} }; -- 2.40.0