From cb92c19fc4ac08a6e8e4806ce6f217d2e4f83b5c Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 15 Jan 2015 23:18:01 +0000 Subject: [PATCH] Use a trivial comdat for C++ tables. This produces comdats for vtables, typeinfo, typeinfo names, and vtts. When combined with llvm not producing implicit comdats, not doing this would cause code bloat on ELF and link errors on COFF. llvm-svn: 226227 --- clang/lib/CodeGen/CGVTT.cpp | 3 ++ clang/lib/CodeGen/CodeGenModule.cpp | 5 ++- clang/lib/CodeGen/ItaniumCXXABI.cpp | 11 ++++-- clang/test/CodeGenCXX/vtable-linkage.cpp | 44 ++++++++++++------------ 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp index bd280ea14e8d..81bd65179b70 100644 --- a/clang/lib/CodeGen/CGVTT.cpp +++ b/clang/lib/CodeGen/CGVTT.cpp @@ -94,6 +94,9 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, // Set the correct linkage. VTT->setLinkage(Linkage); + if (CGM.supportsCOMDAT() && VTT->isWeakForLinker()) + VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName())); + // Set the right visibility. CGM.setGlobalVisibility(VTT, RD); } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 7a97aa64ea9b..72d7a6cd8e06 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1828,7 +1828,10 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name, OldGV->eraseFromParent(); } - + + if (supportsCOMDAT() && GV->isWeakForLinker()) + GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + return GV; } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 7d8ad465bf3e..29d922c68e3e 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1256,6 +1256,9 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, // Set the correct linkage. VTable->setLinkage(Linkage); + if (CGM.supportsCOMDAT() && VTable->isWeakForLinker()) + VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName())); + // Set the right visibility. CGM.setGlobalVisibility(VTable, RD); @@ -2716,9 +2719,13 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields); + llvm::Module &M = CGM.getModule(); llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Init->getType(), - /*Constant=*/true, Linkage, Init, Name); + new llvm::GlobalVariable(M, Init->getType(), + /*Constant=*/true, Linkage, Init, Name); + + if (CGM.supportsCOMDAT() && GV->isWeakForLinker()) + GV->setComdat(M.getOrInsertComdat(GV->getName())); // If there's already an old global variable, replace it with the new one. if (OldGV) { diff --git a/clang/test/CodeGenCXX/vtable-linkage.cpp b/clang/test/CodeGenCXX/vtable-linkage.cpp index 9c08b3037ca1..5cbd3897a1ff 100644 --- a/clang/test/CodeGenCXX/vtable-linkage.cpp +++ b/clang/test/CodeGenCXX/vtable-linkage.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o %t +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o %t // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-optzns -O3 -emit-llvm -o %t.opt // RUN: FileCheck --check-prefix=CHECK %s < %t // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt @@ -89,10 +89,10 @@ void use_F() { // C has no key function, so its vtable should have weak_odr linkage // and hidden visibility (rdar://problem/7523229). -// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant -// CHECK-DAG: @_ZTS1C = linkonce_odr constant -// CHECK-DAG: @_ZTI1C = linkonce_odr constant -// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant +// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant {{.*}}, comdat, +// CHECK-DAG: @_ZTS1C = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTI1C = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant {{.*}}, comdat{{$}} // D has a key function that is defined in this translation unit so its vtable is // defined in the translation unit. @@ -110,28 +110,28 @@ void use_F() { // E is an explicit template instantiation with a key function // defined in this translation unit, so its vtable should have // weak_odr linkage. -// CHECK-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant -// CHECK-DAG: @_ZTS1EIsE = weak_odr constant -// CHECK-DAG: @_ZTI1EIsE = weak_odr constant +// CHECK-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant {{.*}}, comdat, +// CHECK-DAG: @_ZTS1EIsE = weak_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTI1EIsE = weak_odr constant {{.*}}, comdat{{$}} // F is an explicit template instantiation without a key // function, so its vtable should have weak_odr linkage -// CHECK-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant -// CHECK-DAG: @_ZTS1FIsE = weak_odr constant -// CHECK-DAG: @_ZTI1FIsE = weak_odr constant +// CHECK-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant {{.*}}, comdat, +// CHECK-DAG: @_ZTS1FIsE = weak_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTI1FIsE = weak_odr constant {{.*}}, comdat{{$}} // E is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have // linkonce_odr linkage. -// CHECK-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr constant -// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant -// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant +// CHECK-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr constant {{.*}}, comdat, +// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant {{.*}}, comdat{{$}} // F is an implicit template instantiation with no key function, // so its vtable should have linkonce_odr linkage. -// CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr constant -// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant -// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant +// CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr constant {{.*}}, comdat, +// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant {{.*}}, comdat{{$}} // F is an explicit template instantiation declaration without a // key function, so its vtable should have external linkage. @@ -158,11 +158,11 @@ void use_F() { // F is an explicit specialization without a key function, so // its vtable should have linkonce_odr linkage. -// CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr constant -// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant -// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant +// CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr constant {{.*}}, comdat, +// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant {{.*}}, comdat{{$}} +// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant {{.*}}, comdat{{$}} -// CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr constant +// CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr constant {{.*}}, comdat, template class G { public: @@ -178,7 +178,7 @@ void G_f0() { new G(); } // H has a key function without a body but it's a template instantiation // so its VTable must be emitted. -// CHECK-DAG: @_ZTV1HIiE = linkonce_odr unnamed_addr constant +// CHECK-DAG: @_ZTV1HIiE = linkonce_odr unnamed_addr constant {{.*}}, comdat, template class H { public: