Skip to content

[JITLink][AArch64] Implement R_AARCH64_LDR_PREL_LO19 #82172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,14 @@ enum EdgeKind_aarch64 : Edge::Kind {
///
/// Fixup expression:
///
/// Fixup <- (Target - Fixup) >> 2 : int19
/// Fixup <- (Target - Fixup + Addend) >> 2 : int19
///
/// Notes:
/// The '19' in the name refers to the number operand bits and follows the
/// naming convention used by the corresponding ELF relocation.
/// Since the low two bits must be zero (because of the 32-bit alignment of
/// the target) the operand is effectively a signed 21-bit number.
///
///
/// Errors:
/// - The result of the unshifted part of the fixup expression must be
Expand Down Expand Up @@ -377,6 +384,11 @@ inline bool isADR(uint32_t Instr) {
return (Instr & ADRMask) == 0x10000000;
}

inline bool isLDRLiteral(uint32_t Instr) {
constexpr uint32_t LDRLitMask = 0x3b000000;
return (Instr & LDRLitMask) == 0x18000000;
}

// Returns the amount the address operand of LD/ST (imm12)
// should be shifted right by.
//
Expand Down Expand Up @@ -494,16 +506,14 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
}
case LDRLiteral19: {
assert((FixupAddress.getValue() & 0x3) == 0 && "LDR is not 32-bit aligned");
assert(E.getAddend() == 0 && "LDRLiteral19 with non-zero addend");
uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
assert(RawInstr == 0x58000010 && "RawInstr isn't a 64-bit LDR literal");
int64_t Delta = E.getTarget().getAddress() - FixupAddress;
assert(isLDRLiteral(RawInstr) && "RawInstr is not an LDR Literal");
int64_t Delta = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
if (Delta & 0x3)
return make_error<JITLinkError>("LDR literal target is not 32-bit "
"aligned");
if (Delta < -(1 << 20) || Delta > ((1 << 20) - 1))
if (!isInt<21>(Delta))
return makeTargetOutOfRangeError(G, B, E);

uint32_t EncodedImm = ((static_cast<uint32_t>(Delta) >> 2) & 0x7ffff) << 5;
uint32_t FixedInstr = RawInstr | EncodedImm;
*(ulittle32_t *)FixupPtr = FixedInstr;
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
private:
enum ELFAArch64RelocationKind : Edge::Kind {
ELFCall26 = Edge::FirstRelocation,
ELFLdrLo19,
ELFAdrLo21,
ELFAdrPage21,
ELFAddAbs12,
Expand Down Expand Up @@ -82,6 +83,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
case ELF::R_AARCH64_CALL26:
case ELF::R_AARCH64_JUMP26:
return ELFCall26;
case ELF::R_AARCH64_LD_PREL_LO19:
return ELFLdrLo19;
case ELF::R_AARCH64_ADR_PREL_LO21:
return ELFAdrLo21;
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
Expand Down Expand Up @@ -191,6 +194,15 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
Kind = aarch64::Branch26PCRel;
break;
}
case ELFLdrLo19: {
uint32_t Instr = *(const ulittle32_t *)FixupContent;
if (!aarch64::isLDRLiteral(Instr))
return make_error<JITLinkError>(
"R_AARCH64_LDR_PREL_LO19 target is not an LDR Literal instruction");

Kind = aarch64::LDRLiteral19;
break;
}
case ELFAdrLo21: {
uint32_t Instr = *(const ulittle32_t *)FixupContent;
if (!aarch64::isADR(Instr))
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ test_adr_prel_lo21:
## to test this bit better
adr_data = test_adr_prel_lo21 + 0xe46f2

# Check R_AARCH64_LD_PREL_LO19 relocation of a local symbol
#
# jitlink-check: decode_operand(test_ldr_prel_lo19 + 0, 1)[19:0] = \
# jitlink-check: (ldr_data - test_ldr_prel_lo19 + 0x4)[21:2]
.globl test_ldr_prel_lo19, ldr_data
.p2align 2
test_ldr_prel_lo19:
ldr x0, ldr_data + 0x4
.size test_ldr_prel_lo19, .-test_ldr_prel_lo19
ldr_data = test_ldr_prel_lo19 + 4

# Check R_AARCH64_ADR_PREL_PG_HI21 / R_AARCH64_ADD_ABS_LO12_NC relocation of a local symbol
#
# For the ADR_PREL_PG_HI21/ADRP instruction we have the 21-bit delta to the 4k page
Expand Down
Loading