llvm/lld/test/ELF/ppc64-local-exec-tls.s

// REQUIRES: ppc
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
// RUN: ld.lld  %t.o -o %t
// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s

// RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR

/// Reject local-exec TLS relocations for -shared.
// ERR: error: relocation R_PPC64_TPREL16_HA against a cannot be used with -shared
// ERR: error: relocation R_PPC64_TPREL16_LO against a cannot be used with -shared
// ERR: error: relocation R_PPC64_TPREL16 against b cannot be used with -shared
// ERR: error: relocation R_PPC64_TPREL16_HI against b cannot be used with -shared
// ERR: error: relocation R_PPC64_TPREL16_DS against b cannot be used with -shared
// ERR: error: relocation R_PPC64_TPREL16_LO_DS against b cannot be used with -shared
// ERR: error: relocation R_PPC64_TPREL16_HIGHESTA against b cannot be used with -shared
// ERR: error: relocation R_PPC64_TPREL16_HIGHERA against b cannot be used with -shared

	.text
	.abiversion 2
	.globl	test_local_exec                    # -- Begin function test_local_exec
	.p2align	4
	.type	test_local_exec,@function
test_local_exec:                                   # @test_local_exec
.Lfunc_begin0:
# %bb.0:                                # %entry
	li 3, 0
	stw 3, -12(1)
	addis 3, 13, a@tprel@ha
	addi 3, 3, a@tprel@l
	ld 3, 0(3)
	mr 4, 3
	extsw 3, 4
	blr
	.long	0
	.quad	0
.Lfunc_end0:
	.size	test_local_exec, .Lfunc_end0-.Lfunc_begin0
                                        # -- End function
test_tprel:
.Lfunc_gep1:
  addis 2, 12, .TOC.-.Lfunc_gep1@ha
  addi 2, 2, .TOC.-.Lfunc_gep1@l
.Lfunc_lep1:
  .localentry test_tprel, .Lfunc_lep1-.Lfunc_gep1
  addi 3, 13, b@tprel
  blr


test_hi:
.Lfunc_gep2:
  addis 2, 12, .TOC.-.Lfunc_gep2@ha
  addi  2, 2,  .TOC.-.Lfunc_gep2@l
.Lfunc_lep2:
  .localentry test_hi, .Lfunc_lep2-.Lfunc_gep2
  addis 3, 13, b@tprel@h
  blr

test_ds:
.Lfunc_gep3:
  addis 2, 12, .TOC.-.Lfunc_gep3@ha
  addi 2, 2, .TOC.-.Lfunc_gep3@l
.Lfunc_lep3:
  .localentry test_ds, .Lfunc_lep3-.Lfunc_gep3
  ld 3, b@tprel, 13
  blr

test_lo_ds:
.Lfunc_gep4:
  addis 2, 12, .TOC.-.Lfunc_gep4@ha
  addi 2, 2, .TOC.-.Lfunc_gep4@l
.Lfunc_lep4:
  .localentry test_lo_ds, .Lfunc_lep4-.Lfunc_gep4
  ld 3, b@tprel@l, 13
  blr

test_highest_a:
.Lfunc_gep5:
  addis 2, 12, .TOC.-.Lfunc_gep5@ha
  addi  2, 2,  .TOC.-.Lfunc_gep5@l
.Lfunc_lep5:
  .localentry test_highest_a, .Lfunc_lep5-.Lfunc_gep5
  lis 4, b@tprel@highesta
  ori 4, 4, b@tprel@highera
  lis 5, b@tprel@ha
  addi 5, 5, b@tprel@l
  sldi 4, 4, 32
  or   4, 4, 5
  add  3, 13, 4
  blr

test_highest:
.Lfunc_gep6:
  addis 2, 12, .TOC.-.Lfunc_gep6@ha
  addi  2, 2,  .TOC.-.Lfunc_gep6@l
