Index: lld/trunk/ELF/Arch/PPC64.cpp =================================================================== --- lld/trunk/ELF/Arch/PPC64.cpp +++ lld/trunk/ELF/Arch/PPC64.cpp @@ -200,6 +200,7 @@ void writeGotHeader(uint8_t *Buf) const override; bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, uint64_t BranchAddr, const Symbol &S) const override; + uint32_t getThunkSectionSpacing() const override; bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, RelExpr Expr) const override; @@ -885,6 +886,14 @@ getPPC64GlobalEntryToLocalEntryOffset(S.StOther)); } +uint32_t PPC64::getThunkSectionSpacing() const { + // See comment in Arch/ARM.cpp for a more detailed explanation of + // getThunkSectionSpacing(). For PPC64 we pick the constant here based on + // R_PPC64_REL24, which is used by unconditional branch instructions. + // 0x2000000 = (1 << 24-1) * 4 + return 0x2000000; +} + bool PPC64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { int64_t Offset = Dst - Src; if (Type == R_PPC64_REL14) Index: lld/trunk/test/ELF/ppc64-bsymbolic-toc-restore.s =================================================================== --- lld/trunk/test/ELF/ppc64-bsymbolic-toc-restore.s +++ lld/trunk/test/ELF/ppc64-bsymbolic-toc-restore.s @@ -53,7 +53,7 @@ # CHECK-LABEL: caller # CHECK: bl .+44 # CHECK-NEXT: mr 31, 3 -# CHECK-NEXT: bl .-48 +# CHECK-NEXT: bl .+44 # CHECK-NEXT: ld 2, 24(1) # CHECK-NEXT: add 3, 3, 31 # CHECK-NEXT: addi 1, 1, 32 @@ -63,6 +63,6 @@ # CHECK-EMPTY: # CHECK-NEXT: def: # CHECK-NEXT: addis 2, 12, 2 -# CHECK-NEXT: addi 2, 2, -32636 +# CHECK-NEXT: addi 2, 2, -32616 # CHECK-NEXT: li 3, 55 # CHECK-NEXT: blr Index: lld/trunk/test/ELF/ppc64-call-reach.s =================================================================== --- lld/trunk/test/ELF/ppc64-call-reach.s +++ lld/trunk/test/ELF/ppc64-call-reach.s @@ -65,27 +65,24 @@ # NEGOFFSET: 10010014: bl .-33554432 # NEGOFFSET: 10010024: b .+33554432 +# THUNK-LABEL: test: +# THUNK: 10010014: bl .+20 +# THUNK: 10010024: b .+20 + # .branch_lt[0] # THUNK-LABEL: __long_branch_callee: -# THUNK-NEXT: 10010000: addis 12, 2, 1 +# THUNK-NEXT: 10010028: addis 12, 2, 1 # THUNK-NEXT: ld 12, -32768(12) # THUNK-NEXT: mtctr 12 # THUNK-NEXT: bctr # .branch_lt[1] # THUNK-LABEL: __long_branch_tail_callee: -# THUNK-NEXT: 10010010: addis 12, 2, 1 +# THUNK-NEXT: 10010038: addis 12, 2, 1 # THUNK-NEXT: ld 12, -32760(12) # THUNK-NEXT: mtctr 12 # THUNK-NEXT: bctr -# Each call now branches to a thunk, and although it is printed as positive -# the offset is interpreted as a signed 26 bit value so 67108812 is actually -# -52. -# THUNK-LABEL: test: -# THUNK: 10010034: bl .-52 -# THUNK: 10010044: b .+67108812 - # The offset from the TOC to the .branch_lt section is (-1 << 16) - 32768. # Name Type Address Off Size # BRANCHLT: .got PROGBITS 0000000010020000 020000 000008 Index: lld/trunk/test/ELF/ppc64-ifunc.s =================================================================== --- lld/trunk/test/ELF/ppc64-ifunc.s +++ lld/trunk/test/ELF/ppc64-ifunc.s @@ -15,11 +15,21 @@ # RUN: llvm-readelf -r %t | FileCheck --check-prefix=DYNREL %s # NM-DAG: 0000000010028000 d .TOC. -# NM-DAG: 0000000010010028 T ifunc -# NM-DAG: 000000001001002c T ifunc2 +# NM-DAG: 0000000010010000 T ifunc +# NM-DAG: 0000000010010004 T ifunc2 # SECTIONS: .plt NOBITS 0000000010030000 +# __plt_ifunc - . = 0x10010020 - 0x10010010 = 16 +# __plt_ifunc2 - . = 0x10010044 - 0x10010018 = 28 +# CHECK: _start: +# CHECK-NEXT: addis 2, 12, 1 +# CHECK-NEXT: addi 2, 2, 32760 +# CHECK-NEXT: 10010010: bl .+16 +# CHECK-NEXT: ld 2, 24(1) +# CHECK-NEXT: 10010018: bl .+28 +# CHECK-NEXT: ld 2, 24(1) + # .plt[0] - .TOC. = 0x10030000 - 0x10028000 = (1<<16) - 32768 # CHECK: __plt_ifunc: # CHECK-NEXT: std 2, 24(1) @@ -36,19 +46,9 @@ # CHECK-NEXT: mtctr 12 # CHECK-NEXT: bctr -# __plt_ifunc - . = 0x10010000 - 0x10010038 = -56 -# __plt_ifunc2 - . = 0x10010014 - 0x10010040 = -44 -# CHECK: _start: -# CHECK-NEXT: addis 2, 12, 1 -# CHECK-NEXT: addi 2, 2, 32720 -# CHECK-NEXT: 10010038: bl .-56 -# CHECK-NEXT: ld 2, 24(1) -# CHECK-NEXT: 10010040: bl .-44 -# CHECK-NEXT: ld 2, 24(1) - # Check that we emit 2 R_PPC64_IRELATIVE. -# DYNREL: R_PPC64_IRELATIVE 10010028 -# DYNREL: R_PPC64_IRELATIVE 1001002c +# DYNREL: R_PPC64_IRELATIVE 10010000 +# DYNREL: R_PPC64_IRELATIVE 10010004 .type ifunc STT_GNU_IFUNC .globl ifunc Index: lld/trunk/test/ELF/ppc64-local-dynamic.s =================================================================== --- lld/trunk/test/ELF/ppc64-local-dynamic.s +++ lld/trunk/test/ELF/ppc64-local-dynamic.s @@ -113,7 +113,7 @@ // Dis: test: // Dis: addis 3, 2, 0 // Dis-NEXT: addi 3, 3, -32760 -// Dis-NEXT: bl .-60 +// Dis-NEXT: bl .+60 // Dis-NEXT: ld 2, 24(1) // Dis-NEXT: addis 3, 3, 0 // Dis-NEXT: lwa 3, -32768(3) Index: lld/trunk/test/ELF/ppc64-long-branch-init.s =================================================================== --- lld/trunk/test/ELF/ppc64-long-branch-init.s +++ lld/trunk/test/ELF/ppc64-long-branch-init.s @@ -0,0 +1,44 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=powerpc64-pc-freebsd13.0 %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s + +## .init consists of sections from several object files. Sections other than the +## last one do not have a terminator. Check we do not create a long branch stub +## in the middle. +## We currently use thunk section spacing to ensure the stub is in the end. This +## is not foolproof but good enough to not break in practice. + +# CHECK: Disassembly of section .init: +# CHECK-EMPTY: +# CHECK-LABEL: _init: +# CHECK: blr +# CHECK-EMPTY: +# CHECK-LABEL: __long_branch_foo: + +.globl foo +foo: + .space 0x2000000 + blr + +.section .init,"ax",@progbits,unique,0 +.globl _init +_init: + stdu 1, -48(1) + mflr 0 + std 0, 64(1) + +.section .init,"ax",@progbits,unique,1 + bl foo + nop + +.section .init,"ax",@progbits,unique,2 + bl foo + nop + +.section .init,"ax",@progbits,unique,3 + ld 1, 0(1) + ld 0, 16(1) + mtlr 0 + blr Index: lld/trunk/test/ELF/ppc64-plt-stub.s =================================================================== --- lld/trunk/test/ELF/ppc64-plt-stub.s +++ lld/trunk/test/ELF/ppc64-plt-stub.s @@ -4,17 +4,20 @@ // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o // RUN: ld.lld -shared %t2.o -o %t2.so // RUN: ld.lld %t.o %t2.so -o %t -// RUN: llvm-objdump -d %t | FileCheck %s +// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o // RUN: ld.lld -shared %t2.o -o %t2.so // RUN: ld.lld %t.o %t2.so -o %t -// RUN: llvm-objdump -d %t | FileCheck %s +// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s // CHECK: Disassembly of section .text: // CHECK-EMPTY: -// CHECK-NEXT: __plt_foo: +// CHECK-NEXT: _start: +// CHECK: 10010008: bl .+16 + +// CHECK-LABEL: 0000000010010018 __plt_foo: // CHECK-NEXT: std 2, 24(1) // CHECK-NEXT: addis 12, 2, 0 // CHECK-NEXT: ld 12, 32560(12) @@ -22,8 +25,6 @@ // CHECK-NEXT: bctr -// CHECK: _start: -// CHECK: bl .-40 .text .abiversion 2 .globl _start Index: lld/trunk/test/ELF/ppc64-toc-restore-recursive-call.s =================================================================== --- lld/trunk/test/ELF/ppc64-toc-restore-recursive-call.s +++ lld/trunk/test/ELF/ppc64-toc-restore-recursive-call.s @@ -14,12 +14,11 @@ # for recursive calls as well as keeps the logic for recursive calls consistent # with non-recursive calls. -# CHECK-LABEL: __plt_recursive_func: -# CHECK-NEXT: 10000: -# CHECK-LABEL: recursive_func -# CHECK-NEXT: 10014: -# CHECK: 1003c: bl .-60 -# CHECK-NEXT: 10040: ld 2, 24(1) +# CHECK-LABEL: 0000000000010000 recursive_func: +# CHECK: 10028: bl .+32 +# CHECK-NEXT: ld 2, 24(1) + +# CHECK-LABEL: 0000000000010048 __plt_recursive_func: .abiversion 2 .section ".text" Index: lld/trunk/test/ELF/ppc64-toc-restore.s =================================================================== --- lld/trunk/test/ELF/ppc64-toc-restore.s +++ lld/trunk/test/ELF/ppc64-toc-restore.s @@ -28,17 +28,11 @@ bl foo nop bl bar_local - - -// CHECK: Disassembly of section .text: +// CHECK-LABEL: _start: +// CHECK-NEXT: 10010008: bl .+64 +// CHECK-NEXT: 1001000c: ld 2, 24(1) +// CHECK-NEXT: 10010010: bl .-16 // CHECK-EMPTY: -// CHECK: _start: -// CHECK: 1001001c: bl .-28 -// CHECK-NOT: 10010020: nop -// CHECK: 10010020: ld 2, 24(1) -// CHECK: 10010024: bl .-16 -// CHECK-NOT: 10010028: nop -// CHECK-NOT: 10010028: ld 2, 24(1) # Calling a function in another object file which will have same # TOC base does not need a nop. If nop present, do not rewrite to @@ -48,26 +42,24 @@ bl foo_not_shared bl foo_not_shared nop - -// CHECK: _diff_object: -// CHECK-NEXT: 10010028: bl .+24 -// CHECK-NEXT: 1001002c: bl .+20 -// CHECK-NEXT: 10010030: nop +// CHECK-LABEL: _diff_object: +// CHECK-NEXT: 10010014: bl .+28 +// CHECK-NEXT: 10010018: bl .+24 +// CHECK-NEXT: 1001001c: nop # Branching to a local function does not need a nop .global noretbranch noretbranch: b bar_local -// CHECK: noretbranch: -// CHECK: 10010034: b .+67108832 -// CHECK-NOT: 10010038: nop -// CHECK-NOT: 1001003c: ld 2, 24(1) +// CHECK-LABEL: noretbranch: +// CHECK: 10010020: b .+67108832 +// CHECK-EMPTY: // This should come last to check the end-of-buffer condition. .global last last: bl foo nop -// CHECK: last: -// CHECK: 10010038: bl .-56 -// CHECK-NEXT: 1001003c: ld 2, 24(1) +// CHECK-LABEL: last: +// CHECK-NEXT: 10010024: bl .+36 +// CHECK-NEXT: 10010028: ld 2, 24(1)