From: Rafael Espindola Date: Wed, 7 Feb 2018 22:15:33 +0000 (+0000) Subject: Recommit r324107 again. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=19347d7065a90fecbe8efd7f9f48b91f0f1319e6;p=clang Recommit r324107 again. The difference from the previous try is that we no longer directly access function declarations from position independent executables. It should work, but currently doesn't with some linkers. It now includes a fix to not mark available_externally definitions as dso_local. Original message: Start setting dso_local in clang. This starts adding dso_local to clang. The hope is to eventually have TargetMachine::shouldAssumeDsoLocal go away. My objective for now is to move enough of it to clang to remove the need for the TargetMachine one to handle PIE copy relocations and -fno-plt. With that it should then be easy to implement a -fno-copy-reloc in clang. This patch just adds the cases where we assume a symbol to be local based on the file being compiled for an executable or a shared library. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324535 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index e3e4098e7c..7c05a0dee3 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -240,7 +240,7 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl( getModule(), LTy, Ty.isConstant(getContext()), Linkage, Init, Name, nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); GV->setAlignment(getContext().getDeclAlign(&D).getQuantity()); - setGlobalVisibility(GV, &D); + setGVProperties(GV, &D); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); @@ -344,6 +344,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D, OldGV->getThreadLocalMode(), CGM.getContext().getTargetAddressSpace(D.getType())); GV->setVisibility(OldGV->getVisibility()); + GV->setDSOLocal(OldGV->isDSOLocal()); GV->setComdat(OldGV->getComdat()); // Steal the name of the old global diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp index 92fd93b5ca..41c8c943f5 100644 --- a/lib/CodeGen/CGVTT.cpp +++ b/lib/CodeGen/CGVTT.cpp @@ -100,7 +100,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName())); // Set the right visibility. - CGM.setGlobalVisibility(VTT, RD); + CGM.setGVProperties(VTT, RD); } llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 67388ee208..7a5c6cfe65 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -51,7 +51,7 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD, const ThunkInfo &Thunk, llvm::Function *Fn) { - CGM.setGlobalVisibility(Fn, MD); + CGM.setGVProperties(Fn, MD); } static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk, @@ -730,7 +730,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, // Create the variable that will hold the construction vtable. llvm::GlobalVariable *VTable = CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage); - CGM.setGlobalVisibility(VTable, RD); + CGM.setGVProperties(VTable, RD); // V-tables are always unnamed_addr. VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index b3974b6de4..7fa4fddc79 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -715,6 +715,63 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, GV->setVisibility(GetLLVMVisibility(LV.getVisibility())); } +static bool shouldAssumeDSOLocal(const CodeGenModule &CGM, + llvm::GlobalValue *GV, const NamedDecl *D) { + const llvm::Triple &TT = CGM.getTriple(); + // Only handle ELF for now. + if (!TT.isOSBinFormatELF()) + return false; + + // If this is not an executable, don't assume anything is local. + const auto &CGOpts = CGM.getCodeGenOpts(); + llvm::Reloc::Model RM = CGOpts.RelocationModel; + const auto &LOpts = CGM.getLangOpts(); + if (RM != llvm::Reloc::Static && !LOpts.PIE) + return false; + + // A definition cannot be preempted from an executable. + if (!GV->isDeclarationForLinker()) + return true; + + // Most PIC code sequences that assume that a symbol is local cannot produce a + // 0 if it turns out the symbol is undefined. While this is ABI and relocation + // depended, it seems worth it to handle it here. + if (RM == llvm::Reloc::PIC_ && GV->hasExternalWeakLinkage()) + return false; + + // PPC has no copy relocations and cannot use a plt entry as a symbol address. + llvm::Triple::ArchType Arch = TT.getArch(); + if (Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 || + Arch == llvm::Triple::ppc64le) + return false; + + // If we can use copy relocations we can assume it is local. + if (isa(D) && + (RM == llvm::Reloc::Static || CGOpts.PIECopyRelocations)) + return true; + + // If we can use a plt entry as the symbol address we can assume it + // is local. + // FIXME: This should work for PIE, but the gold linker doesn't support it. + if (isa(D) && !CGOpts.NoPLT && RM == llvm::Reloc::Static) + return true; + + // Otherwise don't assue it is local. + return false; +} + +void CodeGenModule::setDSOLocal(llvm::GlobalValue *GV, + const NamedDecl *D) const { + if (shouldAssumeDSOLocal(*this, GV, D)) + GV->setDSOLocal(true); +} + +void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, + const NamedDecl *D) const { + setGlobalVisibility(GV, D); + setDSOLocal(GV, D); +} + static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) { return llvm::StringSwitch(S) .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel) @@ -1172,7 +1229,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, void CodeGenModule::SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV) { if (const auto *ND = dyn_cast_or_null(D)) - setGlobalVisibility(GV, ND); + setGVProperties(GV, ND); else GV->setVisibility(llvm::GlobalValue::DefaultVisibility); @@ -1312,7 +1369,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, // overridden by a definition. setLinkageForGV(F, FD); - setGlobalVisibility(F, FD); + setGVProperties(F, FD); if (FD->getAttr()) { F->addFnAttr("implicit-section-name"); @@ -2639,7 +2696,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); setLinkageForGV(GV, D); - setGlobalVisibility(GV, D); + setGVProperties(GV, D); if (D->getTLSKind()) { if (D->getTLSKind() == VarDecl::TLS_Dynamic) @@ -3458,7 +3515,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, setFunctionDLLStorageClass(GD, Fn); // FIXME: this is redundant with part of setFunctionDefinitionAttributes - setGlobalVisibility(Fn, D); + setGVProperties(Fn, D); MaybeHandleStaticInExternC(D, Fn); @@ -4054,7 +4111,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(), /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); if (emitter) emitter->finalize(GV); - setGlobalVisibility(GV, VD); + setGVProperties(GV, VD); GV->setAlignment(Align.getQuantity()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 33ec27ff17..30ce47b5d7 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -721,6 +721,10 @@ public: /// Set the visibility for the given LLVM GlobalValue. void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const; + void setDSOLocal(llvm::GlobalValue *GV, const NamedDecl *D) const; + + void setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D) const; + /// Set the TLS mode for the given LLVM GlobalValue for the thread-local /// variable declaration D. void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const; diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 3661c0bdb0..bbb323e4f2 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -1531,7 +1531,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName())); // Set the right visibility. - CGM.setGlobalVisibility(VTable, RD); + CGM.setGVProperties(VTable, RD); // Use pointer alignment for the vtable. Otherwise we would align them based // on the size of the initializer which doesn't make sense as only single @@ -1641,7 +1641,7 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, VTable = CGM.CreateOrReplaceCXXRuntimeVariable( Name, VTableType, llvm::GlobalValue::ExternalLinkage); VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.setGlobalVisibility(VTable, RD); + CGM.setGVProperties(VTable, RD); if (RD->hasAttr()) VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); @@ -2052,6 +2052,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, false, var->getLinkage(), llvm::ConstantInt::get(guardTy, 0), guardName.str()); + guard->setDSOLocal(var->isDSOLocal()); guard->setVisibility(var->getVisibility()); // If the variable is thread-local, so is its guard variable. guard->setThreadLocalMode(var->getThreadLocalMode()); @@ -3212,7 +3213,10 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force, llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility()); TypeName->setVisibility(llvmVisibility); + CGM.setDSOLocal(TypeName, Ty->getAsCXXRecordDecl()); + GV->setVisibility(llvmVisibility); + CGM.setDSOLocal(GV, Ty->getAsCXXRecordDecl()); if (CGM.getTriple().isWindowsItaniumEnvironment()) { auto RD = Ty->getAsCXXRecordDecl(); diff --git a/test/CodeGen/dso-local-executable.c b/test/CodeGen/dso-local-executable.c new file mode 100644 index 0000000000..5637ae4127 --- /dev/null +++ b/test/CodeGen/dso-local-executable.c @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck --check-prefix=STATIC %s +// STATIC-DAG: @bar = external dso_local global i32 +// STATIC-DAG: @weak_bar = extern_weak dso_local global i32 +// STATIC-DAG: declare dso_local void @foo() +// STATIC-DAG: @baz = dso_local global i32 42 +// STATIC-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck --check-prefix=PIE-COPY %s +// PIE-COPY-DAG: @bar = external dso_local global i32 +// PIE-COPY-DAG: @weak_bar = extern_weak global i32 +// PIE-COPY-DAG: declare void @foo() +// PIE-COPY-DAG: @baz = dso_local global i32 42 +// PIE-COPY-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie %s -o - | FileCheck --check-prefix=PIE %s +// PIE-DAG: @bar = external global i32 +// PIE-DAG: @weak_bar = extern_weak global i32 +// PIE-DAG: declare void @foo() +// PIE-DAG: @baz = dso_local global i32 42 +// PIE-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -mrelocation-model static -fno-plt %s -o - | FileCheck --check-prefix=NOPLT %s +// NOPLT-DAG: @bar = external dso_local global i32 +// NOPLT-DAG: @weak_bar = extern_weak dso_local global i32 +// NOPLT-DAG: declare void @foo() +// NOPLT-DAG: @baz = dso_local global i32 42 +// NOPLT-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -fno-plt -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck --check-prefix=PIE-COPY-NOPLT %s +// PIE-COPY-NOPLT-DAG: @bar = external dso_local global i32 +// PIE-COPY-NOPLT-DAG: @weak_bar = extern_weak global i32 +// PIE-COPY-NOPLT-DAG: declare void @foo() +// PIE-COPY-NOPLT-DAG: @baz = dso_local global i32 42 +// PIE-COPY-NOPLT-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -pic-is-pie -fno-plt %s -o - | FileCheck --check-prefix=PIE-NO-PLT %s +// RUN: %clang_cc1 -triple powerpc64le-pc-linux -emit-llvm -mrelocation-model static %s -o - | FileCheck --check-prefix=PIE-NO-PLT %s +// PIE-NO-PLT-DAG: @bar = external global i32 +// PIE-NO-PLT-DAG: @weak_bar = extern_weak global i32 +// PIE-NO-PLT-DAG: declare void @foo() +// PIE-NO-PLT-DAG: @baz = dso_local global i32 42 +// PIE-NO-PLT-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck --check-prefix=SHARED %s +// SHARED-DAG: @bar = external global i32 +// SHARED-DAG: @weak_bar = extern_weak global i32 +// SHARED-DAG: declare void @foo() +// SHARED-DAG: @baz = global i32 42 +// SHARED-DAG: define i32* @zed() + +extern int bar; +__attribute__((weak)) extern int weak_bar; +void foo(void); + +int baz = 42; +int *zed() { + foo(); + return baz ? &weak_bar : &bar; +} diff --git a/test/CodeGen/mbackchain-2.c b/test/CodeGen/mbackchain-2.c index e76afaf768..bea46d2482 100644 --- a/test/CodeGen/mbackchain-2.c +++ b/test/CodeGen/mbackchain-2.c @@ -1,6 +1,6 @@ // RUN: %clang -mbackchain --target=s390x-linux -S -emit-llvm -o - %s | FileCheck %s -// CHECK: define void @foo() [[NUW:#[0-9]+]] +// CHECK: define dso_local void @foo() [[NUW:#[0-9]+]] void foo(void) { } diff --git a/test/CodeGen/mbackchain-3.c b/test/CodeGen/mbackchain-3.c index b115861f5e..5ff0e16761 100644 --- a/test/CodeGen/mbackchain-3.c +++ b/test/CodeGen/mbackchain-3.c @@ -1,6 +1,6 @@ // RUN: %clang -mno-backchain --target=s390x-linux -S -emit-llvm -o - %s | FileCheck %s -// CHECK: define void @foo() [[NUW:#[0-9]+]] +// CHECK: define dso_local void @foo() [[NUW:#[0-9]+]] void foo(void) { } diff --git a/test/CodeGen/mips-vector-return.c b/test/CodeGen/mips-vector-return.c index 8af4998cdf..dd3c400c01 100644 --- a/test/CodeGen/mips-vector-return.c +++ b/test/CodeGen/mips-vector-return.c @@ -8,13 +8,13 @@ typedef float v4sf __attribute__ ((__vector_size__ (16))); typedef double v4df __attribute__ ((__vector_size__ (32))); typedef int v4i32 __attribute__ ((__vector_size__ (16))); -// O32-LABEL: define void @test_v4sf(<4 x float>* noalias nocapture sret +// O32-LABEL: define dso_local void @test_v4sf(<4 x float>* noalias nocapture sret // N64: define inreg { i64, i64 } @test_v4sf v4sf test_v4sf(float a) { return (v4sf){0.0f, a, 0.0f, 0.0f}; } -// O32-LABEL: define void @test_v4df(<4 x double>* noalias nocapture sret +// O32-LABEL: define dso_local void @test_v4df(<4 x double>* noalias nocapture sret // N64-LABEL: define void @test_v4df(<4 x double>* noalias nocapture sret v4df test_v4df(double a) { return (v4df){0.0, a, 0.0, 0.0}; @@ -23,7 +23,7 @@ v4df test_v4df(double a) { // O32 returns integer vectors whose size is equal to or smaller than 16-bytes // in integer registers. // -// O32: define inreg { i32, i32, i32, i32 } @test_v4i32 +// O32: define dso_local inreg { i32, i32, i32, i32 } @test_v4i32 // N64: define inreg { i64, i64 } @test_v4i32 v4i32 test_v4i32(int a) { return (v4i32){0, a, 0, 0}; diff --git a/test/CodeGen/split-stacks.c b/test/CodeGen/split-stacks.c index bf4cf0f026..d9ff1f955d 100644 --- a/test/CodeGen/split-stacks.c +++ b/test/CodeGen/split-stacks.c @@ -14,13 +14,13 @@ int main() { return foo(); } -// CHECK-SEGSTK: define i32 @foo() [[SS:#[0-9]+]] { -// CHECK-SEGSTK: define i32 @nosplit() [[NSS:#[0-9]+]] { -// CHECK-SEGSTK: define i32 @main() [[SS]] { +// CHECK-SEGSTK: define dso_local i32 @foo() [[SS:#[0-9]+]] { +// CHECK-SEGSTK: define dso_local i32 @nosplit() [[NSS:#[0-9]+]] { +// CHECK-SEGSTK: define dso_local i32 @main() [[SS]] { // CHECK-SEGSTK-NOT: [[NSS]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK-NOT: [[NSS]] = { {{.*}} "split-stack" {{.*}} } -// CHECK-NOSEGSTK: define i32 @foo() #0 { -// CHECK-NOSEGSTK: define i32 @main() #0 { +// CHECK-NOSEGSTK: define dso_local i32 @foo() #0 { +// CHECK-NOSEGSTK: define dso_local i32 @main() #0 { // CHECK-NOSEGSTK-NOT: #0 = { {{.*}} "split-stack" {{.*}} } diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp index 3537754ced..702d1f87e7 100644 --- a/test/CodeGenCXX/debug-info-static-member.cpp +++ b/test/CodeGenCXX/debug-info-static-member.cpp @@ -3,9 +3,9 @@ // RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck %s // PR14471 -// CHECK: @_ZN1C1aE = global i32 4, align 4, !dbg [[A:![0-9]+]] -// CHECK: @_ZN1C1bE = global i32 2, align 4, !dbg [[B:![0-9]+]] -// CHECK: @_ZN1C1cE = global i32 1, align 4, !dbg [[C:![0-9]+]] +// CHECK: @_ZN1C1aE = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]] +// CHECK: @_ZN1C1bE = dso_local global i32 2, align 4, !dbg [[B:![0-9]+]] +// CHECK: @_ZN1C1cE = dso_local global i32 1, align 4, !dbg [[C:![0-9]+]] enum X { Y diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index 0c34145162..4b330a0b0a 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -1,8 +1,8 @@ // RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s -// CHECK: @tci = global %"struct.TC::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]] -// CHECK: @tcn = global %struct.TC zeroinitializer, align 1, !dbg [[TCN:![0-9]+]] -// CHECK: @nn = global %struct.NN zeroinitializer, align 1, !dbg [[NN:![0-9]+]] +// CHECK: @tci = dso_local global %"struct.TC::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]] +// CHECK: @tcn = dso_local global %struct.TC zeroinitializer, align 1, !dbg [[TCN:![0-9]+]] +// CHECK: @nn = dso_local global %struct.NN zeroinitializer, align 1, !dbg [[NN:![0-9]+]] // CHECK: !DICompileUnit( // CHECK: [[EMPTY:![0-9]*]] = !{} diff --git a/test/CodeGenCXX/dso-local-executable.cpp b/test/CodeGenCXX/dso-local-executable.cpp new file mode 100644 index 0000000000..cc8d50f09c --- /dev/null +++ b/test/CodeGenCXX/dso-local-executable.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux -mrelocation-model static -O1 -emit-llvm %s -o - | FileCheck --check-prefix=STATIC %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -mrelocation-model static -fno-plt -O1 -emit-llvm %s -o - | FileCheck --check-prefix=NOPLT %s + +// STATIC-DAG: @_ZTV1C = linkonce_odr dso_local unnamed_addr constant +// STATIC-DAG: @_ZTS1C = linkonce_odr dso_local constant +// STATIC-DAG: @_ZTI1C = linkonce_odr dso_local constant +// STATIC-DAG: @_ZZ14useStaticLocalvE3obj = linkonce_odr dso_local global +// STATIC-DAG: @_ZGVZN5guard1gEvE1a = linkonce_odr dso_local global +// STATIC-DAG: define dso_local void @_ZN1CC2Ev( +// STATIC-DAG: define dso_local void @_ZN1CC1Ev( +// STATIC-DAG: define linkonce_odr dso_local void @_ZN1C3fooEv( + +// NOPLT-DAG: @_ZTV1C = linkonce_odr dso_local unnamed_addr constant +// NOPLT-DAG: @_ZTS1C = linkonce_odr dso_local constant +// NOPLT-DAG: @_ZTI1C = linkonce_odr dso_local constant +// NOPLT-DAG: @_ZZ14useStaticLocalvE3obj = linkonce_odr dso_local global +// NOPLT-DAG: @_ZGVZN5guard1gEvE1a = linkonce_odr dso_local global +// NOPLT-DAG: define dso_local void @_ZN1CC2Ev( +// NOPLT-DAG: define dso_local void @_ZN1CC1Ev( +// NOPLT-DAG: define linkonce_odr dso_local void @_ZN1C3fooEv( + +struct C { + C(); + virtual void foo() {} +}; +C::C() {} + +struct HasVTable { + virtual void f(); +}; +inline HasVTable &useStaticLocal() { + static HasVTable obj; + return obj; +} +void useit() { + useStaticLocal(); +} + +namespace guard { +int f(); +inline int g() { + static int a = f(); + return a; +} +int h() { + return g(); +} +} // namespace guard + + +// STATIC-DAG: define available_externally dso_local void @_ZN5test23barIcEC1Ev( +// NOPLT-DAG: define available_externally void @_ZN5test23barIcEC1Ev( +namespace test2 { +void foo(); +template +struct bar { + virtual void zed(); + bar() { foo(); } +}; +extern template class bar; +bar abc; +} // namespace test2 diff --git a/test/CodeGenCXX/float16-declarations.cpp b/test/CodeGenCXX/float16-declarations.cpp index e0d62b71c4..e82c05ec8c 100644 --- a/test/CodeGenCXX/float16-declarations.cpp +++ b/test/CodeGenCXX/float16-declarations.cpp @@ -29,18 +29,18 @@ namespace { /* File */ _Float16 f1f; -// CHECK-AARCH64-DAG: @f1f = global half 0xH0000, align 2 -// CHECK-X86-DAG: @f1f = global half 0xH0000, align 2 +// CHECK-AARCH64-DAG: @f1f = dso_local global half 0xH0000, align 2 +// CHECK-X86-DAG: @f1f = dso_local global half 0xH0000, align 2 _Float16 f2f = 32.4; -// CHECK-DAG: @f2f = global half 0xH500D, align 2 +// CHECK-DAG: @f2f = dso_local global half 0xH500D, align 2 _Float16 arr1f[10]; -// CHECK-AARCH64-DAG: @arr1f = global [10 x half] zeroinitializer, align 2 -// CHECK-X86-DAG: @arr1f = global [10 x half] zeroinitializer, align 16 +// CHECK-AARCH64-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 2 +// CHECK-X86-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 16 _Float16 arr2f[] = { -1.2, -3.0, -3.e4 }; -// CHECK-DAG: @arr2f = global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2 +// CHECK-DAG: @arr2f = dso_local global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2 _Float16 func1f(_Float16 arg); @@ -51,24 +51,24 @@ class C1 { _Float16 f1c; static const _Float16 f2c; -// CHECK-DAG: @_ZN2C13f2cE = external constant half, align 2 +// CHECK-DAG: @_ZN2C13f2cE = external dso_local constant half, align 2 volatile _Float16 f3c; public: C1(_Float16 arg) : f1c(arg), f3c(arg) { } // Check that we mangle _Float16 to DF16_ -// CHECK-DAG: define linkonce_odr void @_ZN2C1C2EDF16_(%class.C1*{{.*}}, half{{.*}}) +// CHECK-DAG: define linkonce_odr dso_local void @_ZN2C1C2EDF16_(%class.C1*{{.*}}, half{{.*}}) _Float16 func1c(_Float16 arg ) { return f1c + arg; } -// CHECK-DAG: define linkonce_odr half @_ZN2C16func1cEDF16_(%class.C1*{{.*}}, half{{.*}}) +// CHECK-DAG: define linkonce_odr dso_local half @_ZN2C16func1cEDF16_(%class.C1*{{.*}}, half{{.*}}) static _Float16 func2c(_Float16 arg) { return arg * C1::f2c; } -// CHECK-DAG: define linkonce_odr half @_ZN2C16func2cEDF16_(half{{.*}}) +// CHECK-DAG: define linkonce_odr dso_local half @_ZN2C16func2cEDF16_(half{{.*}}) }; /* Template */ @@ -76,7 +76,7 @@ public: template C func1t(C arg) { return arg * 2.f16; } -// CHECK-DAG: define linkonce_odr half @_Z6func1tIDF16_ET_S0_(half{{.*}}) +// CHECK-DAG: define linkonce_odr dso_local half @_Z6func1tIDF16_ET_S0_(half{{.*}}) template struct S1 { C mem1; diff --git a/test/CodeGenCXX/split-stacks.cpp b/test/CodeGenCXX/split-stacks.cpp index 76e1b79b8f..2373bcc982 100644 --- a/test/CodeGenCXX/split-stacks.cpp +++ b/test/CodeGenCXX/split-stacks.cpp @@ -16,18 +16,18 @@ int nosplit() { return tnosplit(); } -// 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]+]] comdat { +// CHECK-SEGSTK: define dso_local i32 @_Z3foov() [[SS:#[0-9]+]] { +// CHECK-SEGSTK: define dso_local i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] { +// CHECK-SEGSTK: define linkonce_odr dso_local i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] comdat { // CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} } // CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} } -// 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]+]] comdat { +// CHECK-NOSEGSTK: define dso_local i32 @_Z3foov() [[NSS0:#[0-9]+]] { +// CHECK-NOSEGSTK: define dso_local i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] { +// CHECK-NOSEGSTK: define linkonce_odr dso_local 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/Driver/lanai-unknown-unknown.cpp b/test/Driver/lanai-unknown-unknown.cpp index 5ce0adf9f3..220a84f9eb 100644 --- a/test/Driver/lanai-unknown-unknown.cpp +++ b/test/Driver/lanai-unknown-unknown.cpp @@ -11,25 +11,25 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t; extern "C" { -// CHECK: @align_c = global i32 1 +// CHECK: @align_c = dso_local global i32 1 int align_c = __alignof(char); -// CHECK: @align_s = global i32 2 +// CHECK: @align_s = dso_local global i32 2 int align_s = __alignof(short); -// CHECK: @align_i = global i32 4 +// CHECK: @align_i = dso_local global i32 4 int align_i = __alignof(int); -// CHECK: @align_l = global i32 4 +// CHECK: @align_l = dso_local global i32 4 int align_l = __alignof(long); -// CHECK: @align_ll = global i32 8 +// CHECK: @align_ll = dso_local global i32 8 int align_ll = __alignof(long long); -// CHECK: @align_p = global i32 4 +// CHECK: @align_p = dso_local global i32 4 int align_p = __alignof(void*); -// CHECK: @align_vl = global i32 4 +// CHECK: @align_vl = dso_local global i32 4 int align_vl = __alignof(va_list); // Check types diff --git a/test/Driver/le32-unknown-nacl.cpp b/test/Driver/le32-unknown-nacl.cpp index 379ddb6c63..9bbcdec037 100644 --- a/test/Driver/le32-unknown-nacl.cpp +++ b/test/Driver/le32-unknown-nacl.cpp @@ -10,34 +10,34 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t; extern "C" { -// CHECK: @align_c = global i32 1 +// CHECK: @align_c = dso_local global i32 1 int align_c = __alignof(char); -// CHECK: @align_s = global i32 2 +// CHECK: @align_s = dso_local global i32 2 int align_s = __alignof(short); -// CHECK: @align_i = global i32 4 +// CHECK: @align_i = dso_local global i32 4 int align_i = __alignof(int); -// CHECK: @align_l = global i32 4 +// CHECK: @align_l = dso_local global i32 4 int align_l = __alignof(long); -// CHECK: @align_ll = global i32 8 +// CHECK: @align_ll = dso_local global i32 8 int align_ll = __alignof(long long); -// CHECK: @align_p = global i32 4 +// CHECK: @align_p = dso_local global i32 4 int align_p = __alignof(void*); -// CHECK: @align_f = global i32 4 +// CHECK: @align_f = dso_local global i32 4 int align_f = __alignof(float); -// CHECK: @align_d = global i32 8 +// CHECK: @align_d = dso_local global i32 8 int align_d = __alignof(double); -// CHECK: @align_ld = global i32 8 +// CHECK: @align_ld = dso_local global i32 8 int align_ld = __alignof(long double); -// CHECK: @align_vl = global i32 4 +// CHECK: @align_vl = dso_local global i32 4 int align_vl = __alignof(va_list); // CHECK: __LITTLE_ENDIAN__defined diff --git a/test/Driver/le64-unknown-unknown.cpp b/test/Driver/le64-unknown-unknown.cpp index d0a58598ff..8cee9dc375 100644 --- a/test/Driver/le64-unknown-unknown.cpp +++ b/test/Driver/le64-unknown-unknown.cpp @@ -9,34 +9,34 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t; extern "C" { -// CHECK: @align_c = global i32 1 +// CHECK: @align_c = dso_local global i32 1 int align_c = __alignof(char); -// CHECK: @align_s = global i32 2 +// CHECK: @align_s = dso_local global i32 2 int align_s = __alignof(short); -// CHECK: @align_i = global i32 4 +// CHECK: @align_i = dso_local global i32 4 int align_i = __alignof(int); -// CHECK: @align_l = global i32 8 +// CHECK: @align_l = dso_local global i32 8 int align_l = __alignof(long); -// CHECK: @align_ll = global i32 8 +// CHECK: @align_ll = dso_local global i32 8 int align_ll = __alignof(long long); -// CHECK: @align_p = global i32 8 +// CHECK: @align_p = dso_local global i32 8 int align_p = __alignof(void*); -// CHECK: @align_f = global i32 4 +// CHECK: @align_f = dso_local global i32 4 int align_f = __alignof(float); -// CHECK: @align_d = global i32 8 +// CHECK: @align_d = dso_local global i32 8 int align_d = __alignof(double); -// CHECK: @align_ld = global i32 8 +// CHECK: @align_ld = dso_local global i32 8 int align_ld = __alignof(long double); -// CHECK: @align_vl = global i32 4 +// CHECK: @align_vl = dso_local global i32 4 int align_vl = __alignof(va_list); // CHECK: __LITTLE_ENDIAN__defined diff --git a/test/Driver/riscv32-toolchain.c b/test/Driver/riscv32-toolchain.c index 3839f8e59c..36ba4b6df3 100644 --- a/test/Driver/riscv32-toolchain.c +++ b/test/Driver/riscv32-toolchain.c @@ -41,37 +41,37 @@ typedef __SIZE_TYPE__ size_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __WCHAR_TYPE__ wchar_t; -// CHECK: @align_c = global i32 1 +// CHECK: @align_c = dso_local global i32 1 int align_c = __alignof(char); -// CHECK: @align_s = global i32 2 +// CHECK: @align_s = dso_local global i32 2 int align_s = __alignof(short); -// CHECK: @align_i = global i32 4 +// CHECK: @align_i = dso_local global i32 4 int align_i = __alignof(int); -// CHECK: @align_wc = global i32 4 +// CHECK: @align_wc = dso_local global i32 4 int align_wc = __alignof(wchar_t); -// CHECK: @align_l = global i32 4 +// CHECK: @align_l = dso_local global i32 4 int align_l = __alignof(long); -// CHECK: @align_ll = global i32 8 +// CHECK: @align_ll = dso_local global i32 8 int align_ll = __alignof(long long); -// CHECK: @align_p = global i32 4 +// CHECK: @align_p = dso_local global i32 4 int align_p = __alignof(void*); -// CHECK: @align_f = global i32 4 +// CHECK: @align_f = dso_local global i32 4 int align_f = __alignof(float); -// CHECK: @align_d = global i32 8 +// CHECK: @align_d = dso_local global i32 8 int align_d = __alignof(double); -// CHECK: @align_ld = global i32 16 +// CHECK: @align_ld = dso_local global i32 16 int align_ld = __alignof(long double); -// CHECK: @align_vl = global i32 4 +// CHECK: @align_vl = dso_local global i32 4 int align_vl = __alignof(va_list); // Check types @@ -79,44 +79,44 @@ int align_vl = __alignof(va_list); // CHECK: zeroext i8 @check_char() char check_char() { return 0; } -// CHECK: define signext i16 @check_short() +// CHECK: define dso_local signext i16 @check_short() short check_short() { return 0; } -// CHECK: define i32 @check_int() +// CHECK: define dso_local i32 @check_int() int check_int() { return 0; } -// CHECK: define i32 @check_wchar_t() +// CHECK: define dso_local i32 @check_wchar_t() int check_wchar_t() { return 0; } -// CHECK: define i32 @check_long() +// CHECK: define dso_local i32 @check_long() long check_long() { return 0; } -// CHECK: define i64 @check_longlong() +// CHECK: define dso_local i64 @check_longlong() long long check_longlong() { return 0; } -// CHECK: define zeroext i8 @check_uchar() +// CHECK: define dso_local zeroext i8 @check_uchar() unsigned char check_uchar() { return 0; } -// CHECK: define zeroext i16 @check_ushort() +// CHECK: define dso_local zeroext i16 @check_ushort() unsigned short check_ushort() { return 0; } -// CHECK: define i32 @check_uint() +// CHECK: define dso_local i32 @check_uint() unsigned int check_uint() { return 0; } -// CHECK: define i32 @check_ulong() +// CHECK: define dso_local i32 @check_ulong() unsigned long check_ulong() { return 0; } -// CHECK: define i64 @check_ulonglong() +// CHECK: define dso_local i64 @check_ulonglong() unsigned long long check_ulonglong() { return 0; } -// CHECK: define i32 @check_size_t() +// CHECK: define dso_local i32 @check_size_t() size_t check_size_t() { return 0; } -// CHECK: define float @check_float() +// CHECK: define dso_local float @check_float() float check_float() { return 0; } -// CHECK: define double @check_double() +// CHECK: define dso_local double @check_double() double check_double() { return 0; } -// CHECK: define fp128 @check_longdouble() +// CHECK: define dso_local fp128 @check_longdouble() long double check_longdouble() { return 0; } diff --git a/test/Driver/riscv64-toolchain.c b/test/Driver/riscv64-toolchain.c index 8a3f3228ed..44dcc937df 100644 --- a/test/Driver/riscv64-toolchain.c +++ b/test/Driver/riscv64-toolchain.c @@ -10,82 +10,82 @@ typedef __SIZE_TYPE__ size_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __WCHAR_TYPE__ wchar_t; -// CHECK: @align_c = global i32 1 +// CHECK: @align_c = dso_local global i32 1 int align_c = __alignof(char); -// CHECK: @align_s = global i32 2 +// CHECK: @align_s = dso_local global i32 2 int align_s = __alignof(short); -// CHECK: @align_i = global i32 4 +// CHECK: @align_i = dso_local global i32 4 int align_i = __alignof(int); -// CHECK: @align_wc = global i32 4 +// CHECK: @align_wc = dso_local global i32 4 int align_wc = __alignof(wchar_t); -// CHECK: @align_l = global i32 8 +// CHECK: @align_l = dso_local global i32 8 int align_l = __alignof(long); -// CHECK: @align_ll = global i32 8 +// CHECK: @align_ll = dso_local global i32 8 int align_ll = __alignof(long long); -// CHECK: @align_p = global i32 8 +// CHECK: @align_p = dso_local global i32 8 int align_p = __alignof(void*); -// CHECK: @align_f = global i32 4 +// CHECK: @align_f = dso_local global i32 4 int align_f = __alignof(float); -// CHECK: @align_d = global i32 8 +// CHECK: @align_d = dso_local global i32 8 int align_d = __alignof(double); -// CHECK: @align_ld = global i32 16 +// CHECK: @align_ld = dso_local global i32 16 int align_ld = __alignof(long double); -// CHECK: @align_vl = global i32 8 +// CHECK: @align_vl = dso_local global i32 8 int align_vl = __alignof(va_list); // Check types -// CHECK: define zeroext i8 @check_char() +// CHECK: define dso_local zeroext i8 @check_char() char check_char() { return 0; } -// CHECK: define signext i16 @check_short() +// CHECK: define dso_local signext i16 @check_short() short check_short() { return 0; } -// CHECK: define signext i32 @check_int() +// CHECK: define dso_local signext i32 @check_int() int check_int() { return 0; } -// CHECK: define signext i32 @check_wchar_t() +// CHECK: define dso_local signext i32 @check_wchar_t() int check_wchar_t() { return 0; } -// CHECK: define i64 @check_long() +// CHECK: define dso_local i64 @check_long() long check_long() { return 0; } -// CHECK: define i64 @check_longlong() +// CHECK: define dso_local i64 @check_longlong() long long check_longlong() { return 0; } -// CHECK: define zeroext i8 @check_uchar() +// CHECK: define dso_local zeroext i8 @check_uchar() unsigned char check_uchar() { return 0; } -// CHECK: define zeroext i16 @check_ushort() +// CHECK: define dso_local zeroext i16 @check_ushort() unsigned short check_ushort() { return 0; } -// CHECK: define signext i32 @check_uint() +// CHECK: define dso_local signext i32 @check_uint() unsigned int check_uint() { return 0; } -// CHECK: define i64 @check_ulong() +// CHECK: define dso_local i64 @check_ulong() unsigned long check_ulong() { return 0; } -// CHECK: define i64 @check_ulonglong() +// CHECK: define dso_local i64 @check_ulonglong() unsigned long long check_ulonglong() { return 0; } -// CHECK: define i64 @check_size_t() +// CHECK: define dso_local i64 @check_size_t() size_t check_size_t() { return 0; } -// CHECK: define float @check_float() +// CHECK: define dso_local float @check_float() float check_float() { return 0; } -// CHECK: define double @check_double() +// CHECK: define dso_local double @check_double() double check_double() { return 0; } -// CHECK: define fp128 @check_longdouble() +// CHECK: define dso_local fp128 @check_longdouble() long double check_longdouble() { return 0; } diff --git a/test/Frontend/ast-codegen.c b/test/Frontend/ast-codegen.c index 4a3f8a3b79..e1140fdd8b 100644 --- a/test/Frontend/ast-codegen.c +++ b/test/Frontend/ast-codegen.c @@ -5,9 +5,9 @@ // CHECK: module asm "foo" __asm__("foo"); -// CHECK: @g0 = common global i32 0, align 4 +// CHECK: @g0 = common dso_local global i32 0, align 4 int g0; -// CHECK: define i32 @f0() +// CHECK: define dso_local i32 @f0() int f0() { }