.Lfunc_lep6:
  .localentry test_highest, .Lfunc_lep6-.Lfunc_gep6
  lis 4, b@tprel@highest
  ori 4, 4, b@tprel@higher
  sldi 4, 4, 32
  oris  4, 4, b@tprel@h
  ori   4, 4, b@tprel@l
  add  3, 13, 4
  blr

	.type	a,@object               # @a
	.type	b,@object               # @b
	.section	.tdata,"awT",@progbits
	.p2align	3
a:
	.quad	55                      # 0x37
	.size	a, 8

b:
	.quad	55                      # 0x37
	.size	b, 8

// Verify that the input has every initial-exec tls relocation type.
// InputRelocs: Relocation section '.rela.text'
// InputRelocs: R_PPC64_TPREL16_HA {{0+}} a + 0
// InputRelocs: R_PPC64_TPREL16_LO {{0+}} a + 0
// InputRelocs: R_PPC64_TPREL16 {{0+8}} b + 0
// InputRelocs: R_PPC64_TPREL16_HI {{0+8}} b + 0
// InputRelocs: R_PPC64_TPREL16_DS {{0+8}} b + 0
// InputRelocs: R_PPC64_TPREL16_LO_DS {{0+8}} b + 0
// InputRelocs: R_PPC64_TPREL16_HIGHESTA {{0+8}} b + 0
// InputRelocs: R_PPC64_TPREL16_HIGHERA {{0+8}} b + 0
// InputRelocs: R_PPC64_TPREL16_HIGHEST {{0+8}} b + 0
// InputRelocs: R_PPC64_TPREL16_HIGHER {{0+8}} b + 0

// The start of the TLS storage area is 0x7000 bytes before the thread pointer (r13).
// We are building the address of the first TLS variable, relative to the thread pointer.
// #ha(a@tprel) --> (0 - 0x7000 + 0x8000) >> 16 = 0
// #lo(a@tprel)) --> (0 - 0x7000) &  0xFFFF =  -0x7000 = -28672
// Dis: <test_local_exec>:
// Dis: addis 3, 13, 0
// Dis: addi 3, 3, -28672

// We are building the offset for the second TLS variable
// Offset within tls storage - 0x7000
// b@tprel = 8 - 0x7000 = 28664
// Dis: <test_tprel>:
// Dis: addi 3, 13, -28664

// #hi(b@tprel) --> (8 - 0x7000) >> 16 = -1
// Dis: <test_hi>:
// Dis: addis 3, 13, -1

// b@tprel = 8 - 0x7000 = -28664
// Dis: <test_ds>:
// Dis: ld 3, -28664(13)

// #lo(b@tprel) --> (8 - 0x7000) & 0xFFFF = -28664
// Dis: <test_lo_ds>:
// Dis: ld 3, -28664(13)

// #highesta(b@tprel) --> ((0x8 - 0x7000 + 0x8000) >> 48) & 0xFFFF = 0
// #highera(b@tprel)  --> ((0x8 - 0x7000 + 0x8000) >> 32) & 0xFFFF = 0
// #ha(k@dtprel)       --> ((0x8 - 0x7000 + 0x8000) >> 16) & 0xFFFF = 0
// #lo(k@dtprel)       --> ((0x8 - 0x7000) & 0xFFFF = -28664
// Dis: <test_highest_a>:
// Dis: lis 4, 0
// Dis: ori 4, 4, 0
// Dis: lis 5, 0
// Dis: addi 5, 5, -28664

// #highest(b@tprel) --> ((0x8 - 0x7000) >> 48) & 0xFFFF = 0xFFFF = -1
// #higher(b@tprel)  --> ((0x8 - 0x7000) >> 32) & 0xFFFF = 0xFFFF = 65535
// #hi(k@dtprel)      --> ((0x8 - 0x7000) >> 16) & 0xFFFF = 0xFFFF = 65535
// #lo(k@dtprel)      --> ((0x8 - 0x7000) & 0xFFFF = 33796
// Dis: <test_highest>:
// Dis: lis 4, -1
// Dis: ori 4, 4, 65535
// Dis: oris 4, 4, 65535
// Dis: ori 4, 4, 36872