forked from OSchip/llvm-project
[PPC64] Helper for offset from a function's global entry to local entry. [NFC]
The PPC64 elf V2 abi defines 2 entry points for a function. There are a few places we need to calculate the offset from the global entry to the local entry and how this is done is not straight forward. This patch adds a helper function mostly for documentation purposes, explaining how the 2 entry points differ and why we choose one over the other, as well as documenting how the offsets are encoded into a functions st_other field. Differential Revision: https://reviews.llvm.org/D52231 llvm-svn: 342603
This commit is contained in:
parent
7f3f05e0b7
commit
e0e586b997
|
@ -74,6 +74,32 @@ uint64_t elf::getPPC64TocBase() {
|
|||
return TocVA + PPC64TocOffset;
|
||||
}
|
||||
|
||||
|
||||
unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther) {
|
||||
// The offset is encoded into the 3 most significant bits of the st_other
|
||||
// field, with some special values described in section 3.4.1 of the ABI:
|
||||
// 0 --> Zero offset between the GEP and LEP, and the function does NOT use
|
||||
// the TOC pointer (r2). r2 will hold the same value on returning from
|
||||
// the function as it did on entering the function.
|
||||
// 1 --> Zero offset between the GEP and LEP, and r2 should be treated as a
|
||||
// caller-saved register for all callers.
|
||||
// 2-6 --> The binary logarithm of the offset eg:
|
||||
// 2 --> 2^2 = 4 bytes --> 1 instruction.
|
||||
// 6 --> 2^6 = 64 bytes --> 16 instructions.
|
||||
// 7 --> Reserved.
|
||||
uint8_t GepToLep = (StOther >> 5) & 7;
|
||||
if (GepToLep < 2)
|
||||
return 0;
|
||||
|
||||
// The value encoded in the st_other bits is the
|
||||
// log-base-2(offset).
|
||||
if (GepToLep < 7)
|
||||
return 1 << GepToLep;
|
||||
|
||||
error("reserved value of 7 in the 3 most-significant-bits of st_other");
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class PPC64 final : public TargetInfo {
|
||||
public:
|
||||
|
|
|
@ -631,16 +631,12 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
|
|||
return 0;
|
||||
|
||||
// PPC64 V2 ABI describes two entry points to a function. The global entry
|
||||
// point sets up the TOC base pointer. When calling a local function, the
|
||||
// call should branch to the local entry point rather than the global entry
|
||||
// point. Section 3.4.1 describes using the 3 most significant bits of the
|
||||
// st_other field to find out how many instructions there are between the
|
||||
// local and global entry point.
|
||||
uint8_t StOther = (Sym.StOther >> 5) & 7;
|
||||
if (StOther == 0 || StOther == 1)
|
||||
return SymVA - P;
|
||||
|
||||
return SymVA - P + (1LL << StOther);
|
||||
// point is used for calls where the caller and callee (may) have different
|
||||
// TOC base pointers and r2 needs to be modified to hold the TOC base for
|
||||
// the callee. For local calls the caller and callee share the same
|
||||
// TOC base and so the TOC pointer initialization code should be skipped by
|
||||
// branching to the local entry point.
|
||||
return SymVA - P + getPPC64GlobalEntryToLocalEntryOffset(Sym.StOther);
|
||||
}
|
||||
case R_PPC_TOC:
|
||||
return getPPC64TocBase() + A;
|
||||
|
|
|
@ -171,6 +171,15 @@ static inline std::string getErrorLocation(const uint8_t *Loc) {
|
|||
return getErrorPlace(Loc).Loc;
|
||||
}
|
||||
|
||||
// In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first is
|
||||
// a global entry point (GEP) which typically is used to intiailzie the TOC
|
||||
// pointer in general purpose register 2. The second is a local entry
|
||||
// point (LEP) which bypasses the TOC pointer initialization code. The
|
||||
// offset between GEP and LEP is encoded in a function's st_other flags.
|
||||
// This function will return the offset (in bytes) from the global entry-point
|
||||
// to the local entry-point.
|
||||
unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther);
|
||||
|
||||
uint64_t getPPC64TocBase();
|
||||
uint64_t getAArch64Page(uint64_t Expr);
|
||||
|
||||
|
|
Loading…
Reference in New Issue