TLS for Android (and iOS)
zans.is.for.cans at yahoo.com
Sun Mar 30 01:22:14 PDT 2014
"Joakim" <joakim at airpost.net> writes:
> On Thursday, 27 March 2014 at 16:01:31 UTC, Dan Olson wrote:
>> If nobody is working on the emulated TLS for LDC, I will give it a
>> Nothing to lose.
> Whatever I do to implement packed TLS in the dmd backend is not going
> to work for ldc anyway, so nothing stopping you from making your own
> effort. You will have to patch llvm also, if the weak symbols bug
> David pointed out is still around in llvm 3.5. Let us know what
> approach you take.
The approach I started with was to make LLVM do the work. I read
through all of the comments in this thread and decided this might be the
ARMISelLowering.cpp has TLS disabled for all but ELF targets. I
commented out an assertion blocking other targets to see what would
happen for iOS (Mach-O). To my suprise, found that Mach-O tls sections
are generated (__thread_vars, __thread_data, .tbss) and populated with
the D thread local vars.
The load/store instructions were treating TLS vars like global data
though. So I looked at the Mach-O X86 version and saw what it is trying
to do. LLVM coding is still a mystery to me, but managed after many
hours today to hack together something that would turn this D code
a += 4; // access a
movw r0, :lower16:(__D4tlsd1ai-(LPC4_0+4))
movt r0, :upper16:(__D4tlsd1ai-(LPC4_0+4))
add r0, pc
ldr r1, [r0]
adds r1, #4
str r1, [r0]
.tbss __D4tlsd1ai$tlv$init, 4, 2
The following link helped explain what is going on with the
__thread_vars data layout.
Mach-O dyln replaces tlv_bootstrap (thunk) with tlv_get_addr in the
TLVDescriptor (__thread_vars). My LLVM hack for now is just doing a
direct call to __tls_get_addr instead of indirect to tlv_get_addr. For
proof of concept (one thread only), I have __tls_get_addr hard wired as
void* function(TLVDescriptor*) thunk;
//void* tlv_get_addr(TLVDescriptor* d)
//void* __tls_get_addr(void* ptr)
void* __tls_get_addr(TLVDescriptor* tlvd)
__gshared static ubyte data;
printf("__tls_get_addr %p \n", tlvd);
printf("thunk %p, key %u, offset %u\n",
tlvd.thunk, tlvd.key, tlvd.offset);
return data.ptr + tlvd.offset;
assert(false, "Should not get here");
It looks promising. Next step is to add in some realistic runtime
support. Not sure if I will base it on dmd's sections-osx or the Apple
dyld. Probably a hybrid.
Eventually will need some help getting the LLVM changes clean instead of
my hack job.
Now that I've gone down this path a bit, I am beginning to wonder if
changing LLVM to support iOS thread locals will have issues. Would LLVM
want changes that affect Darwin/Mach-O (Apple's turf)? I suppose they
could be optional.
More information about the digitalmars-d-ldc