Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -388,6 +388,12 @@ assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) && "No emulated TLS variables in the common section"); + // When in emulated TLS mode, skip __emutls_v.* variables. + // __emutls_v.xyz and __emutls_t.xyz are emitted in place of xyz. + // __emutls_t.xyz is not in the symbol table. + if (TM.Options.EmulatedTLS && GV->getName().startswith("__emutls_v.")) + return; + if (GV->hasInitializer()) { // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(GV)) Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -3072,9 +3072,19 @@ Module *VariableModule = const_cast(GA->getGlobal()->getParent()); StringRef EmuTlsVarName(NameString); GlobalVariable *EmuTlsVar = VariableModule->getNamedGlobal(EmuTlsVarName); - if (!EmuTlsVar) + if (!EmuTlsVar) { EmuTlsVar = dyn_cast_or_null( VariableModule->getOrInsertGlobal(EmuTlsVarName, VoidPtrType)); + // EmuTlsVar should have the same linkage as its TLS variable. + // getOrInsertGlobal always creates new ExternalLinkage variable. + EmuTlsVar->setLinkage(GA->getGlobal()->getLinkage()); + if (!EmuTlsVar->hasInitializer() && + dyn_cast(GA->getGlobal())->hasInitializer()) { + // A fake initializer is necessary to pass through all verification phases. + // Real initializer is computed later from the TLS variable. + EmuTlsVar->setInitializer(ConstantPointerNull::get(VoidPtrType)); + } + } Entry.Node = DAG.getGlobalAddress(EmuTlsVar, dl, PtrVT); Entry.Ty = VoidPtrType; Args.push_back(Entry); Index: test/CodeGen/AArch64/emutls.ll =================================================================== --- test/CodeGen/AArch64/emutls.ll +++ test/CodeGen/AArch64/emutls.ll @@ -54,59 +54,88 @@ ret i32* @i1 } +define i32 @f5() nounwind { +; ARM64-LABEL: f5: +; ARM64: adrp x0, __emutls_v.i3 +; ARM64: add x0, x0, :lo12:__emutls_v.i3 +; ARM64-NEXT: bl __emutls_get_address +; ARM64-NEXT: ldr w0, [x0] + +entry: + %tmp1 = load i32, i32* @i3 + ret i32 %tmp1 +} + +define i32* @f6() { +; ARM64-LABEL: f6: +; ARM64: adrp x0, __emutls_v.i3 +; ARM64: add x0, x0, :lo12:__emutls_v.i3 +; ARM64-NEXT: bl __emutls_get_address +; ARM64-NEXT: ldp x29, x30, [sp] + +entry: + ret i32* @i3 +} + + ;;;;;;;;;;;;;; 64-bit __emutls_v. and __emutls_t. -; ARM64 .section .data.rel.local, +; ARM64: .data{{$}} +; ARM64: .globl __emutls_v.i1 ; ARM64-LABEL: __emutls_v.i1: ; ARM64-NEXT: .xword 4 ; ARM64-NEXT: .xword 4 ; ARM64-NEXT: .xword 0 ; ARM64-NEXT: .xword __emutls_t.i1 -; ARM64 .section .rodata, +; ARM64: .section .rodata, ; ARM64-LABEL: __emutls_t.i1: ; ARM64-NEXT: .word 15 ; ARM64-NOT: __emutls_v.i2 -; ARM64 .section .data.rel.local, +; ARM64: .data{{$}} +; ARM64-NOT: .globl ; ARM64-LABEL: __emutls_v.i3: ; ARM64-NEXT: .xword 4 ; ARM64-NEXT: .xword 4 ; ARM64-NEXT: .xword 0 ; ARM64-NEXT: .xword __emutls_t.i3 -; ARM64 .section .rodata, +; ARM64: .section .rodata, ; ARM64-LABEL: __emutls_t.i3: ; ARM64-NEXT: .word 15 -; ARM64 .section .data.rel.local, +; ARM64: .hidden __emutls_v.i4 +; ARM64: .data{{$}} +; ARM64: .globl __emutls_v.i4 ; ARM64-LABEL: __emutls_v.i4: ; ARM64-NEXT: .xword 4 ; ARM64-NEXT: .xword 4 ; ARM64-NEXT: .xword 0 ; ARM64-NEXT: .xword __emutls_t.i4 -; ARM64 .section .rodata, +; ARM64: .section .rodata, ; ARM64-LABEL: __emutls_t.i4: ; ARM64-NEXT: .word 15 ; ARM64-NOT: __emutls_v.i5: -; ARM64 .hidden __emutls_v.i5 +; ARM64: .hidden __emutls_v.i5 ; ARM64-NOT: __emutls_v.i5: -; ARM64 .section .data.rel.local, +; ARM64: .data{{$}} +; ARM64: .globl __emutls_v.s1 ; ARM64-LABEL: __emutls_v.s1: ; ARM64-NEXT: .xword 2 ; ARM64-NEXT: .xword 2 ; ARM64-NEXT: .xword 0 ; ARM64-NEXT: .xword __emutls_t.s1 -; ARM64 .section .rodata, +; ARM64: .section .rodata, ; ARM64-LABEL: __emutls_t.s1: ; ARM64-NEXT: .hword 15 -; ARM64 .section .data.rel.local, +; ARM64: .data{{$}} ; ARM64-LABEL: __emutls_v.b1: ; ARM64-NEXT: .xword 1 ; ARM64-NEXT: .xword 1 Index: test/CodeGen/AArch64/emutls_generic.ll =================================================================== --- test/CodeGen/AArch64/emutls_generic.ll +++ test/CodeGen/AArch64/emutls_generic.ll @@ -37,6 +37,8 @@ ; ARM_64: __emutls_get_address ; ARM_64-NOT: __emutls_t.external_x ; ARM_64-NOT: __emutls_v.external_x: +; ARM_64: .data{{$}} +; ARM_64: .globl __emutls_v.external_y ; ARM_64: .align 3 ; ARM_64-LABEL: __emutls_v.external_y: ; ARM_64-NEXT: .xword 1 @@ -47,7 +49,8 @@ ; ARM_64: .section .rodata, ; ARM_64-LABEL: __emutls_t.external_y: ; ARM_64-NEXT: .byte 7 -; ARM_64: .data +; ARM_64: .data{{$}} +; ARM_64-NOT: .globl __emutls_v ; ARM_64: .align 3 ; ARM_64-LABEL: __emutls_v.internal_y: ; ARM_64-NEXT: .xword 8 Index: test/CodeGen/ARM/emutls.ll =================================================================== --- test/CodeGen/ARM/emutls.ll +++ test/CodeGen/ARM/emutls.ll @@ -13,6 +13,7 @@ ; ARM32: ldr r0, [pc, r0] ; ARM32-NEXT: bl my_emutls_get_address(PLT) ; ARM32-NEXT: ldr r0, [r0] +; ARM32: .long my_emutls_v_xyz(GOT_PREL) entry: %call = call i8* @my_emutls_get_address(i8* bitcast (i8** @my_emutls_v_xyz to i8*)) @@ -35,6 +36,7 @@ ; ARM32: ldr r0, [pc, r0] ; ARM32-NEXT: bl __emutls_get_address(PLT) ; ARM32-NEXT: ldr r0, [r0] +; ARM32: .long __emutls_v.i1(GOT_PREL) entry: %tmp1 = load i32, i32* @i1 @@ -47,6 +49,7 @@ ; ARM32: ldr r0, [pc, r0] ; ARM32-NEXT: bl __emutls_get_address(PLT) ; ARM32-NEXT: pop +; ARM32: .long __emutls_v.i1(GOT_PREL) entry: ret i32* @i1 @@ -58,6 +61,7 @@ ; ARM32: ldr r0, [pc, r0] ; ARM32-NEXT: bl __emutls_get_address(PLT) ; ARM32-NEXT: ldr r0, [r0] +; ARM32: .long __emutls_v.i2(GOT_PREL) entry: %tmp1 = load i32, i32* @i2 @@ -70,6 +74,7 @@ ; ARM32: ldr r0, [pc, r0] ; ARM32-NEXT: bl __emutls_get_address(PLT) ; ARM32-NEXT: pop +; ARM32: .long __emutls_v.i2(GOT_PREL) entry: ret i32* @i2 @@ -78,9 +83,10 @@ define i32 @f5() nounwind { ; ARM32-LABEL: f5: ; ARM32: ldr r0, -; ARM32: ldr r0, [pc, r0] +; ARM32: add r0, pc, r0 ; ARM32-NEXT: bl __emutls_get_address(PLT) ; ARM32-NEXT: ldr r0, [r0] +; ARM32: .long __emutls_v.i3- entry: %tmp1 = load i32, i32* @i3 @@ -90,9 +96,10 @@ define i32* @f6() { ; ARM32-LABEL: f6: ; ARM32: ldr r0, -; ARM32: ldr r0, [pc, r0] +; ARM32: add r0, pc, r0 ; ARM32-NEXT: bl __emutls_get_address(PLT) ; ARM32-NEXT: pop +; ARM32: .long __emutls_v.i3- entry: ret i32* @i3 @@ -104,6 +111,7 @@ ; ARM32: ldr r0, [pc, r0] ; ARM32-NEXT: bl __emutls_get_address(PLT) ; ARM32-NEXT: ldr r0, [r0] +; ARM32: .long __emutls_v.i4(GOT_PREL) entry: %tmp1 = load i32, i32* @i4 @@ -116,6 +124,7 @@ ; ARM32: ldr r0, [pc, r0] ; ARM32-NEXT: bl __emutls_get_address(PLT) ; ARM32-NEXT: pop +; ARM32: .long __emutls_v.i4(GOT_PREL) entry: ret i32* @i4 @@ -198,46 +207,50 @@ ;;;;;;;;;;;;;; 32-bit __emutls_v. and __emutls_t. -; ARM32 .section .data.rel.local, +; ARM32: .data{{$}} +; ARM32: .globl __emutls_v.i1 ; ARM32-LABEL: __emutls_v.i1: ; ARM32-NEXT: .long 4 ; ARM32-NEXT: .long 4 ; ARM32-NEXT: .long 0 ; ARM32-NEXT: .long __emutls_t.i1 -; ARM32 .section .rodata, +; ARM32: .section .rodata, ; ARM32-LABEL: __emutls_t.i1: ; ARM32-NEXT: .long 15 ; ARM32-NOT: __emutls_v.i2 -; ARM32 .section .data.rel.local, +; ARM32: .data{{$}} +; ARM32-NOT: .globl ; ARM32-LABEL: __emutls_v.i3: ; ARM32-NEXT: .long 4 ; ARM32-NEXT: .long 4 ; ARM32-NEXT: .long 0 ; ARM32-NEXT: .long __emutls_t.i3 -; ARM32 .section .rodata, +; ARM32: .section .rodata, ; ARM32-LABEL: __emutls_t.i3: ; ARM32-NEXT: .long 15 -; ARM32 .section .data.rel.local, +; ARM32: .data{{$}} +; ARM32: .globl __emutls_v.i4 ; ARM32-LABEL: __emutls_v.i4: ; ARM32-NEXT: .long 4 ; ARM32-NEXT: .long 4 ; ARM32-NEXT: .long 0 ; ARM32-NEXT: .long __emutls_t.i4 -; ARM32 .section .rodata, +; ARM32: .section .rodata, ; ARM32-LABEL: __emutls_t.i4: ; ARM32-NEXT: .long 15 ; ARM32-NOT: __emutls_v.i5: -; ARM32 .hidden __emutls_v.i5 +; ARM32: .hidden __emutls_v.i5 ; ARM32-NOT: __emutls_v.i5: -; ARM32 .section .data.rel.local, +; ARM32: .data{{$}} +; ARM32: .globl __emutls_v.s1 ; ARM32-LABEL: __emutls_v.s1: ; ARM32-NEXT: .long 2 ; ARM32-NEXT: .long 2 @@ -248,7 +261,8 @@ ; ARM32-LABEL: __emutls_t.s1: ; ARM32-NEXT: .short 15 -; ARM32 .section .data.rel.local, +; ARM32: .data{{$}} +; ARM32: .globl __emutls_v.b1 ; ARM32-LABEL: __emutls_v.b1: ; ARM32-NEXT: .long 1 ; ARM32-NEXT: .long 1 Index: test/CodeGen/ARM/emutls_generic.ll =================================================================== --- test/CodeGen/ARM/emutls_generic.ll +++ test/CodeGen/ARM/emutls_generic.ll @@ -35,11 +35,12 @@ ; ARM_32: bl __emutls_get_address ; ARM_32: .long __emutls_v.external_y ; ARM_32-LABEL: get_internal_y: -; ARM_32: bl __emutls_get_address -; ARM_32: .long __emutls_v.internal_y -; ARM_32-NOT: __emutls_t.external_x -; ARM_32-NOT: __emutls_v.external_x: -; ARM_32: .data +; ARM_32: bl __emutls_get_address +; ARM_32: .long __emutls_v.internal_y +; ARM_32-NOT: __emutls_t.external_x +; ARM_32-NOT: __emutls_v.external_x: +; ARM_32: .data{{$}} +; ARM_32: .globl __emutls_v.external_y ; ARM_32: .align 2 ; ARM_32-LABEL: __emutls_v.external_y: ; ARM_32-NEXT: .long 1 @@ -49,7 +50,8 @@ ; ARM_32: .section .rodata, ; ARM_32-LABEL: __emutls_t.external_y: ; ARM_32-NEXT: .byte 7 -; ARM_32: .data +; ARM_32: .data{{$}} +; ARM_32-NOT: .globl ; ARM_32: .align 2 ; ARM_32-LABEL: __emutls_v.internal_y: ; ARM_32-NEXT: .long 8 Index: test/CodeGen/X86/emutls-pic.ll =================================================================== --- test/CodeGen/X86/emutls-pic.ll +++ test/CodeGen/X86/emutls-pic.ll @@ -82,28 +82,29 @@ } ; X32-LABEL: f5: -; X32: movl __emutls_v.j@GOT(%ebx), %eax +; X32: leal __emutls_v.j@GOTOFF(%ebx), %eax ; X32-NEXT: movl %eax, (%esp) ; X32-NEXT: calll __emutls_get_address@PLT ; X32-NEXT: movl (%eax), %esi -; X32-NEXT: movl __emutls_v.k@GOT(%ebx), %eax +; X32-NEXT: leal __emutls_v.k@GOTOFF(%ebx), %eax ; X32-NEXT: movl %eax, (%esp) ; X32-NEXT: calll __emutls_get_address@PLT ; X32-NEXT: addl (%eax), %esi ; X32-NEXT: movl %esi, %eax ; X64-LABEL: f5: -; X64: movq __emutls_v.j@GOTPCREL(%rip), %rdi +; X64: leaq __emutls_v.j(%rip), %rdi ; X64-NEXT: callq __emutls_get_address@PLT ; X64-NEXT: movl (%rax), %ebx -; X64-NEXT: movq __emutls_v.k@GOTPCREL(%rip), %rdi +; X64-NEXT: leaq __emutls_v.k(%rip), %rdi ; X64-NEXT: callq __emutls_get_address@PLT ; X64-NEXT: addl (%rax), %ebx ; X64-NEXT: movl %ebx, %eax ;;;;; 32-bit targets -; X32: .data +; X32: .data{{$}} +; X32: .globl __emutls_v.i ; X32-LABEL: __emutls_v.i: ; X32-NEXT: .long 4 ; X32-NEXT: .long 4 @@ -114,7 +115,8 @@ ; X32-LABEL: __emutls_t.i: ; X32-NEXT: .long 15 -; X32: .data +; X32: .data{{$}} +; X32-NOT: .globl ; X32-LABEL: __emutls_v.j: ; X32-NEXT: .long 4 ; X32-NEXT: .long 4 @@ -125,7 +127,8 @@ ; X32-LABEL: __emutls_t.j: ; X32-NEXT: .long 42 -; X32: .data +; X32: .data{{$}} +; X32-NOT: .globl ; X32-LABEL: __emutls_v.k: ; X32-NEXT: .long 4 ; X32-NEXT: .long 8 @@ -136,7 +139,8 @@ ;;;;; 64-bit targets -; X64: .data +; X64: .data{{$}} +; X64: .globl __emutls_v.i ; X64-LABEL: __emutls_v.i: ; X64-NEXT: .quad 4 ; X64-NEXT: .quad 4 @@ -147,7 +151,8 @@ ; X64-LABEL: __emutls_t.i: ; X64-NEXT: .long 15 -; X64: .data +; X64: .data{{$}} +; X64-NOT: .globl ; X64-LABEL: __emutls_v.j: ; X64-NEXT: .quad 4 ; X64-NEXT: .quad 4 @@ -158,7 +163,8 @@ ; X64-LABEL: __emutls_t.j: ; X64-NEXT: .long 42 -; X64: .data +; X64: .data{{$}} +; X64-NOT: .globl ; X64-LABEL: __emutls_v.k: ; X64-NEXT: .quad 4 ; X64-NEXT: .quad 8 Index: test/CodeGen/X86/emutls_generic.ll =================================================================== --- test/CodeGen/X86/emutls_generic.ll +++ test/CodeGen/X86/emutls_generic.ll @@ -45,17 +45,18 @@ ; CHECK: __emutls_t.internal_y ; X86_32-LABEL: get_external_x: -; X86_32: movl __emutls_v.external_x +; X86_32: movl __emutls_v.external_x@GOT(%ebx) ; X86_32: calll __emutls_get_address ; X86_32-LABEL: get_external_y: -; X86_32: movl __emutls_v.external_y +; X86_32: movl __emutls_v.external_y@GOT(%ebx) ; X86_32: calll __emutls_get_address ; X86_32-LABEL: get_internal_y: -; X86_32: movl __emutls_v.internal_y -; X86_32: calll __emutls_get_address -; X86_32-NOT: __emutls_t.external_x -; X86_32-NOT: __emutls_v.external_x: -; X86_32: .data +; X86_32: leal __emutls_v.internal_y@GOTOFF(%ebx) +; X86_32: calll __emutls_get_address +; X86_32-NOT: __emutls_t.external_x +; X86_32-NOT: __emutls_v.external_x: +; X86_32: .data{{$}} +; X86_32: .globl __emutls_v.external_y ; X86_32: .align 4 ; X86_32-LABEL: __emutls_v.external_y: ; X86_32-NEXT: .long 1 @@ -65,7 +66,8 @@ ; X86_32: .section .rodata, ; X86_32-LABEL: __emutls_t.external_y: ; X86_32-NEXT: .byte 7 -; X86_32: .data +; X86_32: .data{{$}} +; X86_32-NOT: .globl ; X86_32: .align 4 ; X86_32-LABEL: __emutls_v.internal_y: ; X86_32-NEXT: .long 8 @@ -75,16 +77,17 @@ ; X86_32-LABEL: __emutls_t.internal_y: ; X86_32-NEXT: .quad 9 ; X86_64-LABEL: get_external_x: -; X86_64: __emutls_v.external_x -; X86_64: __emutls_get_address +; X86_64: __emutls_v.external_x@GOTPCREL(%rip) +; X86_64: __emutls_get_address ; X86_64-LABEL: get_external_y: -; X86_64: __emutls_v.external_y -; X86_64: __emutls_get_address +; X86_64: __emutls_v.external_y@GOTPCREL(%rip) +; X86_64: __emutls_get_address ; X86_64-LABEL: get_internal_y: -; X86_64: __emutls_v.internal_y -; X86_64: __emutls_get_address -; X86_64-NOT: __emutls_t.external_x -; X86_64-NOT: __emutls_v.external_x: +; X86_64: __emutls_v.internal_y(%rip) +; X86_64: __emutls_get_address +; X86_64-NOT: __emutls_t.external_x +; X86_64-NOT: __emutls_v.external_x: +; X86_64: .globl __emutls_v.external_y ; X86_64: .align 8 ; X86_64-LABEL: __emutls_v.external_y: ; X86_64-NEXT: .quad 1 @@ -95,7 +98,8 @@ ; X86_64: .section .rodata, ; X86_64-LABEL: __emutls_t.external_y: ; X86_64-NEXT: .byte 7 -; X86_64: .data +; X86_64: .data{{$}} +; X86_64-NOT: .globl ; X86_64: .align 8 ; X86_64-LABEL: __emutls_v.internal_y: ; X86_64-NEXT: .quad 8