# RUN: rm -rf %t && mkdir -p %t
# RUN: llvm-mc -triple=x86_64-unknown-linux -position-independent -filetype=obj -o %t/elf_reloc.o %s
# RUN: llvm-jitlink -noexec -slab-allocate 100Kb -slab-address 0xfff00000 \
# RUN:              -define-abs external_data=0x1 \
# RUN:              -define-abs extern_in_range32=0xffe00000 \
# RUN:              -define-abs extern_out_of_range32=0x7fff00000000 \
# RUN:              -check %s %t/elf_reloc.o
#
# Test standard ELF relocations.

        .text
        .file   "testcase.c"

# Empty main entry point.
        .globl  main
        .p2align        4, 0x90
        .type   main,@function
main:
        retq

        .size   main, .-main

# Test PCRel32 / R_X86_64_PC32 handling.
# jitlink-check: decode_operand(test_pcrel32, 4) = named_data - next_pc(test_pcrel32)
        .globl  test_pcrel32
        .p2align       4, 0x90
        .type   test_pcrel32,@function
test_pcrel32:
        movl    named_data(%rip), %eax

         .size   test_pcrel32, .-test_pcrel32

        .globl  named_func
        .p2align       4, 0x90
        .type   named_func,@function
named_func:
        xorq    %rax, %rax

        .size   named_func, .-named_func

# Check R_X86_64_PLT32 handling with a call to a local function. This produces a
# Branch32 edge that is resolved like a regular PCRel32 (no PLT entry created).
#
# jitlink-check: decode_operand(test_call_local, 0) = named_func - next_pc(test_call_local)
        .globl  test_call_local
        .p2align       4, 0x90
        .type   test_call_local,@function
test_call_local:
        callq   named_func

        .size   test_call_local, .-test_call_local

# Check R_X86_64_PLT32 handling with a call to an external. This produces a
# Branch32ToStub edge, because externals are not defined locally. During
# resolution, the target turns out to be in-range from the callsite and so the
# edge is relaxed in post-allocation optimization.
#
# jitlink-check: decode_operand(test_call_extern, 0) = extern_in_range32 - next_pc(test_call_extern)
        .globl  test_call_extern
        .p2align       4, 0x90
        .type   test_call_extern,@function
test_call_extern:
        callq   extern_in_range32@plt

        .size   test_call_extern, .-test_call_extern

# Check R_X86_64_PLT32 handling with a call to an external via PLT. This
# produces a Branch32ToStub edge, because externals are not defined locally.
# As the target is out-of-range from the callsite, the edge keeps using its PLT
# entry.
#
# jitlink-check: decode_operand(test_call_extern_plt, 0) = \
# jitlink-check:     stub_addr(elf_reloc.o, extern_out_of_range32) - next_pc(test_call_extern_plt)
# jitlink-check: *{8}(got_addr(elf_reloc.o, extern_out_of_range32)) = extern_out_of_range32
        .globl  test_call_extern_plt
        .p2align       4, 0x90
        .type   test_call_extern_plt,@function
test_call_extern_plt:
        callq   extern_out_of_range32@plt

        .size   test_call_extern_plt, .-test_call_extern_plt

# Test GOTPCREL handling. We want to check both the offset to the GOT entry and its
# contents.
# jitlink-check: decode_operand(test_gotpcrel, 4) = got_addr(elf_reloc.o, named_data) - next_pc(test_gotpcrel)
# jitlink-check: *{8}(got_addr(elf_reloc.o, named_data)) = named_data

        .globl test_gotpcrel
        .p2align      4, 0x90
        .type   test_gotpcrel,@function
test_gotpcrel:
	movl    named_data@GOTPCREL(%rip), %eax

        .size   test_gotpcrel, .-test_gotpcrel

# Test REX_GOTPCRELX handling. We want to check both the offset to the GOT entry and its
# contents.
# jitlink-check: decode_operand(test_rex_gotpcrelx, 4) = \
# jitlink-check:   got_addr(elf_reloc.o, external_data) - next_pc(test_rex_gotpcrelx)

        .globl test_rex_gotpcrelx
        .p2align      4, 0x90
        .type   test_rex_gotpcrelx,@function
test_rex_gotpcrelx:
	movq    external_data@GOTPCREL(%rip), %rax

        .size   test_rex_gotpcrelx, .-test_rex_gotpcrelx

        .type   named_data,@object
        .data
        .p2align        3
named_data:
        .quad   42
        .size   named_data, 8

# Test BSS / zero-fill section handling.
# llvm-jitlink: *{4}bss_variable = 0

	.type	bss_variable,@object
	.bss
	.globl	bss_variable
	.p2align	2
bss_variable:
	.long	0
	.size	bss_variable, 4

        .ident  "clang version 10.0.0-4ubuntu1 "
        .section        ".note.GNU-stack","",@progbits
        .addrsig
