r210632 - CodeGen: Correct linkage of thread_local for OS X

David Majnemer david.majnemer at gmail.com
Tue Jun 10 21:08:55 PDT 2014


Author: majnemer
Date: Tue Jun 10 23:08:55 2014
New Revision: 210632

URL: http://llvm.org/viewvc/llvm-project?rev=210632&view=rev
Log:
CodeGen: Correct linkage of thread_local for OS X

The backing store of thread local variables is internal for OS X and all
accesses must go through the thread wrapper.

However, individual TUs may have inlined through the thread wrapper.
To fix this, give the thread wrapper functions WeakAnyLinkage.  This
prevents them from getting inlined into call-sites.

This fixes PR19989.

Modified:
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/tls-init-funcs.cpp

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=210632&r1=210631&r2=210632&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Jun 10 23:08:55 2014
@@ -7843,14 +7843,6 @@ static GVALinkage basicGVALinkageForVari
                                                : StaticLocalLinkage;
   }
 
-  // On Darwin, the backing variable for a C++11 thread_local variable always
-  // has internal linkage; all accesses should just be calls to the
-  // Itanium-specified entry point, which has the normal linkage of the
-  // variable.
-  if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
-      Context.getTargetInfo().getTriple().isMacOSX())
-    return GVA_Internal;
-
   switch (VD->getTemplateSpecializationKind()) {
   case TSK_Undeclared:
   case TSK_ExplicitSpecialization:

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=210632&r1=210631&r2=210632&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Jun 10 23:08:55 2014
@@ -1903,6 +1903,16 @@ void CodeGenModule::EmitGlobalVarDefinit
   // Set the llvm linkage type as appropriate.
   llvm::GlobalValue::LinkageTypes Linkage =
       getLLVMLinkageVarDefinition(D, GV->isConstant());
+
+  // On Darwin, the backing variable for a C++11 thread_local variable always
+  // has internal linkage; all accesses should just be calls to the
+  // Itanium-specified entry point, which has the normal linkage of the
+  // variable.
+  if (const auto *VD = dyn_cast<VarDecl>(D))
+    if (!VD->isStaticLocal() && VD->getTLSKind() == VarDecl::TLS_Dynamic &&
+        Context.getTargetInfo().getTriple().isMacOSX())
+      Linkage = llvm::GlobalValue::InternalLinkage;
+
   GV->setLinkage(Linkage);
   if (D->hasAttr<DLLImportAttr>())
     GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=210632&r1=210631&r2=210632&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Jun 10 23:08:55 2014
@@ -1575,11 +1575,21 @@ void ItaniumCXXABI::registerGlobalDtor(C
 /// Get the appropriate linkage for the wrapper function. This is essentially
 /// the weak form of the variable's linkage; every translation unit which wneeds
 /// the wrapper emits a copy, and we want the linker to merge them.
-static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage(
-    llvm::GlobalValue::LinkageTypes VarLinkage) {
+static llvm::GlobalValue::LinkageTypes
+getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) {
+  llvm::GlobalValue::LinkageTypes VarLinkage =
+      CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false);
+
   // For internal linkage variables, we don't need an external or weak wrapper.
   if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
     return VarLinkage;
+
+  // All accesses to the thread_local variable go through the thread wrapper.
+  // However, this means that we cannot allow the thread wrapper to get inlined
+  // into any functions.
+  if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
+      CGM.getTarget().getTriple().isMacOSX())
+    return llvm::GlobalValue::WeakAnyLinkage;
   return llvm::GlobalValue::WeakODRLinkage;
 }
 
@@ -1602,10 +1612,9 @@ ItaniumCXXABI::getOrCreateThreadLocalWra
     RetTy = RetTy->getPointerElementType();
 
   llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, false);
-  llvm::Function *Wrapper = llvm::Function::Create(
-      FnTy, getThreadLocalWrapperLinkage(
-                CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)),
-      WrapperName.str(), &CGM.getModule());
+  llvm::Function *Wrapper =
+      llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM),
+                             WrapperName.str(), &CGM.getModule());
   // Always resolve references to the wrapper at link time.
   if (!Wrapper->hasLocalLinkage())
     Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);

Modified: cfe/trunk/test/CodeGenCXX/tls-init-funcs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/tls-init-funcs.cpp?rev=210632&r1=210631&r2=210632&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/tls-init-funcs.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/tls-init-funcs.cpp Tue Jun 10 23:08:55 2014
@@ -2,6 +2,7 @@
 
 // CHECK: @a = internal thread_local global
 // CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev
+// CHECK: define weak hidden {{.*}} @_ZTW1a
 
 struct A {
   ~A();





More information about the cfe-commits mailing list