1; RUN: llc < %s -emulated-tls -march=x86 -mcpu=generic -mtriple=i386-linux-gnu -relocation-model=pic \ 2; RUN: | FileCheck -check-prefix=X32 %s 3; RUN: llc < %s -emulated-tls -march=x86-64 -mcpu=generic -mtriple=x86_64-linux-gnu -relocation-model=pic \ 4; RUN: | FileCheck -check-prefix=X64 %s 5; RUN: llc < %s -emulated-tls -march=x86 -mcpu=generic -mtriple=i386-linux-android -relocation-model=pic \ 6; RUN: | FileCheck -check-prefix=X32 %s 7; RUN: llc < %s -emulated-tls -march=x86-64 -mcpu=generic -mtriple=x86_64-linux-android -relocation-model=pic \ 8; RUN: | FileCheck -check-prefix=X64 %s 9 10; Use my_emutls_get_address like __emutls_get_address. 11@my_emutls_v_xyz = external global i8*, align 4 12declare i8* @my_emutls_get_address(i8*) 13 14define i32 @my_get_xyz() { 15; X32-LABEL: my_get_xyz: 16; X32: movl my_emutls_v_xyz@GOT(%ebx), %eax 17; X32-NEXT: movl %eax, (%esp) 18; X32-NEXT: calll my_emutls_get_address@PLT 19; X32-NEXT: movl (%eax), %eax 20; X32-NEXT: addl $8, %esp 21; X32-NEXT: popl %ebx 22; X32-NEXT: retl 23; X64-LABEL: my_get_xyz: 24; X64: movq my_emutls_v_xyz@GOTPCREL(%rip), %rdi 25; X64-NEXT: callq my_emutls_get_address@PLT 26; X64-NEXT: movl (%rax), %eax 27; X64-NEXT: popq %rcx 28; X64-NEXT: retq 29 30entry: 31 %call = call i8* @my_emutls_get_address(i8* bitcast (i8** @my_emutls_v_xyz to i8*)) 32 %0 = bitcast i8* %call to i32* 33 %1 = load i32, i32* %0, align 4 34 ret i32 %1 35} 36 37@i = thread_local global i32 15 38@i2 = external thread_local global i32 39 40define i32 @f1() { 41; X32-LABEL: f1: 42; X32: leal __emutls_v.i@GOTOFF(%ebx), %eax 43; X32-NEXT: movl %eax, (%esp) 44; X32-NEXT: calll __emutls_get_address@PLT 45; X32-NEXT: movl (%eax), %eax 46; X32-NEXT: addl $8, %esp 47; X32-NEXT: popl %ebx 48; X32-NEXT: retl 49; X64-LABEL: f1: 50; X64: leaq __emutls_v.i(%rip), %rdi 51; X64-NEXT: callq __emutls_get_address@PLT 52; X64-NEXT: movl (%rax), %eax 53; X64-NEXT: popq %rcx 54; X64-NEXT: retq 55 56entry: 57 %tmp1 = load i32, i32* @i 58 ret i32 %tmp1 59} 60 61define i32* @f2() { 62; X32-LABEL: f2: 63; X32: leal __emutls_v.i@GOTOFF(%ebx), %eax 64; X32-NEXT: movl %eax, (%esp) 65; X32-NEXT: calll __emutls_get_address@PLT 66; X64-LABEL: f2: 67; X64: leaq __emutls_v.i(%rip), %rdi 68; X64-NEXT: callq __emutls_get_address@PLT 69 70entry: 71 ret i32* @i 72} 73 74define i32 @f3() { 75; X32-LABEL: f3: 76; X32: movl __emutls_v.i2@GOT(%ebx), %eax 77; X32-NEXT: movl %eax, (%esp) 78; X32-NEXT: calll __emutls_get_address@PLT 79; X64-LABEL: f3: 80; X64: movq __emutls_v.i2@GOTPCREL(%rip), %rdi 81; X64-NEXT: callq __emutls_get_address@PLT 82 83entry: 84 %tmp1 = load i32, i32* @i2 85 ret i32 %tmp1 86} 87 88define i32* @f4() { 89; X32-LABEL: f4: 90; X32: movl __emutls_v.i2@GOT(%ebx), %eax 91; X32-NEXT: movl %eax, (%esp) 92; X32-NEXT: calll __emutls_get_address@PLT 93; X64-LABEL: f4: 94; X64: movq __emutls_v.i2@GOTPCREL(%rip), %rdi 95; X64-NEXT: callq __emutls_get_address@PLT 96 97entry: 98 ret i32* @i2 99} 100 101;;;;; 32-bit targets 102 103; X32: .data 104; X32-LABEL: __emutls_v.i: 105; X32-NEXT: .long 4 106; X32-NEXT: .long 4 107; X32-NEXT: .long 0 108; X32-NEXT: .long __emutls_t.i 109 110; X32: .section .rodata, 111; X32-LABEL: __emutls_t.i: 112; X32-NEXT: .long 15 113 114; X32-NOT: __emutls_v.i2 115; X32-NOT: __emutls_t.i2 116 117;;;;; 64-bit targets 118 119; X64: .data 120; X64-LABEL: __emutls_v.i: 121; X64-NEXT: .quad 4 122; X64-NEXT: .quad 4 123; X64-NEXT: .quad 0 124; X64-NEXT: .quad __emutls_t.i 125 126; X64: .section .rodata, 127; X64-LABEL: __emutls_t.i: 128; X64-NEXT: .long 15 129 130; X64-NOT: __emutls_v.i2 131; X64-NOT: __emutls_t.i2 132 133 134!llvm.module.flags = !{!0, !1} 135!0 = !{i32 1, !"PIC Level", i32 1} 136!1 = !{i32 1, !"PIE Level", i32 1} 137