- Address Richard's review comments.
http://reviews.llvm.org/D4109
Files:
lib/CodeGen/ItaniumCXXABI.cpp
test/CodeGenCXX/tls-init-funcs.cpp
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -1572,6 +1572,15 @@
CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
}
+static bool
+isThreadLocalBackingVariableAlwaysReferenceable(const VarDecl *VD,
+ CodeGen::CodeGenModule &CGM) {
+ // OS X prefers to have references to thread local variables to go through
+ // the thread wrapper instead of directly referencing the backing variable.
+ return VD->getTLSKind() != VarDecl::TLS_Dynamic ||
+ !CGM.getTarget().getTriple().isMacOSX();
+}
+
/// 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.
@@ -1584,12 +1593,14 @@
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;
+ // The thread wrapper can't be inlined if the backing variable cannot always
+ // be referenced.
+ if (!isThreadLocalBackingVariableAlwaysReferenceable(VD, CGM)) {
+ if (llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
+ !VD->isStaticLocal())
+ return llvm::GlobalVariable::WeakAnyLinkage;
+ return VarLinkage;
+ }
return llvm::GlobalValue::WeakODRLinkage;
}
@@ -1616,7 +1627,8 @@
llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM),
WrapperName.str(), &CGM.getModule());
// Always resolve references to the wrapper at link time.
- if (!Wrapper->hasLocalLinkage())
+ if (!Wrapper->hasLocalLinkage() &&
+ isThreadLocalBackingVariableAlwaysReferenceable(VD, CGM))
Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
return Wrapper;
}
@@ -1628,6 +1640,13 @@
const VarDecl *VD = Decls[I].first;
llvm::GlobalVariable *Var = Decls[I].second;
+ // Some targets require that all access to thread local variables go through
+ // the thread wrapper. This means that we cannot attempt to create a thread
+ // wrapper or a thread helper.
+ if (!isThreadLocalBackingVariableAlwaysReferenceable(VD, CGM) &&
+ !VD->hasDefinition())
+ continue;
+
// Mangle the name for the thread_local initialization function.
SmallString<256> InitFnName;
{
Index: test/CodeGenCXX/tls-init-funcs.cpp
===================================================================
--- test/CodeGenCXX/tls-init-funcs.cpp
+++ test/CodeGenCXX/tls-init-funcs.cpp
@@ -1,11 +1,30 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++1y -S -emit-llvm %s -o - | FileCheck %s
// CHECK: @a = internal thread_local global
+// CHECK: @_Z2vtIiE = internal thread_local global i32 5
+// CHECK: @_ZZ3inlvE3loc = linkonce_odr thread_local global i32 0
// CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev
-// CHECK: define weak hidden {{.*}} @_ZTW1a
+// CHECK: call i32* @_ZTW3ext()
+// CHECK: declare i32* @_ZTW3ext()
+// CHECK: define weak i32* @_ZTW2vtIiE()
+// CHECK: define {{.*}} @_ZTW1a
struct A {
~A();
};
thread_local A a;
+
+extern thread_local int ext;
+int &get_ext() { return ext; }
+
+template <typename T>
+thread_local int vt = 5;
+
+int get_vt() { return vt<int>; }
+
+inline int &inl() {
+ thread_local int loc;
+ return loc;
+}
+int &use_inl() { return inl(); }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits