[llvm] [JITLink][AArch64] Implement R_AARCH64_LDR_PREL_LO19 (PR #82172)
Pavel Samolysov via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 18 07:58:49 PST 2024
https://github.com/samolisov created https://github.com/llvm/llvm-project/pull/82172
This relocation is used for the 32-bit aligned 21-bit immediate in LDR Literal instructions.
>From 58ccbd0c159faa35ffd998cbb7405ebf82981678 Mon Sep 17 00:00:00 2001
From: Pavel Samolysov <samolisov at gmail.com>
Date: Sun, 18 Feb 2024 16:49:39 +0300
Subject: [PATCH] [JITLink][AArch64] Implement R_AARCH64_LDR_PREL_LO19
This relocation is used for the 32-bit aligned 21-bit immediate in LDR
Literal instructions.
---
.../llvm/ExecutionEngine/JITLink/aarch64.h | 15 +++++++++------
llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp | 12 ++++++++++++
.../JITLink/AArch64/ELF_relocations.s | 15 +++++++++++++++
3 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
index 40b9339eb5316d..4d081589ac403c 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
@@ -171,7 +171,7 @@ enum EdgeKind_aarch64 : Edge::Kind {
///
/// Fixup expression:
///
- /// Fixup <- (Target - Fixup) >> 2 : int19
+ /// Fixup <- (Target - Fixup + Addend) >> 2 : int19
///
/// Errors:
/// - The result of the unshifted part of the fixup expression must be
@@ -377,6 +377,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.
//
@@ -494,16 +499,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;
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index f17b2c626ac250..6cd2b7e03a58dd 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -47,6 +47,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
private:
enum ELFAArch64RelocationKind : Edge::Kind {
ELFCall26 = Edge::FirstRelocation,
+ ELFLdrLo19,
ELFAdrLo21,
ELFAdrPage21,
ELFAddAbs12,
@@ -80,6 +81,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:
@@ -189,6 +192,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))
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
index b260961f741d72..b837ac18afd270 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
@@ -51,6 +51,21 @@ 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 + 12, 1)[19:0] = \
+# jitlink-check: (ldr_data - test_ldr_prel_lo19_inst + 0x4)[21:2]
+ .globl test_ldr_prel_lo19, test_ldr_prel_lo19_inst, ldr_data
+ .p2align 2
+test_ldr_prel_lo19:
+ nop
+ nop
+ nop
+test_ldr_prel_lo19_inst:
+ 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
More information about the llvm-commits
mailing list