mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 19:12:56 +02:00
RuntimeDyldELF: don't create thunk if not needed
This patch doesn't create thunk for branch operation when following conditions are met: - Architecture is AArch64 - Relocation target is in the same object file - Relocation target is close enough to be encoded in immediate offset In such case we branch directly to the target instead of branching to thunk Differential revision: https://reviews.llvm.org/D28108 llvm-svn: 291431
This commit is contained in:
parent
b704324492
commit
724c326513
@ -896,6 +896,49 @@ uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType,
|
|||||||
return ELF::R_MIPS_NONE;
|
return ELF::R_MIPS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sometimes we don't need to create thunk for a branch.
|
||||||
|
// This typically happens when branch target is located
|
||||||
|
// in the same object file. In such case target is either
|
||||||
|
// a weak symbol or symbol in a different executable section.
|
||||||
|
// This function checks if branch target is located in the
|
||||||
|
// same object file and if distance between source and target
|
||||||
|
// fits R_AARCH64_CALL26 relocation. If both conditions are
|
||||||
|
// met, it emits direct jump to the target and returns true.
|
||||||
|
// Otherwise false is returned and thunk is created.
|
||||||
|
bool RuntimeDyldELF::resolveAArch64ShortBranch(
|
||||||
|
unsigned SectionID, relocation_iterator RelI,
|
||||||
|
const RelocationValueRef &Value) {
|
||||||
|
uint64_t Address;
|
||||||
|
if (Value.SymbolName) {
|
||||||
|
auto Loc = GlobalSymbolTable.find(Value.SymbolName);
|
||||||
|
|
||||||
|
// Don't create direct branch for external symbols.
|
||||||
|
if (Loc == GlobalSymbolTable.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto &SymInfo = Loc->second;
|
||||||
|
Address = reinterpret_cast<uint64_t>(
|
||||||
|
Sections[SymInfo.getSectionID()].getLoadAddressWithOffset(
|
||||||
|
SymInfo.getOffset()));
|
||||||
|
} else {
|
||||||
|
Address =
|
||||||
|
reinterpret_cast<uint64_t>(Sections[Value.SectionID].getLoadAddress());
|
||||||
|
}
|
||||||
|
uint64_t Offset = RelI->getOffset();
|
||||||
|
uint64_t SourceAddress = Sections[SectionID].getLoadAddressWithOffset(Offset);
|
||||||
|
|
||||||
|
// R_AARCH64_CALL26 requires immediate to be in range -2^27 <= imm < 2^27
|
||||||
|
// If distance between source and target is out of range then we should
|
||||||
|
// create thunk.
|
||||||
|
if (!isInt<28>(Address + Value.Addend - SourceAddress))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
resolveRelocation(Sections[SectionID], Offset, Address, RelI->getType(),
|
||||||
|
Value.Addend);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Expected<relocation_iterator>
|
Expected<relocation_iterator>
|
||||||
RuntimeDyldELF::processRelocationRef(
|
RuntimeDyldELF::processRelocationRef(
|
||||||
unsigned SectionID, relocation_iterator RelI, const ObjectFile &O,
|
unsigned SectionID, relocation_iterator RelI, const ObjectFile &O,
|
||||||
@ -1003,7 +1046,7 @@ RuntimeDyldELF::processRelocationRef(
|
|||||||
(uint64_t)Section.getAddressWithOffset(i->second),
|
(uint64_t)Section.getAddressWithOffset(i->second),
|
||||||
RelType, 0);
|
RelType, 0);
|
||||||
DEBUG(dbgs() << " Stub function found\n");
|
DEBUG(dbgs() << " Stub function found\n");
|
||||||
} else {
|
} else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) {
|
||||||
// Create a new stub function.
|
// Create a new stub function.
|
||||||
DEBUG(dbgs() << " Create a new stub function\n");
|
DEBUG(dbgs() << " Create a new stub function\n");
|
||||||
Stubs[Value] = Section.getStubOffset();
|
Stubs[Value] = Section.getStubOffset();
|
||||||
|
@ -40,6 +40,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
|||||||
void resolveAArch64Relocation(const SectionEntry &Section, uint64_t Offset,
|
void resolveAArch64Relocation(const SectionEntry &Section, uint64_t Offset,
|
||||||
uint64_t Value, uint32_t Type, int64_t Addend);
|
uint64_t Value, uint32_t Type, int64_t Addend);
|
||||||
|
|
||||||
|
bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI,
|
||||||
|
const RelocationValueRef &Value);
|
||||||
|
|
||||||
void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset,
|
void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset,
|
||||||
uint32_t Value, uint32_t Type, int32_t Addend);
|
uint32_t Value, uint32_t Type, int32_t Addend);
|
||||||
|
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
# RUN: llvm-mc -triple=arm64-none-linux-gnu -filetype=obj -o %T/branch.o %s
|
||||||
|
# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -check=%s %T/branch.o
|
||||||
|
|
||||||
|
.globl _main
|
||||||
|
.weak _label1
|
||||||
|
|
||||||
|
.section .text.1,"ax"
|
||||||
|
_label1:
|
||||||
|
nop
|
||||||
|
_main:
|
||||||
|
b _label1
|
||||||
|
|
||||||
|
## Branch 1 instruction back from _main
|
||||||
|
# rtdyld-check: *{4}(_main) = 0x17ffffff
|
Loading…
Reference in New Issue
Block a user