diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -123,6 +123,7 @@ bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, uint8_t StOther) const override; + uint32_t getThunkSectionSpacing() const override; }; } // namespace @@ -925,6 +926,11 @@ return true; } +uint32_t PPC64::getThunkSectionSpacing() const { + // REL14 range + return 0x8000; +} + TargetInfo *elf::getPPC64TargetInfo() { static PPC64 Target; return &Target; diff --git a/lld/test/ELF/Inputs/ppc64-far-branch-rangethunk.s b/lld/test/ELF/Inputs/ppc64-far-branch-rangethunk.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/Inputs/ppc64-far-branch-rangethunk.s @@ -0,0 +1,7 @@ + +.global too_far1 +.type too_far1,%function + +// place too_far1 to + 64MB (should be above 32MB) +too_far1 = 0x10010000 + 0x4000000 + diff --git a/lld/test/ELF/ppc64-branch-thunkspacing.s b/lld/test/ELF/ppc64-branch-thunkspacing.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc64-branch-thunkspacing.s @@ -0,0 +1,37 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd13.0 %s -o %t +# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd13.0 %S/Inputs/ppc64-far-branch-rangethunk.s -o %tfar +# RUN: ld.lld %t %tfar -o %t2 2>&1 +# RUN: llvm-objdump -d -triple=powerpc64-unknown-freebsd13.0 %t2 | FileCheck %s + + .section .init,"ax",@progbits + .align 2 + .globl _start + .type _start,@function +_start: + stwu 1,-16(1) + mflr 0 + stw 31,12(1) + stw 0,20(1) + mr 31,1 + bl too_far1 + + +# When ThunkSpacing is applied, "__long_branch_too_far1" is shifted +# to an offset after "_start" + +# CHECK: Disassembly of section .init: +# CHECK-NEXT: 0000000010010000 _start: +# CHECK-NEXT: 10010000: 94 21 ff f0 stwu 1, -16(1) +# CHECK-NEXT: 10010004: 7c 08 02 a6 mflr 0 +# CHECK-NEXT: 10010008: 93 e1 00 0c stw 31, 12(1) +# CHECK-NEXT: 1001000c: 90 01 00 14 stw 0, 20(1) +# CHECK-NEXT: 10010010: 7c 3f 0b 78 mr 31, 1 +# CHECK-NEXT: 10010014: 48 00 00 05 bl .+4 + +# CHECK: 0000000010010018 __long_branch_too_far1: +# CHECK-NEXT: 10010018: 3d 82 10 02 addis 12, 2, 4098 +# CHECK-NEXT: 1001001c: e9 8c 80 00 ld 12, -32768(12) +# CHECK-NEXT: 10010020: 7d 89 03 a6 mtctr 12 +# CHECK-NEXT: 10010024: 4e 80 04 20 bctr