With a couple of very minor modifications, recent versions of clang will
support thread_local storage including support for complex destructors on
10.6.8 using the same emutls.c system that gcc uses to support it. I'll attach
the (amazingly simple) patches below. It picks up the emutls.c support from
libgcc and libstdc++:
$ nm /opt/local/lib/libgcc/libstdc++.6.dylib | grep cxa_thread
0000000000001e16 T ___cxa_thread_atexit
$ nm /opt/local/lib/libgcc/libgcc_s.1.dylib | grep emu
000000000000bd56 T ___emutls_get_address
000000000000bec7 T ___emutls_register_common
This works when we use the MacPorts alternate c++11 support Marcus came up
with, using
-stdlib=macports-libstdc++
and it seems to me to pass all the tests of how thread_local should work that I
can throw at it. So this seems very usable to me at present.
However, when using libc++ (my preferred setup) I'm still having a couple of
issues getting cxa_thread_atexit and emutls_get_address to build into libc++abi
and show up at runtime.
Using RJVB's libcxx Port, I have built libc++abi more in the LINUX way, with
cxa_thread_atexit.cpp included (that was fairly easy), but it doesn't find the
symbols in
/opt/local/libexec/llvm-7.0/lib/clang/7.0.0/lib/darwin/libclang_rt.osx.a
that it needs to find and dies at runtime. I think it's possibly a visibility
thing.
If there is anyone out there with any skills and interest in working on this
please speak up and I'll bring you fully up to speed offline regarding my
libc++/libc++abi build efforts
Best,
Ken
Patches for llvm/clang-7.0 to enable thread_local support using
-stdlib=macports-libstdc++:
==========================
--- a/include/llvm/ADT/Triple.h.orig 2018-10-02 17:38:10.000000000 -0700
+++ b/include/llvm/ADT/Triple.h 2018-10-02 17:38:58.000000000 -0700
@@ -682,7 +682,7 @@
/// Tests whether the target uses emulated TLS as default.
bool hasDefaultEmulatedTLS() const {
- return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment();
+ return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment() ||
isMacOSXVersionLT(10, 7);
}
/// @}
==========================
--- a/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp.orig 2018-10-02
18:31:17.000000000 -0700
+++ b/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp 2018-10-02 18:32:35.000000000
-0700
@@ -2255,7 +2255,7 @@
const char *Name = "__cxa_atexit";
if (TLS) {
const llvm::Triple &T = CGF.getTarget().getTriple();
- Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";
+ Name = (T.isOSDarwin() && !T.isMacOSXVersionLT(10, 7)) ? "_tlv_atexit" :
"__cxa_thread_atexit";
}
// We're assuming that the destructor function is something we can
--- a/tools/clang/lib/Basic/Targets/OSTargets.h.orig 2018-10-02
17:14:10.000000000 -0700
+++ b/tools/clang/lib/Basic/Targets/OSTargets.h 2018-10-02 17:14:41.000000000
-0700
@@ -93,7 +93,7 @@
this->TLSSupported = false;
if (Triple.isMacOSX())
- this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7);
+ this->TLSSupported = !Triple.isMacOSXVersionLT(10, 4);
else if (Triple.isiOS()) {
// 64-bit iOS supported it from 8 onwards, 32-bit device from 9 onwards,
// 32-bit simulator from 10 onwards.
==========================