rafael created this revision.
rafael added reviewers: rnk, rsmith.

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.


https://reviews.llvm.org/D41318

Files:
  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

Index: test/CodeGen/dso-local-executable.c
===================================================================
--- /dev/null
+++ test/CodeGen/dso-local-executable.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck --check-prefix=STATIC %s
+// RUN: %clang_cc1 -emit-llvm -pic-level 2 -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck --check-prefix=STATIC %s
+// STATIC-DAG: @bar = external 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 -emit-llvm -pic-level 2 -pic-is-pie %s -o - | FileCheck --check-prefix=PIE %s
+// PIE-DAG: @bar = external 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 -emit-llvm -fno-plt %s -o - | FileCheck --check-prefix=NOPLT %s
+// NOPLT-DAG: @bar = external 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 -emit-llvm -pic-level 2 -pic-is-pie -fno-plt %s -o - | FileCheck --check-prefix=PIE-NO-PLT %s
+// PIE-NO-PLT-DAG: @bar = external 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 -emit-llvm -pic-level 2 %s -o - | FileCheck --check-prefix=SHARED %s
+// SHARED-DAG: @bar = external global i32
+// SHARED-DAG: declare void @foo()
+// SHARED-DAG: @baz = global i32 42
+// SHARED-DAG: define i32* @zed()
+
+extern int bar;
+void foo(void);
+
+int baz = 42;
+int *zed(void) {
+  foo();
+  return &bar;
+}
+
+// 2* 2 * 2 - 3 =5
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -1531,7 +1531,7 @@
     VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
 
   // Set the right visibility.
-  CGM.setGlobalVisibility(VTable, RD, ForDefinition);
+  CGM.setGVProperties(VTable, RD, ForDefinition);
 
   // 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 @@
   VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
       Name, VTableType, llvm::GlobalValue::ExternalLinkage);
   VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
-  CGM.setGlobalVisibility(VTable, RD, NotForDefinition);
+  CGM.setGVProperties(VTable, RD, NotForDefinition);
 
   if (RD->hasAttr<DLLImportAttr>())
     VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -713,6 +713,12 @@
   void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D,
                            ForDefinition_t IsForDefinition) const;
 
+  void setDSOLocal(llvm::GlobalValue *GV, const NamedDecl *D,
+                   ForDefinition_t IsForDefinition) const;
+
+  void setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D,
+                       ForDefinition_t IsForDefinition) 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: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -684,6 +684,48 @@
     GV->setVisibility(GetLLVMVisibility(LV.getVisibility()));
 }
 
+static bool shouldAssumeDSOLocal(const CodeGenModule &CGM,
+                                 llvm::GlobalValue *GV, const NamedDecl *D,
+                                 ForDefinition_t IsForDefinition) {
+  // Only handle ELF for now.
+  if (!CGM.getTriple().isOSBinFormatELF())
+    return false;
+
+  // If this is not an executable, don't assume anything is local.
+  const auto &LOpts = CGM.getLangOpts();
+  if (LOpts.PICLevel != 0 && !LOpts.PIE)
+    return false;
+
+  // A definition cannot be preempted from an executable.
+  if (IsForDefinition)
+    return true;
+
+  const auto &CGOpts = CGM.getCodeGenOpts();
+  // If we can use copy relocations we can assume it is local.
+  if (isa<VarDecl>(D) && (LOpts.PICLevel == 0 || 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,
+                                ForDefinition_t IsForDefinition) const {
+  if (shouldAssumeDSOLocal(*this, GV, D, IsForDefinition))
+    GV->setDSOLocal(true);
+}
+
+void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D,
+                                    ForDefinition_t IsForDefinition) const {
+  setGlobalVisibility(GV, D, IsForDefinition);
+  setDSOLocal(GV, D, IsForDefinition);
+}
+
 static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) {
   return llvm::StringSwitch<llvm::GlobalVariable::ThreadLocalMode>(S)
       .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel)
