summaryrefslogtreecommitdiff
path: root/lld/ELF
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2023-02-27 16:19:13 -0800
committerFangrui Song <i@maskray.me>2023-02-27 16:19:13 -0800
commit7198c87f42f6c15d76b127c1c63530e9b4d5dd39 (patch)
tree023c183cf970df2ad707c3166de7b3cae72aea8e /lld/ELF
parentd77f96a9e0c86a35f5d5986058b4dcce30113cca (diff)
downloadllvm-7198c87f42f6c15d76b127c1c63530e9b4d5dd39.tar.gz
[ELF][PPC64] Actually implement --no-power10-stubs
When a caller that does not use TOC calls a function, a call stub is needed if the function may use TOC. --no-power10-stubs avoids PC-relative instructions in the code sequence. The --no-power10-stubs=no implementation added in D94627 is wrong. First, the first instruction incorrectly uses `mflr 0` (instead of `mflr 12`). Second, for the PLT case, it uses addis+addi with getVA instead of addis+ld with getGotPltVA.
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/Thunks.cpp18
-rw-r--r--lld/ELF/Thunks.h4
2 files changed, 11 insertions, 11 deletions
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index ce35bb525835..ca0d34dce7dc 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -1089,13 +1089,17 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) {
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
- 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
+ uint32_t off = offset - 8;
+ write32(buf + 0, 0x7d8802a6); // mflr 12
+ write32(buf + 4, 0x429f0005); // bcl 20,31,.+4
+ write32(buf + 8, 0x7d6802a6); // mflr 11
+ write32(buf + 12, 0x7d8803a6); // mtlr 12
+ write32(buf + 16,
+ 0x3d8b0000 | ((off + 0x8000) >> 16)); // addis 12,11,off@ha
+ if (gotPlt)
+ write32(buf + 20, 0xe98c0000 | (off & 0xffff)); // ld 12, off@l(12)
+ else
+ write32(buf + 20, 0x398c0000 | (off & 0xffff)); // addi 12,12,off@l
nextInstOffset = 24;
}
write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
diff --git a/lld/ELF/Thunks.h b/lld/ELF/Thunks.h
index 86aaee15f93b..12ddf08cadc0 100644
--- a/lld/ELF/Thunks.h
+++ b/lld/ELF/Thunks.h
@@ -73,10 +73,6 @@ void writePPC32PltCallStub(uint8_t *buf, uint64_t gotPltVA,
const InputFile *file, int64_t addend);
void writePPC64LoadAndBranch(uint8_t *buf, int64_t offset);
-static inline uint16_t computeHiBits(uint32_t toCompute) {
- return (toCompute + 0x8000) >> 16;
-}
-
} // namespace lld::elf
#endif