[llvm] d395b56 - [JITLink][AArch64] Implement R_AARCH64_LDR_PREL_LO19 (#82172)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 16 21:46:47 PDT 2024
Author: Pavel Samolysov
Date: 2024-05-17T07:46:43+03:00
New Revision: d395b56a52e9809ec3ea1139f5b30698c9f4e247
URL: https://github.com/llvm/llvm-project/commit/d395b56a52e9809ec3ea1139f5b30698c9f4e247
DIFF: https://github.com/llvm/llvm-project/commit/d395b56a52e9809ec3ea1139f5b30698c9f4e247.diff
LOG: [JITLink][AArch64] Implement R_AARCH64_LDR_PREL_LO19 (#82172)
This relocation is used for the 32-bit aligned 21-bit immediate in LDR
Literal instructions.
Added:
Modified:
llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
index 40b9339eb5316..c09398f984477 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
@@ -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
@@ -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.
//
@@ -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;
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index 6b03bb3c90b20..9ce8aecb717ca 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -49,6 +49,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
private:
enum ELFAArch64RelocationKind : Edge::Kind {
ELFCall26 = Edge::FirstRelocation,
+ ELFLdrLo19,
ELFAdrLo21,
ELFAdrPage21,
ELFAddAbs12,
@@ -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:
@@ -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))
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
index fccef479c2c36..75e367bee80a9 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
@@ -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
More information about the llvm-commits
mailing list