# REQUIRES: riscv
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=riscv64 a.s -o a.64.o
# RUN: llvm-mc -filetype=obj -triple=riscv64 c.s -o c.64.o
# RUN: ld.lld -shared -soname=c.64.so c.64.o -o c.64.so
# RUN: llvm-mc -filetype=obj -triple=riscv32 --defsym ELF32=1 a.s -o a.32.o
# RUN: llvm-mc -filetype=obj -triple=riscv32 --defsym ELF32=1 c.s -o c.32.o
# RUN: ld.lld -shared -soname=c.32.so c.32.o -o c.32.so

# RUN: ld.lld -shared -z now a.64.o c.64.o -o a.64.so
# RUN: llvm-readobj -r -x .got a.64.so | FileCheck --check-prefix=GD64-RELA %s
# RUN: llvm-objdump --no-show-raw-insn -M no-aliases -h -d a.64.so | FileCheck %s --check-prefix=GD64

# RUN: ld.lld -shared -z now a.64.o c.64.o -o rel.64.so -z rel
# RUN: llvm-readobj -r -x .got rel.64.so | FileCheck --check-prefix=GD64-REL %s

# RUN: ld.lld -e 0 -z now a.64.o c.64.o -o a.64.le
# RUN: llvm-readelf -r a.64.le | FileCheck --check-prefix=NOREL %s
# RUN: llvm-objdump --no-show-raw-insn -M no-aliases -h -d a.64.le | FileCheck %s --check-prefix=LE64

# RUN: ld.lld -e 0 -z now a.64.o c.64.so -o a.64.ie
# RUN: llvm-readobj -r a.64.ie | FileCheck --check-prefix=IE64-RELA %s
# RUN: llvm-objdump --no-show-raw-insn -M no-aliases -h -d a.64.ie | FileCheck %s --check-prefix=IE64

## 32-bit code is mostly the same. We only test a few variants. The IE optimization uses the LW instruction.

# RUN: ld.lld -shared -z now a.32.o c.32.o -o rel.32.so -z rel
# RUN: llvm-readobj -r -x .got rel.32.so | FileCheck --check-prefix=GD32-REL %s
# RUN: ld.lld -e 0 -z now a.32.o c.32.so -o a.32.ie
# RUN: llvm-objdump --no-show-raw-insn -M no-aliases -h -d a.32.ie | FileCheck %s --check-prefix=IE32

## Prior to https://github.com/llvm/llvm-project/pull/85817 the local TLSDESC
## labels would be marked STT_TLS, resulting in an error "has an STT_TLS symbol but doesn't have an SHF_TLS section"

# RUN: llvm-mc -triple=riscv64 -filetype=obj d.s -o d.64.o
# RUN: ld.lld -shared -soname=d.64.so -o d.64.so d.64.o --fatal-warnings
# RUN: llvm-mc -triple=riscv32 -filetype=obj d.s -o d.32.o --defsym ELF32=1
# RUN: ld.lld -shared -soname=d.32.so -o d.32.so d.32.o --fatal-warnings

## The output has a TLS reference but no TLS section.
# RUN: llvm-mc -filetype=obj -triple=riscv64 a1.s -o a1.64.o
# RUN: ld.lld -pie a1.64.o c.64.so -o a1.64
# RUN: llvm-objdump --no-show-raw-insn -M no-aliases -Rd a1.64 | FileCheck %s --check-prefix=IE64A

# GD64-RELA:      .rela.dyn {
# GD64-RELA-NEXT:   0x2408 R_RISCV_TLSDESC - 0x7FF
# GD64-RELA-NEXT:   0x23E8 R_RISCV_TLSDESC a 0x0
# GD64-RELA-NEXT:   0x23F8 R_RISCV_TLSDESC c 0x0
# GD64-RELA-NEXT: }
# GD64-RELA:      Hex dump of section '.got':
# GD64-RELA-NEXT: 0x000023e0 20230000 00000000 00000000 00000000 #
# GD64-RELA-NEXT: 0x000023f0 00000000 00000000 00000000 00000000 .

# GD64-REL:      .rel.dyn {
# GD64-REL-NEXT:   0x23F0 R_RISCV_TLSDESC -
# GD64-REL-NEXT:   0x23D0 R_RISCV_TLSDESC a
# GD64-REL-NEXT:   0x23E0 R_RISCV_TLSDESC c
# GD64-REL-NEXT: }
# GD64-REL:      Hex dump of section '.got':
# GD64-REL-NEXT: 0x000023c8 08230000 00000000 00000000 00000000 .
# GD64-REL-NEXT: 0x000023d8 00000000 00000000 00000000 00000000 .
# GD64-REL-NEXT: 0x000023e8 00000000 00000000 00000000 00000000 .
# GD64-REL-NEXT: 0x000023f8 ff070000 00000000                   .

