315 lines
7.1 KiB
ArmAsm
315 lines
7.1 KiB
ArmAsm
# RUN: llvm-mc -triple=powerpc64le-unknown-linux-gnu -filetype=obj -o %t %s \
|
|
# RUN: --defsym LE=1
|
|
# RUN: llvm-jitlink -abs external_var=0xffff0000 -abs puts=0xffff6400 -abs \
|
|
# RUN: foo=0xffff8800 -abs low_addr=0x0320 -noexec %t
|
|
# RUN: llvm-mc -triple=powerpc64-unknown-linux-gnu -filetype=obj -o %t %s
|
|
# RUN: llvm-jitlink -abs external_var=0xffff0000 -abs puts=0xffff6400 -abs \
|
|
# RUN: foo=0xffff8800 -abs low_addr=0x0320 -noexec %t
|
|
#
|
|
# Check typical relocations involving external function call, external variable
|
|
# reference, local function call and referencing global variable defined in the
|
|
# same CU. This test serves as smoke test, `llvm-jitlink -check` is not used.
|
|
|
|
.text
|
|
.abiversion 2
|
|
.file "ppc64-relocs.c"
|
|
.globl main
|
|
.p2align 4
|
|
.type main,@function
|
|
main:
|
|
.Lfunc_begin0:
|
|
li 3, 0
|
|
blr
|
|
.long 0
|
|
.quad 0
|
|
.Lfunc_end0:
|
|
.size main, .Lfunc_end0-.Lfunc_begin0
|
|
|
|
.globl id
|
|
.p2align 4
|
|
.type id,@function
|
|
id:
|
|
.Lfunc_begin1:
|
|
.Lfunc_gep1:
|
|
addis 2, 12, .TOC.-.Lfunc_gep1@ha
|
|
addi 2, 2, .TOC.-.Lfunc_gep1@l
|
|
.Lfunc_lep1:
|
|
.localentry id, .Lfunc_lep1-.Lfunc_gep1
|
|
addis 4, 2, .LC0@toc@ha
|
|
ld 4, .LC0@toc@l(4)
|
|
lwz 4, 0(4)
|
|
sub 3, 4, 3
|
|
extsw 3, 3
|
|
blr
|
|
.long 0
|
|
.quad 0
|
|
.Lfunc_end1:
|
|
.size id, .Lfunc_end1-.Lfunc_begin1
|
|
|
|
# Test referencing external data via R_PPC64_TOC16HA and R_PPC64_TOC16LO.
|
|
.globl test_reference_external_data
|
|
.p2align 4
|
|
.type test_reference_external_data,@function
|
|
test_reference_external_data:
|
|
.Lfunc_begin2:
|
|
.Lfunc_gep2:
|
|
addis 2, 12, .TOC.-.Lfunc_gep2@ha
|
|
addi 2, 2, .TOC.-.Lfunc_gep2@l
|
|
.Lfunc_lep2:
|
|
.localentry test_reference_external_data, .Lfunc_lep2-.Lfunc_gep2
|
|
addis 3, 2, .LC0@toc@ha
|
|
ld 3, .LC0@toc@l(3)
|
|
blr
|
|
.long 0
|
|
.quad 0
|
|
.Lfunc_end2:
|
|
.size test_reference_external_data, .Lfunc_end2-.Lfunc_begin2
|
|
|
|
# Test referencing global variable defined in the same CU.
|
|
.globl test_reference_local_data
|
|
.p2align 4
|
|
.type test_reference_local_data,@function
|
|
test_reference_local_data:
|
|
.Lfunc_begin3:
|
|
.Lfunc_gep3:
|
|
addis 2, 12, .TOC.-.Lfunc_gep3@ha
|
|
addi 2, 2, .TOC.-.Lfunc_gep3@l
|
|
.Lfunc_lep3:
|
|
.localentry test_reference_local_data, .Lfunc_lep3-.Lfunc_gep3
|
|
addis 3, 2, .LC1@toc@ha
|
|
ld 3, .LC1@toc@l(3)
|
|
blr
|
|
.long 0
|
|
.quad 0
|
|
.Lfunc_end3:
|
|
.size test_reference_local_data, .Lfunc_end3-.Lfunc_begin3
|
|
|
|
# Test external function call with R_PPC64_REL24, which requires PLT
|
|
# call stub.
|
|
.globl test_external_call
|
|
.p2align 4
|
|
.type test_external_call,@function
|
|
test_external_call:
|
|
.Lfunc_begin4:
|
|
.Lfunc_gep4:
|
|
addis 2, 12, .TOC.-.Lfunc_gep4@ha
|
|
addi 2, 2, .TOC.-.Lfunc_gep4@l
|
|
.Lfunc_lep4:
|
|
.localentry test_external_call, .Lfunc_lep4-.Lfunc_gep4
|
|
mflr 0
|
|
stdu 1, -32(1)
|
|
addis 3, 2, .L.str@toc@ha
|
|
std 0, 48(1)
|
|
addi 3, 3, .L.str@toc@l
|
|
bl puts
|
|
nop
|
|
addi 1, 1, 32
|
|
ld 0, 16(1)
|
|
mtlr 0
|
|
blr
|
|
.long 0
|
|
.quad 0
|
|
.Lfunc_end4:
|
|
.size test_external_call, .Lfunc_end4-.Lfunc_begin4
|
|
|
|
# Test local calls with R_PPC64_REL24.
|
|
# Calling to `id` has a nop followed, while there is no
|
|
# nop after calling `id1`.
|
|
.globl test_local_call
|
|
.p2align 4
|
|
.type test_local_call,@function
|
|
test_local_call:
|
|
.Lfunc_begin5:
|
|
.Lfunc_gep5:
|
|
addis 2, 12, .TOC.-.Lfunc_gep5@ha
|
|
addi 2, 2, .TOC.-.Lfunc_gep5@l
|
|
.Lfunc_lep5:
|
|
.localentry test_local_call, .Lfunc_lep5-.Lfunc_gep5
|
|
mflr 0
|
|
std 29, -24(1)
|
|
std 30, -16(1)
|
|
stdu 1, -64(1)
|
|
std 0, 80(1)
|
|
mr 30, 3
|
|
# A local call, with a nop followed.
|
|
bl id
|
|
nop
|
|
mr 29, 3
|
|
mr 3, 30
|
|
# A local call, without nop followed.
|
|
bl id1
|
|
add 3, 3, 29
|
|
extsw 3, 3
|
|
addi 1, 1, 64
|
|
ld 0, 16(1)
|
|
ld 30, -16(1)
|
|
ld 29, -24(1)
|
|
mtlr 0
|
|
blr
|
|
.long 0
|
|
.quad 0
|
|
.Lfunc_end5:
|
|
.size test_local_call, .Lfunc_end5-.Lfunc_begin5
|
|
|
|
.p2align 4
|
|
.type id1,@function
|
|
id1:
|
|
.Lfunc_begin6:
|
|
.Lfunc_gep6:
|
|
addis 2, 12, .TOC.-.Lfunc_gep6@ha
|
|
addi 2, 2, .TOC.-.Lfunc_gep6@l
|
|
.Lfunc_lep6:
|
|
.localentry id1, .Lfunc_lep6-.Lfunc_gep6
|
|
addis 4, 2, .LC1@toc@ha
|
|
ld 4, .LC1@toc@l(4)
|
|
lwz 4, 0(4)
|
|
sub 3, 4, 3
|
|
extsw 3, 3
|
|
blr
|
|
.long 0
|
|
.quad 0
|
|
.Lfunc_end6:
|
|
.size id1, .Lfunc_end6-.Lfunc_begin6
|
|
|
|
# Test external function call with R_PPC64_REL24_NOTOC, which requires PLT
|
|
# call stub, however no saving of r2 is required and there's no nop after
|
|
# the branch instruction.
|
|
.globl bar
|
|
.p2align 4
|
|
.type bar,@function
|
|
bar:
|
|
.Lfunc_begin7:
|
|
.localentry bar, 1
|
|
b foo@notoc
|
|
#TC_RETURNd8 foo@notoc 0
|
|
.long 0
|
|
.quad 0
|
|
.Lfunc_end7:
|
|
.size bar, .Lfunc_end7-.Lfunc_begin7
|
|
|
|
.global foobar
|
|
.p2align 4
|
|
.type foobar,@function
|
|
foobar:
|
|
.Lfunc_begin8:
|
|
.localentry foobar, 1
|
|
paddi 3, 0, .L.str@PCREL, 1
|
|
blr
|
|
.Lfunc_end8:
|
|
.size foobar, .Lfunc_end8-.Lfunc_begin8
|
|
|
|
.global reloc_addr14
|
|
.p2align 4
|
|
.type reloc_addr14,@function
|
|
reloc_addr14:
|
|
.Lfunc_begin9:
|
|
bca 21, 30, low_addr
|
|
.Lfunc_end9:
|
|
.size reloc_addr14, .Lfunc_end9-.Lfunc_begin9
|
|
|
|
.global reloc_half16
|
|
.p2align 4
|
|
.type reloc_half16,@function
|
|
reloc_half16:
|
|
.Lfunc_begin10:
|
|
.ifdef LE
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10, R_PPC64_ADDR16_DS, low_addr
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+4, R_PPC64_ADDR16_LO, low_addr
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+8, R_PPC64_ADDR16_LO_DS, low_addr
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+12, R_PPC64_ADDR16, low_addr
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+16, R_PPC64_ADDR16_HI, low_addr
|
|
.else
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+2, R_PPC64_ADDR16_DS, low_addr
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+6, R_PPC64_ADDR16_LO, low_addr
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+10, R_PPC64_ADDR16_LO_DS, low_addr
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+14, R_PPC64_ADDR16, low_addr
|
|
li 3, 0
|
|
.reloc .Lfunc_begin10+18, R_PPC64_ADDR16_HI, low_addr
|
|
.endif
|
|
li 3, low_addr@ha
|
|
li 3, low_addr@high
|
|
li 3, low_addr@higha
|
|
li 3, low_addr@higher
|
|
li 3, low_addr@highera
|
|
li 3, low_addr@highest
|
|
li 3, low_addr@highesta
|
|
.Ldelta16:
|
|
.ifdef LE
|
|
li 3, 0
|
|
.reloc .Ldelta16, R_PPC64_REL16, reloc_half16
|
|
li 3, 0
|
|
.reloc .Ldelta16+4, R_PPC64_REL16_HI, reloc_half16
|
|
li 3, 0
|
|
.reloc .Ldelta16+8, R_PPC64_REL16_HA, reloc_half16
|
|
li 3, 0
|
|
.reloc .Ldelta16+12, R_PPC64_REL16_LO, reloc_half16
|
|
.else
|
|
li 3, 0
|
|
.reloc .Ldelta16+2, R_PPC64_REL16, reloc_half16
|
|
li 3, 0
|
|
.reloc .Ldelta16+6, R_PPC64_REL16_HI, reloc_half16
|
|
li 3, 0
|
|
.reloc .Ldelta16+10, R_PPC64_REL16_HA, reloc_half16
|
|
li 3, 0
|
|
.reloc .Ldelta16+14, R_PPC64_REL16_LO, reloc_half16
|
|
.endif
|
|
.Ltocdetal16:
|
|
.ifdef LE
|
|
li 3, 0
|
|
.reloc .Ltocdetal16, R_PPC64_TOC16, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+4, R_PPC64_TOC16_HI, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+8, R_PPC64_TOC16_DS, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+12, R_PPC64_TOC16_HA, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+16, R_PPC64_TOC16_LO, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+20, R_PPC64_TOC16_LO_DS, .L.str
|
|
.else
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+2, R_PPC64_TOC16, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+6, R_PPC64_TOC16_HI, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+10, R_PPC64_TOC16_DS, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+14, R_PPC64_TOC16_HA, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+18, R_PPC64_TOC16_LO, .L.str
|
|
li 3, 0
|
|
.reloc .Ltocdetal16+22, R_PPC64_TOC16_LO_DS, .L.str
|
|
.endif
|
|
blr
|
|
.Lfunc_end10:
|
|
.size reloc_half16, .Lfunc_end10-.Lfunc_begin10
|
|
|
|
.type local_var,@object
|
|
.section .bss,"aw",@nobits
|
|
.globl local_var
|
|
.p2align 2, 0x0
|
|
local_var:
|
|
.long 0
|
|
.size local_var, 4
|
|
|
|
.type .L.str,@object
|
|
.section .rodata.str1.1,"aMS",@progbits,1
|
|
.L.str:
|
|
.asciz "Hey!"
|
|
.size .L.str, 5
|
|
|
|
.section .toc,"aw",@progbits
|
|
.LC0:
|
|
.tc external_var[TC],external_var
|
|
.LC1:
|
|
.tc local_var[TC],local_var
|