diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -399,24 +399,6 @@ } }; -// A bl instruction uses a signed 24 bit offset, with an implicit 4 byte -// alignment. This gives a possible 26 bits of 'reach'. If the caller and -// callee do not use toc and the call offset is larger than 26 bits, -// we need to emit a pc-rel based long-branch thunk. The target address of -// the callee is computed with a PC-relative offset. -class PPC64PCRelLongBranchThunk final : public Thunk { -public: - PPC64PCRelLongBranchThunk(Symbol &dest, int64_t addend) - : Thunk(dest, addend) { - alignment = 16; - } - uint32_t size() override { return 32; } - void writeTo(uint8_t *buf) override; - void addSymbols(ThunkSection &isec) override; - bool isCompatibleWith(const InputSection &isec, - const Relocation &rel) const override; -}; - } // end anonymous namespace Defined *Thunk::addSymbol(StringRef name, uint8_t type, uint64_t value, @@ -1000,8 +982,8 @@ } void PPC64R12SetupStub::addSymbols(ThunkSection &isec) { - addSymbol(saver.save("__gep_setup_" + destination.getName()), STT_FUNC, 0, - isec); + addSymbol(saver.save("__long_branch_pcrel_" + destination.getName()), + STT_FUNC, 0, isec); } bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec, @@ -1061,42 +1043,6 @@ return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14; } -void PPC64PCRelLongBranchThunk::writeTo(uint8_t *buf) { - int64_t offset = destination.getVA() - getThunkTargetSym()->getVA(); - if (!isInt<34>(offset)) - reportRangeError(buf, offset, 34, destination, - "PC-relative long branch stub offset"); - - int nextInstOffset; - if (!config->power10Stubs) { - uint32_t off = destination.getVA(addend) - getThunkTargetSym()->getVA() - 8; - write32(buf + 0, 0x7c0802a6); // mflr r12 - write32(buf + 4, 0x429f0005); // bcl 20,31,.+4 - write32(buf + 8, 0x7d6802a6); // mflr r11 - write32(buf + 12, 0x7d8803a6); // mtlr r12 - write32(buf + 16, 0x3d8b0000 | computeHiBits(off)); // addis r12,r11,off@ha - write32(buf + 20, 0x398c0000 | (off & 0xffff)); // addi r12,r12,off@l - nextInstOffset = 24; - } else { - uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) | - (offset & 0xffff); - writePrefixedInstruction(buf + 0, paddi); // paddi r12, 0, func@pcrel, 1 - nextInstOffset = 8; - } - write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12 - write32(buf + nextInstOffset + 4, BCTR); // bctr -} - -void PPC64PCRelLongBranchThunk::addSymbols(ThunkSection &isec) { - addSymbol(saver.save("__long_branch_pcrel_" + destination.getName()), - STT_FUNC, 0, isec); -} - -bool PPC64PCRelLongBranchThunk::isCompatibleWith(const InputSection &isec, - const Relocation &rel) const { - return rel.type == R_PPC64_REL24_NOTOC; -} - Thunk::Thunk(Symbol &d, int64_t a) : destination(d), addend(a), offset(0) {} Thunk::~Thunk() = default; @@ -1223,9 +1169,7 @@ return make(s, a); if (type == R_PPC64_REL24_NOTOC) - return (s.stOther >> 5) > 1 - ? (Thunk *)make(s) - : (Thunk *)make(s, a); + return make(s); if (config->picThunk) return make(s, a); diff --git a/lld/test/ELF/ppc64-pcrel-call-to-toc.s b/lld/test/ELF/ppc64-pcrel-call-to-toc.s --- a/lld/test/ELF/ppc64-pcrel-call-to-toc.s +++ b/lld/test/ELF/ppc64-pcrel-call-to-toc.s @@ -27,7 +27,7 @@ # SYMBOL: 1: 0000000010010000 0 NOTYPE LOCAL DEFAULT 1 func # SYMBOL-NEXT: 2: 0000000010020000 0 NOTYPE LOCAL DEFAULT [] 2 callee # SYMBOL: 4: 0000000010030000 0 NOTYPE LOCAL DEFAULT [] 3 caller -# SYMBOL: 6: 0000000010030010 32 FUNC LOCAL DEFAULT 3 __gep_setup_callee +# SYMBOL: 6: 0000000010030010 32 FUNC LOCAL DEFAULT 3 __long_branch_pcrel_callee # CHECK-LABEL: : # CHECK-NEXT: blr @@ -42,12 +42,12 @@ # CHECK-NEXT: bl 0x10030010 # CHECK-NEXT: blr -# CHECK-LABEL: <__gep_setup_callee>: +# CHECK-LABEL: <__long_branch_pcrel_callee>: # CHECK-NEXT: paddi 12, 0, -65552, 1 # CHECK-NEXT: mtctr 12 # CHECK-NEXT: bctr -# CHECK-NOP10-LABEL: <__gep_setup_callee>: +# CHECK-NOP10-LABEL: <__long_branch_pcrel_callee>: # CHECK-NOP10-NEXT: mflr 0 # CHECK-NOP10-NEXT: bcl 20, 31, 0x10030018 # CHECK-NOP10-NEXT: mflr 11 diff --git a/lld/test/ELF/ppc64-pcrel-cross-link.s b/lld/test/ELF/ppc64-pcrel-cross-link.s --- a/lld/test/ELF/ppc64-pcrel-cross-link.s +++ b/lld/test/ELF/ppc64-pcrel-cross-link.s @@ -27,7 +27,7 @@ # NOSWAP-NEXT: bl 0x10030010 # NOSWAP-NEXT: bl 0x10030030 # NOSWAP-NEXT: blr -# NOSWAP-LABEL: 10030010 <__gep_setup_callee_toc>: +# NOSWAP-LABEL: 10030010 <__long_branch_pcrel_callee_toc>: # NOSWAP: bctr # NOSWAP-LABEL: 10030030 <__long_branch_pcrel_callee_notoc>: # NOSWAP: bctr @@ -66,7 +66,7 @@ # SWAP-NEXT: bl 0x10040010 # SWAP-NEXT: bl 0x10040030 # SWAP-NEXT: blr -# SWAP-LABEL: 10040010 <__gep_setup_callee_toc>: +# SWAP-LABEL: 10040010 <__long_branch_pcrel_callee_toc>: # SWAP: bctr # SWAP-LABEL: 10040030 <__long_branch_pcrel_callee_notoc>: # SWAP: bctr diff --git a/lld/test/ELF/ppc64-pcrel-long-branch-error.s b/lld/test/ELF/ppc64-pcrel-long-branch-error.s --- a/lld/test/ELF/ppc64-pcrel-long-branch-error.s +++ b/lld/test/ELF/ppc64-pcrel-long-branch-error.s @@ -18,7 +18,8 @@ # RUN: ld.lld -shared --script %t/lds %t.o -o %t1 --noinhibit-exec # RUN: rm %t.o %t1 -# CHECK: error: PC-relative long branch stub offset is out of range: 8589934592 is not in [-8589934592, 8589934591]; references high +## Note: GNU ld uses sldi 11, 11, 34 and add 12, 11, 12 to support offsets beyond +-2**33. +# CHECK: error: R12 setup stub offset is out of range: 8589934592 is not in [-8589934592, 8589934591]; references high # CHECK-NEXT: >>> defined in {{.*}}.o //--- asm