# GD32-REL:      .rel.dyn {
# GD32-REL-NEXT:   0x2274 R_RISCV_TLSDESC -
# GD32-REL-NEXT:   0x2264 R_RISCV_TLSDESC a
# GD32-REL-NEXT:   0x226C R_RISCV_TLSDESC c
# GD32-REL-NEXT: }
# GD32-REL:      Hex dump of section '.got':
# GD32-REL-NEXT: 0x00002260 00220000 00000000 00000000 00000000 .
# GD32-REL-NEXT: 0x00002270 00000000 00000000 ff070000          .

# GD64:      .got     00000038 00000000000023e0

## &.got[a]-. = 0x23e0+8 - 0x12e0 = 0x1108
# GD64:        12e0: auipc   a0, 0x1
# GD64-NEXT:         ld      a1, 0x108(a0)
# GD64-NEXT:         addi    a0, a0, 0x108
# GD64-NEXT:         jalr    t0, 0x0(a1)
# GD64-NEXT:         add     a0, a0, tp

## &.got[b]-. = 0x23e0+40 - 0x12f4 = 0x1114
# GD64:        12f4: auipc   a2, 0x1
# GD64-NEXT:         ld      a3, 0x114(a2)
# GD64-NEXT:         addi    a0, a2, 0x114
# GD64-NEXT:         jalr    t0, 0x0(a3)
# GD64-NEXT:         add     a0, a0, tp

## &.got[c]-. = 0x23e0+24 - 0x1308 = 0x10f0
# GD64:        1308: auipc   a4, 0x1
# GD64-NEXT:         ld      a5, 0xf0(a4)
# GD64-NEXT:         addi    a0, a4, 0xf0
# GD64-NEXT:         jalr    t0, 0x0(a5)
# GD64-NEXT:         add     a0, a0, tp

# NOREL: no relocations

# LE64-LABEL: <.Ltlsdesc_hi0>:
## st_value(a) = 8
# LE64-NEXT:         addi    zero, zero, 0x0
# LE64-NEXT:         addi    zero, zero, 0x0
# LE64-NEXT:         addi    zero, zero, 0x0
# LE64-NEXT:         addi    a0, zero, 0x8
# LE64-NEXT:         add     a0, a0, tp
## st_value(b) = 2047
# LE64-LABEL: <.Ltlsdesc_hi1>:
# LE64-NEXT:         addi    zero, zero, 0x0
# LE64-NEXT:         addi    zero, zero, 0x0
# LE64-NEXT:         addi    zero, zero, 0x0
# LE64-NEXT:         addi    a0, zero, 0x7ff
# LE64-NEXT:         add     a0, a0, tp
## st_value(c) = 2048
# LE64-LABEL: <.Ltlsdesc_hi2>:
# LE64-NEXT:         addi    zero, zero, 0x0
# LE64-NEXT:         addi    zero, zero, 0x0
# LE64-NEXT:         lui     a0, 0x1
# LE64-NEXT:         addi    a0, a0, -0x800
# LE64-NEXT:         add     a0, a0, tp

# IE64-RELA:      .rela.dyn {
# IE64-RELA-NEXT:   0x123B0 R_RISCV_TLS_TPREL64 c 0x0
# IE64-RELA-NEXT: }

# IE64:       .got     00000010 00000000000123a8

## a and b are optimized to use LE. c is optimized to IE.
# IE64-LABEL: <.Ltlsdesc_hi0>:
# IE64-NEXT:         addi    zero, zero, 0x0
# IE64-NEXT:         addi    zero, zero, 0x0
# IE64-NEXT:         addi    zero, zero, 0x0
# IE64-NEXT:         addi    a0, zero, 0x8
# IE64-NEXT:         add     a0, a0, tp
# IE64-LABEL: <.Ltlsdesc_hi1>:
# IE64-NEXT:         addi    zero, zero, 0x0
# IE64-NEXT:         addi    zero, zero, 0x0
# IE64-NEXT:         addi    zero, zero, 0x0
# IE64-NEXT:         addi    a0, zero, 0x7ff
# IE64-NEXT:         add     a0, a0, tp
## &.got[c]-. = 0x123a8+8 - 0x112b8 = 0x10f8
# IE64-LABEL: <.Ltlsdesc_hi2>:
# IE64-NEXT:         addi    zero, zero, 0x0
# IE64-NEXT:         addi    zero, zero, 0x0
# IE64-NEXT:  112b8: auipc   a0, 0x1
# IE64-NEXT:         ld      a0, 0xf8(a0)
# IE64-NEXT:         add     a0, a0, tp

