For everyone understand which code must be emitted to implement TLS, I
will paste the code generated by gcc for a simple function:
__thread int a = 1;
int f(){
return a;
}
gcc teste.c -o teste.s -S -O2 (arm-linux-gnueabi):
.global a
.section .tdata,"awT",%progbits <== special section
for
tls symbols
.align 2
.type a, %object
.size a, 4
a:
.word 1
.text
.align 2
.global f
.type f, %function
f:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
str lr, [sp, #-4]!
ldr r3, .L2
bl __aeabi_read_tp @ load_tp_soft <== get thread pointer
(abi dependent)
ldr r0, [r0, r3]
ldr pc, [sp], #4
.L3:
.align 2
.L2:
.word a(tpoff) <== offset of "a"
.size f, .-f
The idea of implementing TLS is to create the "thread_local" keyword.
The program above would be converted to this:
@a = thread_local global i32 1 ; <i32*> [#uses=1] <== Thread
local keyword
define i32 @f() {
entry:
%tmp1 = load i32* @a ; <i32> [#uses=1]
ret i32 %tmp1
}
With "thread_local" keyword, the backends can emit TLS code. The TLS
is architecture and abi dependent, so I think we must let the backends
handle with TLS symbols. Each backend must handle each TLS model.
> Adding TLS support seems to be tricky, since there are 4
> different TLS "models" with different "assumptions".
There is a model ("general dynamic") that works in all situations. The
other three models are optimizations of the first. So, I think we
should start implementing the "general dynamic" model.
I believe the roadmap is:
1. make LLVM understand "thread_local" keyword. (AsmParser, AsmWriter,
BCReader, BCWriter)
2. make llvm-gcc emit "thread_local" keyword
3. implement "thread_local" in C backend (model independent)
3. implement "general dynamic" tls model for i386-linux-gnu
4. implement "general dynamic" tls model for arm-linux-gnueabi (this
is more complex because gcc 4.0 doesn't support tls for arm. I will
have to backport a patch from gcc 4.1 to llvm-gcc)
5. Maybe implement other models for arm-linux-gnueabi
Suggestions are appreciated. :-)
Lauro
Hi Lauro, On Wed, 2007-04-11 at 15:15 -0300, Lauro Ramos Venancio wrote:> For everyone understand which code must be emitted to implement TLS, I > will paste the code generated by gcc for a simple function:... snip ... This proposal sounds really good to me. I only have a couple comments. We have a "section" keyword already developed in LLVM assembly. Perhaps instead of introducing a new keyword we just do: section "TLS" ? This should reduce the amount of work needed to get the feature done. The "general dynamic" mechanism seems to be the way to start this. Get that working on all targets (not just X86 and ARM :) .. then move on to target specific optimizations. If you're signing up for this, could you cut & past it into a new enhancement (if you haven't already) so we can track discussion on the design and progress. Thanks Lauro, Reid.> > __thread int a = 1; > > int f(){ > return a; > } > > gcc teste.c -o teste.s -S -O2 (arm-linux-gnueabi): > > > .global a > .section .tdata,"awT",%progbits <== special section for > tls symbols > .align 2 > .type a, %object > .size a, 4 > a: > .word 1 > .text > .align 2 > .global f > .type f, %function > f: > @ args = 0, pretend = 0, frame = 0 > @ frame_needed = 0, uses_anonymous_args = 0 > str lr, [sp, #-4]! > ldr r3, .L2 > bl __aeabi_read_tp @ load_tp_soft <== get thread pointer > (abi dependent) > ldr r0, [r0, r3] > ldr pc, [sp], #4 > .L3: > .align 2 > .L2: > .word a(tpoff) <== offset of "a" > .size f, .-f > > > The idea of implementing TLS is to create the "thread_local" keyword. > The program above would be converted to this: > > @a = thread_local global i32 1 ; <i32*> [#uses=1] <== Thread > local keyword > > define i32 @f() { > entry: > %tmp1 = load i32* @a ; <i32> [#uses=1] > ret i32 %tmp1 > } > > With "thread_local" keyword, the backends can emit TLS code. The TLS > is architecture and abi dependent, so I think we must let the backends > handle with TLS symbols. Each backend must handle each TLS model. > > > Adding TLS support seems to be tricky, since there are 4 > > different TLS "models" with different "assumptions". > > There is a model ("general dynamic") that works in all situations. The > other three models are optimizations of the first. So, I think we > should start implementing the "general dynamic" model. > > I believe the roadmap is: > > 1. make LLVM understand "thread_local" keyword. (AsmParser, AsmWriter, > BCReader, BCWriter) > 2. make llvm-gcc emit "thread_local" keyword > 3. implement "thread_local" in C backend (model independent) > 3. implement "general dynamic" tls model for i386-linux-gnu > 4. implement "general dynamic" tls model for arm-linux-gnueabi (this > is more complex because gcc 4.0 doesn't support tls for arm. I will > have to backport a patch from gcc 4.1 to llvm-gcc) > 5. Maybe implement other models for arm-linux-gnueabi > > Suggestions are appreciated. :-) > > Lauro > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> This proposal sounds really good to me. I only have a couple comments. > > We have a "section" keyword already developed in LLVM assembly. Perhaps > instead of introducing a new keyword we just do: section "TLS" ? This > should reduce the amount of work needed to get the feature done.This is not possible because the programmer can define the TLS section name. The code __thread int a __attribute__ ((section ("teste"))) = 1; is valid.> The "general dynamic" mechanism seems to be the way to start this. Get > that working on all targets (not just X86 and ARM :) .. then move on to > target specific optimizations.Not only the optimizations are target specific. The ELF TLS manual has a section for each target for each TLS model. So, I think we will have an TLS implementation similar to "LowerCallTo" (every backend must implement or assert). Thanks, Lauro