In this patch, a pc-rel based long branch thunk is added for the local call protocol that caller and callee does not use TOC.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
lld/ELF/Thunks.cpp | ||
---|---|---|
375 | IIUC If there is a call between a pc-rel based caller and a toc-based callee (so that callee has global and local entry points) then we will have emitted an PPC64R12SetupoStub. Likewise, if its a toc-based caller and pc-rel based callee we use an R2SaveStub. So its only between pc-rel based caller and callee that we can have a pc rel based long branch thunk. | |
993 | The R12Setup stub calculates the address of the callee relative to the program counter. writePrefixedInstruction(buf + 0, paddi); // paddi r12, 0, func@pcrel, 1 write32(buf + 8, MTCTR_R12); // mtctr r12 write32(buf + 12, BCTR); // bctr The toc-based long branch thunks have to use a table in the data segment because of limited address-ability. The pc-rel instructions and ABI doesn't have the same limitation, so why use the branch linkage table intead of doing the same thing the R12Setup stubs do? |
lld/ELF/Thunks.cpp | ||
---|---|---|
375 | Yes. PC-Rel based long branch thunk is needed only between pc-rel based caller and callee.
| |
993 | Good point! Will update the patch without using branch_lt table. |
lld/ELF/Thunks.cpp | ||
---|---|---|
993 | Is it not possible to need a long branch to a destination that isn't available yet? I thought that something like the following would require a long branch to a PLT stub: #include <stdio.h> int main(int argc, const char **argv) { int a = argc; printf("a = %d\n", a); asm (".space 134217728"); printf("a = %d\n", a); } But that seems to create two PLT stubs. Is this something that always happens? Namely, is it always the case that the linker will never create a thunk that goes to another thunk? If so, I think a comment explaining that might be useful. |
lld/ELF/Thunks.cpp | ||
---|---|---|
993 | IIUC we only create a long branch thunk between a caller and callee and we check if there is a valid RelType (R_PPC64_REL14, R_PPC64_REL24, R_PPC64_REL24_NOTOC) in PPC64::needsThunk |
lld/ELF/Thunks.cpp | ||
---|---|---|
993 |
getThunk looks at the symbol referenced by the relocation and sees if an existing compatible thunk can be reused, but if none fit the cirteria it creates a new thunk targeting the symbol rather then creating a thunk that targets another thunk.
No: all the address sensitive content has been laid out and finalized by the time the thinks writeTo member function is called. | |
994 | I don't believe we have accounted for the addend in the other PPC64 thunks (both toc-based and pc-rel based). If we do take into account the addend then we have to account for that in 'isCompatableWith' as well. I don't believe the compilers emit calls instructions using both symbol and addends (or we likely would have realized this earlier). I suggest to keep it simple we follow the example of the other thinks and omit the addend, or potentially error on a non-zero addend. We can then revisit this in a subsequent patch where we fix all the thunks that will need to account for the addend. |
lld/ELF/Thunks.cpp | ||
---|---|---|
994 | Agree, will omit the addend in this thunk o be consistent with other PPC64 thunks, we can fix all the thunks to account for the addend in a subsequent patch. |
One minor nit, but otherwise LGTM. If Nemanja would still like the comment he suggested make sure to address that before committing.
lld/ELF/Thunks.cpp | ||
---|---|---|
996 | Real minor nit: mcmodel=large is a helpful hint, but I think its only relevant if you are using a C/C++ compiler and maybe fortran. It might be confusing if you are linking objects that came from a different source language. |
lld/ELF/Thunks.cpp | ||
---|---|---|
996 | Thanks, message updated. |
lld/ELF/Thunks.cpp | ||
---|---|---|
1143 | How is the new PPC64PCRelLongBranchThunk different from PPC64R12SetupStub? Why can't the two be unified? |
lld/ELF/Thunks.cpp | ||
---|---|---|
1143 | They are identical. We will create a NFC patch to unify them. Thanks! |
IIUC If there is a call between a pc-rel based caller and a toc-based callee (so that callee has global and local entry points) then we will have emitted an PPC64R12SetupoStub. Likewise, if its a toc-based caller and pc-rel based callee we use an R2SaveStub. So its only between pc-rel based caller and callee that we can have a pc rel based long branch thunk.