# 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