[lld] 8ce1351 - [ELF][PPC64] Merge PPC64R12SetupStub and PPC64PCRelPLTStub. NFC
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 27 14:33:23 PST 2023
Author: Fangrui Song
Date: 2023-02-27T14:33:18-08:00
New Revision: 8ce135123ec574406c72333798380f486b734fc8
URL: https://github.com/llvm/llvm-project/commit/8ce135123ec574406c72333798380f486b734fc8
DIFF: https://github.com/llvm/llvm-project/commit/8ce135123ec574406c72333798380f486b734fc8.diff
LOG: [ELF][PPC64] Merge PPC64R12SetupStub and PPC64PCRelPLTStub. NFC
PPC64PCRelPLTStub (from D83669) duplicates lot of code from
PPC64R12SetupStub. Just merge them.
Note: PPC64R12SetupStub does not correctly handle long branch to a
non-preemptible non-TOC code.
Added:
Modified:
lld/ELF/Thunks.cpp
Removed:
################################################################################
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 8238b15bcf56b..ce35bb5258358 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -384,34 +384,23 @@ class PPC64R2SaveStub final : public Thunk {
};
// PPC64 R12 Setup Stub
-// When a caller that does not maintain a toc-pointer performs a local call to
-// a callee which requires a toc-pointer then we need this stub to place the
-// callee's global entry point into r12 without a save of R2.
+// When a caller that does not maintain TOC calls a target which may possibly
+// use TOC (either non-preemptible with localentry>1 or preemptible), we need to
+// set r12 to satisfy the requirement of the global entry point.
class PPC64R12SetupStub final : public Thunk {
public:
- PPC64R12SetupStub(Symbol &dest) : Thunk(dest, 0) { alignment = 16; }
+ PPC64R12SetupStub(Symbol &dest, bool gotPlt)
+ : Thunk(dest, 0), gotPlt(gotPlt) {
+ 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;
-};
-// PPC64 PC-relative PLT Stub
-// When a caller that does not maintain a toc-pointer performs an extern call
-// then this stub is needed for:
-// 1) Loading the target functions address from the procedure linkage table into
-// r12 for use by the target functions global entry point, and into the count
-// register with pc-relative instructions.
-// 2) Transferring control to the target function through an indirect branch.
-class PPC64PCRelPLTStub final : public Thunk {
-public:
- PPC64PCRelPLTStub(Symbol &dest) : Thunk(dest, 0) { 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;
+private:
+ bool gotPlt;
};
// A bl instruction uses a signed 24 bit offset, with an implicit 4 byte
@@ -1087,12 +1076,19 @@ bool PPC64R2SaveStub::isCompatibleWith(const InputSection &isec,
}
void PPC64R12SetupStub::writeTo(uint8_t *buf) {
- int64_t offset = destination.getVA() - getThunkTargetSym()->getVA();
+ int64_t offset = (gotPlt ? destination.getGotPltVA() : destination.getVA()) -
+ getThunkTargetSym()->getVA();
if (!isInt<34>(offset))
reportRangeError(buf, offset, 34, destination, "R12 setup stub offset");
int nextInstOffset;
- if (!config->power10Stubs) {
+ if (config->power10Stubs) {
+ const uint64_t imm = (((offset >> 16) & 0x3ffff) << 32) | (offset & 0xffff);
+ // pld 12, func at plt@pcrel or paddi r12, 0, func at pcrel
+ writePrefixedInstruction(
+ buf, (gotPlt ? PLD_R12_NO_DISP : PADDI_R12_NO_DISP) | imm);
+ nextInstOffset = 8;
+ } else {
uint32_t off = destination.getVA(addend) - getThunkTargetSym()->getVA() - 8;
write32(buf + 0, 0x7c0802a6); // mflr r12
write32(buf + 4, 0x429f0005); // bcl 20,31,.+4
@@ -1101,19 +1097,15 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) {
write32(buf + 16, 0x3d8b0000 | computeHiBits(off));// addis r12,r11,off at ha
write32(buf + 20, 0x398c0000 | (off & 0xffff)); // addi r12,r12,off at 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 at pcrel, 1
- nextInstOffset = 8;
}
write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
write32(buf + nextInstOffset + 4, BCTR); // bctr
}
void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {
- addSymbol(saver().save("__gep_setup_" + destination.getName()), STT_FUNC, 0,
- isec);
+ addSymbol(saver().save((gotPlt ? "__plt_pcrel_" : "__gep_setup_") +
+ destination.getName()),
+ STT_FUNC, 0, isec);
}
bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec,
@@ -1121,42 +1113,6 @@ bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec,
return rel.type == R_PPC64_REL24_NOTOC;
}
-void PPC64PCRelPLTStub::writeTo(uint8_t *buf) {
- int nextInstOffset = 0;
- int64_t offset = destination.getGotPltVA() - getThunkTargetSym()->getVA();
-
- if (config->power10Stubs) {
- if (!isInt<34>(offset))
- reportRangeError(buf, offset, 34, destination,
- "PC-relative PLT stub offset");
- const uint64_t pld = PLD_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) |
- (offset & 0xffff);
- writePrefixedInstruction(buf + 0, pld); // pld r12, func at plt@pcrel
- nextInstOffset = 8;
- } else {
- 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 at ha
- write32(buf + 20, 0x398c0000 | (off & 0xffff)); // addi r12,r12,off at l
- nextInstOffset = 24;
- }
- write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
- write32(buf + nextInstOffset + 4, BCTR); // bctr
-}
-
-void PPC64PCRelPLTStub::addSymbols(ThunkSection &isec) {
- addSymbol(saver().save("__plt_pcrel_" + destination.getName()), STT_FUNC, 0,
- isec);
-}
-
-bool PPC64PCRelPLTStub::isCompatibleWith(const InputSection &isec,
- const Relocation &rel) const {
- return rel.type == R_PPC64_REL24_NOTOC;
-}
-
void PPC64LongBranchThunk::writeTo(uint8_t *buf) {
int64_t offset = in.ppc64LongBranchTarget->getEntryVA(&destination, addend) -
getPPC64TocBase();
@@ -1329,8 +1285,9 @@ static Thunk *addThunkPPC64(RelType type, Symbol &s, int64_t a) {
type == R_PPC64_REL24_NOTOC) &&
"unexpected relocation type for thunk");
if (s.isInPlt())
- return type == R_PPC64_REL24_NOTOC ? (Thunk *)make<PPC64PCRelPLTStub>(s)
- : (Thunk *)make<PPC64PltCallStub>(s);
+ return type == R_PPC64_REL24_NOTOC
+ ? (Thunk *)make<PPC64R12SetupStub>(s, /*gotPlt=*/true)
+ : (Thunk *)make<PPC64PltCallStub>(s);
// This check looks at the st_other bits of the callee. If the value is 1
// then the callee clobbers the TOC and we need an R2 save stub when RelType
@@ -1339,7 +1296,7 @@ static Thunk *addThunkPPC64(RelType type, Symbol &s, int64_t a) {
return make<PPC64R2SaveStub>(s, a);
if (type == R_PPC64_REL24_NOTOC)
- return make<PPC64R12SetupStub>(s);
+ return make<PPC64R12SetupStub>(s, /*gotPlt=*/false);
if (config->picThunk)
return make<PPC64PILongBranchThunk>(s, a);
More information about the llvm-commits
mailing list