# IE32:       .got     00000008 00012248

# IE32-LABEL: <.Ltlsdesc_hi0>:
## st_value(a) = 8
# IE32-NEXT:         addi    zero, zero, 0x0
# IE32-NEXT:         addi    zero, zero, 0x0
# IE32-NEXT:         addi    zero, zero, 0x0
# IE32-NEXT:         addi    a0, zero, 0x8
# IE32-NEXT:         add     a0, a0, tp
## st_value(b) = 2047
# IE32-LABEL: <.Ltlsdesc_hi1>:
# IE32-NEXT:         addi    zero, zero, 0x0
# IE32-NEXT:         addi    zero, zero, 0x0
# IE32-NEXT:         addi    zero, zero, 0x0
# IE32-NEXT:         addi    a0, zero, 0x7ff
# IE32-NEXT:         add     a0, a0, tp
## &.got[c]-. = 0x12248+4 - 0x111cc = 0x1080
# IE32-LABEL: <.Ltlsdesc_hi2>:
# IE32-NEXT:         addi    zero, zero, 0x0
# IE32-NEXT:         addi    zero, zero, 0x0
# IE32-NEXT:  111cc: auipc   a0, 0x1
# IE32-NEXT:         lw      a0, 0x80(a0)
# IE32-NEXT:         add     a0, a0, tp

# IE64A:       OFFSET           TYPE                     VALUE
# IE64A-NEXT:  0000000000002340 R_RISCV_TLS_TPREL64      c
# IE64A-EMPTY:
## &.got[c]-. = 0x2340 - 0x1258 = 0x10e8
# IE64A-LABEL: <.Ltlsdesc_hi2>:
# IE64A-NEXT:         addi    zero, zero, 0x0
# IE64A-NEXT:         addi    zero, zero, 0x0
# IE64A-NEXT:   1258: auipc   a0, 0x1
# IE64A-NEXT:         ld      a0, 0xe8(a0)
# IE64A-NEXT:         add     a0, a0, tp

#--- a.s
.macro load dst, src
.ifdef ELF32
lw \dst, \src
.else
ld \dst, \src
.endif
.endm

.Ltlsdesc_hi0:
  auipc a0, %tlsdesc_hi(a)
  load  a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
  addi  a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
  jalr  t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
  add   a0, a0, tp

.Ltlsdesc_hi1:
  auipc a2, %tlsdesc_hi(b)
  load  a3, %tlsdesc_load_lo(.Ltlsdesc_hi1)(a2)
  addi  a0, a2, %tlsdesc_add_lo(.Ltlsdesc_hi1)
  jalr  t0, 0(a3), %tlsdesc_call(.Ltlsdesc_hi1)
  add   a0, a0, tp

.Ltlsdesc_hi2:
  auipc a4, %tlsdesc_hi(c)
  load  a5, %tlsdesc_load_lo(.Ltlsdesc_hi2)(a4)
  addi  a0, a4, %tlsdesc_add_lo(.Ltlsdesc_hi2)
  jalr  t0, 0(a5), %tlsdesc_call(.Ltlsdesc_hi2)
  add   a0, a0, tp

.section .tbss
.globl a
.zero 8
a:
.zero 2039  ## Place b at 0x7ff
b:
.zero 1

#--- a1.s
## a.s without TLS definitions.
.Ltlsdesc_hi2:
  auipc a4, %tlsdesc_hi(c)
  ld    a5, %tlsdesc_load_lo(.Ltlsdesc_hi2)(a4)
  addi  a0, a4, %tlsdesc_add_lo(.Ltlsdesc_hi2)
  jalr  t0, 0(a5), %tlsdesc_call(.Ltlsdesc_hi2)
  add   a0, a0, tp

#--- c.s
.tbss
.globl c
c: .zero 4

#--- d.s
.macro load dst, src
.ifdef ELF32
lw \dst, \src
.else
ld \dst, \src
.endif
.endm

.Ltlsdesc_hi0:
  auipc	a0, %tlsdesc_hi(foo)
  load	a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
  addi	a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
  jalr	t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
  add	a1, a0, tp
