Recommit r324107.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 7 Feb 2018 19:16:49 +0000 (19:16 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 7 Feb 2018 19:16:49 +0000 (19:16 +0000)
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.

llvm-svn: 324500

22 files changed:
clang/lib/CodeGen/CGDecl.cpp
clang/lib/CodeGen/CGVTT.cpp
clang/lib/CodeGen/CGVTables.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h
clang/lib/CodeGen/ItaniumCXXABI.cpp
clang/test/CodeGen/dso-local-executable.c [new file with mode: 0644]
clang/test/CodeGen/mbackchain-2.c
clang/test/CodeGen/mbackchain-3.c
clang/test/CodeGen/mips-vector-return.c
clang/test/CodeGen/split-stacks.c
clang/test/CodeGenCXX/debug-info-static-member.cpp
clang/test/CodeGenCXX/debug-info-template.cpp
clang/test/CodeGenCXX/dso-local-executable.cpp [new file with mode: 0644]
clang/test/CodeGenCXX/float16-declarations.cpp
clang/test/CodeGenCXX/split-stacks.cpp
clang/test/Driver/lanai-unknown-unknown.cpp
clang/test/Driver/le32-unknown-nacl.cpp
clang/test/Driver/le64-unknown-unknown.cpp
clang/test/Driver/riscv32-toolchain.c
clang/test/Driver/riscv64-toolchain.c
clang/test/Frontend/ast-codegen.c

index e3e4098e7cc1edd464cff7c428ca9ba1439c7d06..7c05a0dee38db1df494f0d2de67a633448b17fcc 100644 (file)
@@ -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
index 92fd93b5ca387ad7da2b6a7805f3555243140b7a..41c8c943f54dbbe677143d0551a94909cb43e5e2 100644 (file)
@@ -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) {
index 67388ee208dd55ad72cf3be1cf33c5bbccf173e8..7a5c6cfe655f27bb2a0c8d6cba639834efbd29cd 100644 (file)
@@ -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);
index b3974b6de4b91212ebde04cca92095cd959f69f0..2d2b5e561650390becf67b219618a4e10b7a94dc 100644 (file)
@@ -715,6 +715,62 @@ 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<VarDecl>(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.
+  if (isa<FunctionDecl>(D) && !CGOpts.NoPLT)
+    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<llvm::GlobalVariable::ThreadLocalMode>(S)
       .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel)
@@ -1172,7 +1228,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
 void CodeGenModule::SetCommonAttributes(const Decl *D,
                                         llvm::GlobalValue *GV) {
   if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
-    setGlobalVisibility(GV, ND);
+    setGVProperties(GV, ND);
   else
     GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
 
@@ -1312,7 +1368,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<PragmaClangTextSectionAttr>()) {
     F->addFnAttr("implicit-section-name");
@@ -2639,7 +2695,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 +3514,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 +4110,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()));
index 33ec27ff1751621609a1fd783deaa80c872c8b42..30ce47b5d7d72f988499acf32bb521fe77db0a85 100644 (file)
@@ -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;
index 3661c0bdb02575823f88e453543fd7a05534fafc..bbb323e4f29d31f7258705149f0634e9904bf477 100644 (file)
@@ -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<DLLImportAttr>())
     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/clang/test/CodeGen/dso-local-executable.c b/clang/test/CodeGen/dso-local-executable.c
new file mode 100644 (file)
index 0000000..2fbdb07
--- /dev/null
@@ -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 dso_local 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 dso_local 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;
+}
index e76afaf7687a71b1c9de550c1d1fb3cdd190f228..bea46d2482637f8145ba056bc5d779265f45e755 100644 (file)
@@ -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) {
 }
 
index b115861f5e02a06bb4a12dd03a8f141c18ce8860..5ff0e1676100c530bea12cac47ee165bf8309811 100644 (file)
@@ -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) {
 }
 
index 8af4998cdf7c9177bf33e7949eca9e276f0ae610..dd3c400c0197289a6307429cba37f130a13daa4e 100644 (file)
@@ -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};
index bf4cf0f026aa01976a08b289f5be2ef84ea4eaf6..d9ff1f955d2ef1f94d216781d9fe69fbaa1edea8 100644 (file)
@@ -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" {{.*}} }
index 3537754ced760baede67812e570928dca67f84b9..702d1f87e752ca46c0eca70ad8b8846f40d046a8 100644 (file)
@@ -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
index 0c34145162159fabbc9f3aaf1dcaa5164acf1d33..4b330a0b0a118b01c599bdbcee60a7c418c18359 100644 (file)
@@ -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<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::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<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::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/clang/test/CodeGenCXX/dso-local-executable.cpp b/clang/test/CodeGenCXX/dso-local-executable.cpp
new file mode 100644 (file)
index 0000000..cc8d50f
--- /dev/null
@@ -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 <typename T>
+struct bar {
+  virtual void zed();
+  bar() { foo(); }
+};
+extern template class bar<char>;
+bar<char> abc;
+} // namespace test2
index e0d62b71c4cdfc81dc55d89c90ab82345d0dfaf0..e82c05ec8c81b0da7bd12d61f6e34c1169987b40 100644 (file)
@@ -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 <class C> 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 <class C> struct S1 {
   C mem1;
index 76e1b79b8f1a989f233af2bbdf5535def70cc8f7..2373bcc982f511b778769b8ea6da3ee3e8c16ba9 100644 (file)
@@ -16,18 +16,18 @@ int nosplit() {
   return tnosplit<int>();
 }
 
-// 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" {{.*}} }
index 5ce0adf9f3a466477b45f21dab36c60d9ebbdd0d..220a84f9eb2de0358648c9d7827ffcecc7132e83 100644 (file)
@@ -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
index 379ddb6c63d82c764bbb89daaef786b8a0a7ebe6..9bbcdec037bac1a80ca1889fa448d2b74b47bcc4 100644 (file)
@@ -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
index d0a58598ffe76a17418ac81c1ff6561aaa6874ee..8cee9dc375c1079053f601b4b6ed787b3edf630e 100644 (file)
@@ -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
index 3839f8e59c9b4454b5e5f4024ace99bc5a0aa65a..36ba4b6df3e6cc1d6fab07b1c504f861442612e3 100644 (file)
@@ -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; }
index 8a3f3228ed05fb4aba4e3d2c1d7bca361483c6bc..44dcc937df2d87bc73872b86388557bff4182d24 100644 (file)
@@ -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; }
index 4a3f8a3b79fd83eeaf887c5d9a60d552efc700d2..e1140fdd8b27e4e298ffc63957b7adc4ab6d2ed0 100644 (file)
@@ -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() {
 }