@@ -1061,7 +1103,7 @@
 void CodeGenModule::SetCommonAttributes(const Decl *D,
                                         llvm::GlobalValue *GV) {
   if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
-    setGlobalVisibility(GV, ND, ForDefinition);
+    setGVProperties(GV, ND, ForDefinition);
   else
     GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
 
@@ -1203,7 +1245,7 @@
   // overridden by a definition.
 
   setLinkageForGV(F, FD);
-  setGlobalVisibility(F, FD, NotForDefinition);
+  setGVProperties(F, FD, NotForDefinition);
 
   if (FD->getAttr<PragmaClangTextSectionAttr>()) {
     F->addFnAttr("implicit-section-name");
@@ -2444,7 +2486,7 @@
     GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
 
     setLinkageForGV(GV, D);
-    setGlobalVisibility(GV, D, NotForDefinition);
+    setGVProperties(GV, D, NotForDefinition);
 
     if (D->getTLSKind()) {
       if (D->getTLSKind() == VarDecl::TLS_Dynamic)
@@ -3263,7 +3305,7 @@
   setFunctionDLLStorageClass(GD, Fn);
 
   // FIXME: this is redundant with part of setFunctionDefinitionAttributes
-  setGlobalVisibility(Fn, D, ForDefinition);
+  setGVProperties(Fn, D, ForDefinition);
 
   MaybeHandleStaticInExternC(D, Fn);
 
@@ -3859,7 +3901,7 @@
       getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(),
       /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS);
   if (emitter) emitter->finalize(GV);
-  setGlobalVisibility(GV, VD, ForDefinition);
+  setGVProperties(GV, VD, ForDefinition);
   GV->setAlignment(Align.getQuantity());
   if (supportsCOMDAT() && GV->isWeakForLinker())
     GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
Index: lib/CodeGen/CGVTables.cpp
===================================================================
--- lib/CodeGen/CGVTables.cpp
+++ lib/CodeGen/CGVTables.cpp
@@ -51,7 +51,7 @@
 
 static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
                                const ThunkInfo &Thunk, llvm::Function *Fn) {
-  CGM.setGlobalVisibility(Fn, MD, ForDefinition);
+  CGM.setGVProperties(Fn, MD, ForDefinition);
 }
 
 static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk,
@@ -730,7 +730,7 @@
   // Create the variable that will hold the construction vtable.
   llvm::GlobalVariable *VTable =
     CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage);
-  CGM.setGlobalVisibility(VTable, RD, ForDefinition);
+  CGM.setGVProperties(VTable, RD, ForDefinition);
 
   // V-tables are always unnamed_addr.
   VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Index: lib/CodeGen/CGVTT.cpp
===================================================================
--- lib/CodeGen/CGVTT.cpp
+++ lib/CodeGen/CGVTT.cpp
@@ -100,7 +100,7 @@
     VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName()));
 
   // Set the right visibility.
-  CGM.setGlobalVisibility(VTT, RD, ForDefinition);
+  CGM.setGVProperties(VTT, RD, ForDefinition);
 }
 
 llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -240,7 +240,7 @@
       getModule(), LTy, Ty.isConstant(getContext()), Linkage, Init, Name,
       nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS);
   GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
-  setGlobalVisibility(GV, &D, ForDefinition);
+  setGVProperties(GV, &D, ForDefinition);
 
   if (supportsCOMDAT() && GV->isWeakForLinker())
     GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D41318... Rafael Ávila de Espíndola via Phabricator via cfe-commits
    • [PATCH] D... Reid Kleckner via Phabricator via cfe-commits
      • Re: [... Rafael Avila de Espindola via cfe-commits
        • R... Rafael Avila de Espindola via cfe-commits
    • [PATCH] D... Reid Kleckner via Phabricator via cfe-commits
    • [PATCH] D... Rafael Avila de Espindola via Phabricator via cfe-commits

Reply via email to