]> granicus.if.org Git - clang/commitdiff
Recommit r324107 again.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 7 Feb 2018 22:15:33 +0000 (22:15 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 7 Feb 2018 22:15:33 +0000 (22:15 +0000)
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

22 files changed:
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGVTT.cpp
lib/CodeGen/CGVTables.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/ItaniumCXXABI.cpp
test/CodeGen/dso-local-executable.c [new file with mode: 0644]
test/CodeGen/mbackchain-2.c
test/CodeGen/mbackchain-3.c
test/CodeGen/mips-vector-return.c
test/CodeGen/split-stacks.c
test/CodeGenCXX/debug-info-static-member.cpp
test/CodeGenCXX/debug-info-template.cpp
test/CodeGenCXX/dso-local-executable.cpp [new file with mode: 0644]
test/CodeGenCXX/float16-declarations.cpp
test/CodeGenCXX/split-stacks.cpp
test/Driver/lanai-unknown-unknown.cpp
test/Driver/le32-unknown-nacl.cpp
test/Driver/le64-unknown-unknown.cpp
test/Driver/riscv32-toolchain.c
test/Driver/riscv64-toolchain.c
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..7fa4fddc79e10a7be1adab97f9bdd4c4b6bf38c9 100644 (file)
@@ -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<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.
+  // FIXME: This should work for PIE, but the gold linker doesn't support it.
+  if (isa<FunctionDecl>(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<llvm::GlobalVariable::ThreadLocalMode>(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<NamedDecl>(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<PragmaClangTextSectionAttr>()) {
     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()));
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/test/CodeGen/dso-local-executable.c b/test/CodeGen/dso-local-executable.c
new file mode 100644 (file)
index 0000000..5637ae4
--- /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 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;
+}
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/test/CodeGenCXX/dso-local-executable.cpp b/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() {
 }