# REQUIRES: aarch64
# RUN: rm -rf %t && split-file %s %t

# RUN: llvm-mc -filetype=obj -triple=aarch64 %t/a.s -o %t/a.o
# RUN: llvm-mc -filetype=obj -triple=aarch64 %t/unpaired.s -o %t/unpaired.o
# RUN: llvm-mc -filetype=obj -triple=aarch64 %t/lone-ldr.s -o %t/lone-ldr.o

# RUN: ld.lld %t/a.o -T %t/out-of-adr-range.t -o %t/a
# RUN: llvm-objdump --no-show-raw-insn -d %t/a | FileCheck %s

## Symbol 'x' is nonpreemptible, the relaxation should be applied.
## This test verifies the encoding when the register x1 is used.
# CHECK:      adrp   x1
# CHECK-NEXT: add    x1, x1

## ADRP contains a nonzero addend, no relaxations should be applied.
# CHECK-NEXT: adrp   x2
# CHECK-NEXT: ldr

## LDR contains a nonzero addend, no relaxations should be applied.
# CHECK-NEXT: adrp   x3
# CHECK-NEXT: ldr

## LDR and ADRP use different registers, no relaxations should be applied.
# CHECK-NEXT: adrp   x4
# CHECK-NEXT: ldr

## LDR and ADRP use different registers, no relaxations should be applied.
# CHECK-NEXT: adrp   x6
# CHECK-NEXT: ldr

# RUN: ld.lld %t/a.o -T %t/within-adr-range.t -o %t/a
# RUN: llvm-objdump --no-show-raw-insn -d %t/a | FileCheck --check-prefix=ADR %s

## Symbol 'x' is nonpreemptible, the relaxation should be applied.
# ADR:        nop
# ADR-NEXT:   adr    x1

## Symbol 'x' is nonpreemptible, but --no-relax surpresses relaxations.
# RUN: ld.lld %t/a.o -T %t/out-of-adr-range.t --no-relax -o %t/no-relax
# RUN: llvm-objdump --no-show-raw-insn -d %t/no-relax | \
# RUN:   FileCheck --check-prefix=X1-NO-RELAX %s

# X1-NO-RELAX:      adrp   x1
# X1-NO-RELAX-NEXT: ldr

## Symbol 'x' is nonpreemptible, but the address is not within adrp range.
# RUN: ld.lld %t/a.o -T %t/out-of-range.t -o %t/out-of-range
# RUN: llvm-objdump --no-show-raw-insn -d %t/out-of-range | \
# RUN:   FileCheck --check-prefix=X1-NO-RELAX %s

## Relocations do not appear in pairs, no relaxations should be applied.
# RUN: ld.lld %t/unpaired.o -o %t/unpaired
# RUN: llvm-objdump --no-show-raw-insn -d %t/unpaired | \
# RUN:   FileCheck --check-prefix=UNPAIRED %s

# UNPAIRED:         adrp   x0
# UNPAIRED-NEXT:    b
# UNPAIRED-NEXT:    adrp   x0
# UNPAIRED:         ldr	   x0

## Relocations do not appear in pairs, no relaxations should be applied.
# RUN: ld.lld %t/lone-ldr.o -o %t/lone-ldr
# RUN: llvm-objdump --no-show-raw-insn -d %t/lone-ldr | \
# RUN:   FileCheck --check-prefix=LONE-LDR %s

# LONE-LDR:         ldr	   x0

## This linker script ensures that .rodata and .text are sufficiently (>1M)
## far apart so that the adrp + ldr pair cannot be relaxed to adr + nop.
#--- out-of-adr-range.t
SECTIONS {
 .rodata 0x1000: { *(.rodata) }
 .text   0x200100: { *(.text) }
}

## This linker script ensures that .rodata and .text are sufficiently (<1M)
## close to each other so that the adrp + ldr pair can be relaxed to nop + adr.
#--- within-adr-range.t
SECTIONS {
 .rodata 0x1000: { *(.rodata) }
 .text   0x2000: { *(.text) }
}

## This linker script ensures that .rodata and .text are sufficiently (>4GB)
## far apart so that the adrp + ldr pair cannot be relaxed.
#--- out-of-range.t
SECTIONS {
 .rodata 0x1000: { *(.rodata) }
 .text   0x100002000: { *(.text) }
}

#--- a.s
.rodata
.hidden x
x:
.word 10
.text
.global _start
_start:
  adrp    x1, :got:x
  ldr     x1, [x1, #:got_lo12:x]
  adrp    x2, :got:x+1
  ldr     x2, [x2, #:got_lo12:x]
  adrp    x3, :got:x
  ldr     x3, [x3, #:got_lo12:x+8]
  adrp    x4, :got:x
  ldr     x5, [x4, #:got_lo12:x]
  adrp    x6, :got:x
  ldr     x6, [x0, #:got_lo12:x]

#--- unpaired.s
.text
.hidden x
x:
  nop
.global _start
_start:
  adrp    x0, :got:x
  b L
  adrp    x0, :got:x
L:
  ldr     x0, [x0, #:got_lo12:x]

#--- lone-ldr.s
.text
.hidden x
x:
  nop
.global _start
_start:
  ldr     x0, [x0, #:got_lo12:x]
