From c7bb1deeced2b512ff64b392e3e78c7604efa6c9 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 12 Jan 2015 22:13:53 +0000 Subject: [PATCH] [patch][pr19848] Produce explicit comdats in clang. The llvm IR until recently had no support for comdats. This was a problem when targeting C++ on ELF/COFF as just using weak linkage would cause quite a bit of dead bits to remain on the executable (unless -ffunction-sections, -fdata-sections and --gc-sections were used). To fix the problem, llvm's codegen will just assume that any weak or linkonce that is not in an explicit comdat should be output in one with the same name as the global. This unfortunately breaks cases like pr19848 where a weak symbol is not xpected to be part of any comdat. Now that we have explicit comdats in the IR, we can finally get both cases right. This first patch just makes clang give explicit comdats to GlobalValues where t is allowed to. A followup patch to llvm will then stop implicitly producing comdats. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225705 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 3 ++ lib/CodeGen/CGDeclCXX.cpp | 10 +--- lib/CodeGen/CodeGenModule.cpp | 31 ++++++++++++ lib/CodeGen/ItaniumCXXABI.cpp | 7 +-- lib/CodeGen/MicrosoftCXXABI.cpp | 12 +---- test/CodeGen/ms-declspecs.c | 4 +- test/CodeGenCXX/cxx11-exception-spec.cpp | 16 +++---- test/CodeGenCXX/dllexport-members.cpp | 32 ++++++------- test/CodeGenCXX/dllexport.cpp | 48 +++++++++---------- test/CodeGenCXX/dllimport.cpp | 2 +- ...s-integer-static-data-members-exported.cpp | 4 +- .../ms-integer-static-data-members.cpp | 2 +- test/CodeGenCXX/split-stacks.cpp | 4 +- test/CodeGenCXX/static-init.cpp | 9 ++-- 14 files changed, 100 insertions(+), 84 deletions(-) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 4a612c9bed..39052e54dd 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -206,6 +206,9 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl( GV->setAlignment(getContext().getDeclAlign(&D).getQuantity()); setGlobalVisibility(GV, &D); + if (supportsCOMDAT() && GV->isWeakForLinker()) + GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + if (D.getTLSKind()) setTLSMode(GV, D); diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 0e3117400f..12cdb95097 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -267,15 +267,7 @@ void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D, addUsedGlobal(PtrArray); // If the GV is already in a comdat group, then we have to join it. - llvm::Comdat *C = GV->getComdat(); - - // LinkOnce and Weak linkage are lowered down to a single-member comdat group. - // Make an explicit group so we can join it. - if (!C && (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())) { - C = TheModule.getOrInsertComdat(GV->getName()); - GV->setComdat(C); - } - if (C) + if (llvm::Comdat *C = GV->getComdat()) PtrArray->setComdat(C); } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index a863591aa0..15d383418f 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1928,6 +1928,31 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, R.first->second = nullptr; } +static bool shouldBeInCOMDAT(CodeGenModule &CGM, const Decl &D) { + if (!CGM.supportsCOMDAT()) + return false; + + if (D.hasAttr()) + return true; + + GVALinkage Linkage; + if (auto *VD = dyn_cast(&D)) + Linkage = CGM.getContext().GetGVALinkageForVariable(VD); + else + Linkage = CGM.getContext().GetGVALinkageForFunction(cast(&D)); + + switch (Linkage) { + case GVA_Internal: + case GVA_AvailableExternally: + case GVA_StrongExternal: + return false; + case GVA_DiscardableODR: + case GVA_StrongODR: + return true; + } + llvm_unreachable("No such linkage"); +} + void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { llvm::Constant *Init = nullptr; QualType ASTTy = D->getType(); @@ -2071,6 +2096,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { setTLSMode(GV, *D); } + if (shouldBeInCOMDAT(*this, *D)) + GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + // Emit the initializer function if necessary. if (NeedsGlobalCtor || NeedsGlobalDtor) EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor); @@ -2405,6 +2433,9 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, MaybeHandleStaticInExternC(D, Fn); + if (shouldBeInCOMDAT(*this, *D)) + Fn->setComdat(TheModule.getOrInsertComdat(Fn->getName())); + CodeGenFunction(*this).GenerateCode(D, Fn, FI); setFunctionDefinitionAttributes(D, Fn); diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index deebab8583..f2ffabcf3e 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -1711,11 +1711,12 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // The ABI says: It is suggested that it be emitted in the same COMDAT group // as the associated data object - if (!D.isLocalVarDecl() && var->isWeakForLinker() && CGM.supportsCOMDAT()) { - llvm::Comdat *C = CGM.getModule().getOrInsertComdat(var->getName()); + llvm::Comdat *C = var->getComdat(); + if (!D.isLocalVarDecl() && C) { guard->setComdat(C); - var->setComdat(C); CGF.CurFn->setComdat(C); + } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) { + guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName())); } CGM.setStaticLocalDeclGuardAddress(&D, guard); diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 06c913e1ce..c80db7d18a 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1829,18 +1829,10 @@ void MicrosoftCXXABI::EmitThreadLocalInitFuncs( llvm::Function *F = CXXThreadLocalInits[I]; // If the GV is already in a comdat group, then we have to join it. - llvm::Comdat *C = GV->getComdat(); - - // LinkOnce and Weak linkage are lowered down to a single-member comdat - // group. - // Make an explicit group so we can join it. - if (!C && (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())) { - C = CGM.getModule().getOrInsertComdat(GV->getName()); - GV->setComdat(C); + if (llvm::Comdat *C = GV->getComdat()) AddToXDU(F)->setComdat(C); - } else { + else NonComdatInits.push_back(F); - } } if (!NonComdatInits.empty()) { diff --git a/test/CodeGen/ms-declspecs.c b/test/CodeGen/ms-declspecs.c index 5dc7787b8f..328fc835d3 100644 --- a/test/CodeGen/ms-declspecs.c +++ b/test/CodeGen/ms-declspecs.c @@ -2,8 +2,8 @@ __declspec(selectany) int x1 = 1; const __declspec(selectany) int x2 = 2; -// CHECK: @x1 = weak_odr global i32 1, align 4 -// CHECK: @x2 = weak_odr constant i32 2, align 4 +// CHECK: @x1 = weak_odr global i32 1, comdat, align 4 +// CHECK: @x2 = weak_odr constant i32 2, comdat, align 4 struct __declspec(align(16)) S { char x; diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp index 75f939f93f..3fb5c15c2a 100644 --- a/test/CodeGenCXX/cxx11-exception-spec.cpp +++ b/test/CodeGenCXX/cxx11-exception-spec.cpp @@ -22,9 +22,9 @@ template<> void S::f() { h(); } // CHECK: define {{.*}} @_ZN1SIA2_sE1fEv() [[NUW]] template<> void S::f() noexcept { h(); } -// CHECK: define {{.*}} @_Z1fIDsEvv() [[NONE]] { +// CHECK: define {{.*}} @_Z1fIDsEvv() [[NONE]] comdat { template void f(); -// CHECK: define {{.*}} @_Z1fIA2_DsEvv() [[NUW]] { +// CHECK: define {{.*}} @_Z1fIA2_DsEvv() [[NUW]] comdat { template void f(); // CHECK: define {{.*}} @_ZN1SIDsE1fEv() @@ -34,9 +34,9 @@ template void S::f(); template void S::f(); void h() { - // CHECK: define {{.*}} @_Z1fIiEvv() [[NUW]] { + // CHECK: define {{.*}} @_Z1fIiEvv() [[NUW]] comdat { f(); - // CHECK: define {{.*}} @_Z1fIA2_iEvv() [[NONE]] { + // CHECK: define {{.*}} @_Z1fIA2_iEvv() [[NONE]] comdat { f(); // CHECK: define {{.*}} @_ZN1SIiE1fEv() [[NUW]] @@ -45,9 +45,9 @@ void h() { // CHECK-NOT: [[NUW]] S::f(); - // CHECK: define {{.*}} @_Z1fIfEvv() [[NUW]] { + // CHECK: define {{.*}} @_Z1fIfEvv() [[NUW]] comdat { void (*f1)() = &f; - // CHECK: define {{.*}} @_Z1fIdEvv() [[NONE]] { + // CHECK: define {{.*}} @_Z1fIdEvv() [[NONE]] comdat { void (*f2)() = &f; // CHECK: define {{.*}} @_ZN1SIfE1fEv() [[NUW]] @@ -56,9 +56,9 @@ void h() { // CHECK-NOT: [[NUW]] void (*f4)() = &S::f; - // CHECK: define {{.*}} @_Z1fIA4_cEvv() [[NUW]] { + // CHECK: define {{.*}} @_Z1fIA4_cEvv() [[NUW]] comdat { (void)&f; - // CHECK: define {{.*}} @_Z1fIcEvv() [[NONE]] { + // CHECK: define {{.*}} @_Z1fIcEvv() [[NONE]] comdat { (void)&f; // CHECK: define {{.*}} @_ZN1SIA4_cE1fEv() [[NUW]] diff --git a/test/CodeGenCXX/dllexport-members.cpp b/test/CodeGenCXX/dllexport-members.cpp index d913c09ec7..5b2af1e04b 100644 --- a/test/CodeGenCXX/dllexport-members.cpp +++ b/test/CodeGenCXX/dllexport-members.cpp @@ -110,9 +110,9 @@ public: // MSC-DAG: @"\01?StaticField@ExportMembers@@2HA" = dllexport global i32 1, align 4 // MSC-DAG: @"\01?StaticConstField@ExportMembers@@2HB" = dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN13ExportMembers11StaticFieldE = dllexport global i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE = dllexport constant i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4 @@ -233,9 +233,9 @@ public: // MSC-DAG: @"\01?StaticField@Nested@ExportMembers@@2HA" = dllexport global i32 1, align 4 // MSC-DAG: @"\01?StaticConstField@Nested@ExportMembers@@2HB" = dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE = dllexport global i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE = dllexport constant i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4 @@ -599,21 +599,21 @@ template const int MemVarTmpl::StaticVar; template const int MemVarTmpl::ExportedStaticVar; // Export implicit instantiation of an exported member variable template. -// MSC-DAG: @"\01??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar; } // Export explicit instantiation declaration of an exported member variable // template. -// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 extern template const int MemVarTmpl::ExportedStaticVar; template const int MemVarTmpl::ExportedStaticVar; // Export explicit instantiation definition of an exported member variable // template. -// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 template const int MemVarTmpl::ExportedStaticVar; // Export specialization of an exported member variable template. @@ -630,15 +630,15 @@ template<> const int MemVarTmpl::ExportedStaticVar = 1 // Export explicit instantiation declaration of a non-exported member variable // template. -// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 extern template __declspec(dllexport) const int MemVarTmpl::StaticVar; template __declspec(dllexport) const int MemVarTmpl::StaticVar; // Export explicit instantiation definition of a non-exported member variable // template. -// MSC-DAG: @"\01??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4 -// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 +// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, comdat, align 4 template __declspec(dllexport) const int MemVarTmpl::StaticVar; // Export specialization of a non-exported member variable template. diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index cfbc7e1007..93bd1f5fe9 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -110,43 +110,43 @@ template __declspec(dllexport) int VarTmplImplicitDef; USEVAR(VarTmplImplicitDef) // Export definition. -// MSC-DAG: @"\01??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template __declspec(dllexport) int VarTmplInit1 = 1; INSTVAR(VarTmplInit1) -// MSC-DAG: @"\01??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template int __declspec(dllexport) VarTmplInit2 = 1; INSTVAR(VarTmplInit2) // Declare, then export definition. -// MSC-DAG: @"\01??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template __declspec(dllexport) extern int VarTmplDeclInit; template int VarTmplDeclInit = 1; INSTVAR(VarTmplDeclInit) // Redeclarations -// MSC-DAG: @"\01??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template __declspec(dllexport) extern int VarTmplRedecl1; template __declspec(dllexport) int VarTmplRedecl1 = 1; INSTVAR(VarTmplRedecl1) -// MSC-DAG: @"\01??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template __declspec(dllexport) extern int VarTmplRedecl2; template int VarTmplRedecl2 = 1; INSTVAR(VarTmplRedecl2) -// MSC-DAG: @"\01??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dllexport global i32 1, comdat, align 4 namespace ns { template __declspec(dllexport) int ExternalVarTmpl = 1; } INSTVAR(ns::ExternalVarTmpl) -// MSC-DAG: @"\01??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dllexport global %struct.External zeroinitializer, align 4 -// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global %struct.External zeroinitializer, align 4 +// MSC-DAG: @"\01??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dllexport global %struct.External zeroinitializer, comdat, align 4 +// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global %struct.External zeroinitializer, comdat, align 4 template __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External(); template External ExternalAutoTypeVarTmpl; @@ -155,19 +155,19 @@ template int VarTmpl = 1; template __declspec(dllexport) int ExportedVarTmpl = 1; // Export implicit instantiation of an exported variable template. -// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 USEVAR(ExportedVarTmpl) // Export explicit instantiation declaration of an exported variable template. -// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 extern template int ExportedVarTmpl; template int ExportedVarTmpl; // Export explicit instantiation definition of an exported variable template. -// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template __declspec(dllexport) int ExportedVarTmpl; // Export specialization of an exported variable template. @@ -187,14 +187,14 @@ template<> int ExportedVarTmpl; // Export explicit instantiation declaration of a non-exported variable template. -// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 extern template __declspec(dllexport) int VarTmpl; template __declspec(dllexport) int VarTmpl; // Export explicit instantiation definition of a non-exported variable template. -// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4 -// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4 +// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, comdat, align 4 +// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, comdat, align 4 template __declspec(dllexport) int VarTmpl; // Export specialization of a non-exported variable template. diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index ddd390ad6f..e5b9f64dcc 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -243,7 +243,7 @@ __declspec(dllimport) __attribute__((noinline)) inline void noinline() {} USE(noinline) // MSC2-NOT: @"\01?alwaysInline@@YAXXZ"() -// GNU2-NOT: @_Z12alwaysInlinev() +// GNU-DAG: define linkonce_odr void @_Z12alwaysInlinev() {{.*}} comdat { __declspec(dllimport) __attribute__((always_inline)) inline void alwaysInline() {} USE(alwaysInline) diff --git a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp index 3f868f36ff..78bb3a2b1a 100644 --- a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp +++ b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp @@ -17,6 +17,6 @@ struct __declspec(dllexport) S { }; }; -// CHECK: @"\01?x@S@@2FB" = weak_odr dllexport constant i16 42, align 2 -// CHECK: @"\01?y@S@@2W4Enum@@B" = weak_odr dllexport constant i32 2, align 4 +// CHECK: @"\01?x@S@@2FB" = weak_odr dllexport constant i16 42, comdat, align 2 +// CHECK: @"\01?y@S@@2W4Enum@@B" = weak_odr dllexport constant i32 2, comdat, align 4 // CHECK-NOT: NonExported diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp index b02b679d71..4965f73191 100644 --- a/test/CodeGenCXX/ms-integer-static-data-members.cpp +++ b/test/CodeGenCXX/ms-integer-static-data-members.cpp @@ -26,7 +26,7 @@ const int S::x = 5; // Inline initialization. -// CHECK-INLINE: @"\01?x@S@@2HB" = linkonce_odr constant i32 5, align 4 +// CHECK-INLINE: @"\01?x@S@@2HB" = linkonce_odr constant i32 5, comdat, align 4 // Out-of-line initialization. // CHECK-OUTOFLINE: @"\01?x@S@@2HB" = constant i32 5, align 4 diff --git a/test/CodeGenCXX/split-stacks.cpp b/test/CodeGenCXX/split-stacks.cpp index 3e120344d6..76e1b79b8f 100644 --- a/test/CodeGenCXX/split-stacks.cpp +++ b/test/CodeGenCXX/split-stacks.cpp @@ -18,7 +18,7 @@ int nosplit() { // CHECK-SEGSTK: define i32 @_Z3foov() [[SS:#[0-9]+]] { // CHECK-SEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] { -// CHECK-SEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] { +// CHECK-SEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat { // CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} } @@ -27,7 +27,7 @@ int nosplit() { // CHECK-NOSEGSTK: define i32 @_Z3foov() [[NSS0:#[0-9]+]] { // CHECK-NOSEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] { -// CHECK-NOSEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] { +// CHECK-NOSEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat { // CHECK-NOSEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } // CHECK-NOSEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } // CHECK-NOSEGSTK-NOT: [[NSS3]] = { {{.*}} "split-stack" {{.*}} } diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index a9debe3de7..66ff5b3fba 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -7,10 +7,8 @@ // CHECK: @_ZZN5test31BC1EvE1u = internal global { i8, [3 x i8] } { i8 97, [3 x i8] undef }, align 4 // CHECK: @_ZZN5test1L6getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16 -// CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0 -// CHECK-NOT: comdat -// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0 -// CHECK-NOT: comdat +// CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0, comdat, align +// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat{{$}} struct A { A(); @@ -37,8 +35,7 @@ void h() { static const int i = a(); } -// CHECK: define linkonce_odr void @_Z2h2v() -// CHECK-NOT: comdat +// CHECK: define linkonce_odr void @_Z2h2v() {{.*}} comdat { inline void h2() { static int i = a(); } -- 2.40.0