[llvm] e967638 - [JITLink][AArch64] Implement R_AARCH64_ADR_PREL_LO21
Job Noorman via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 9 03:00:48 PDT 2023
Author: Job Noorman
Date: 2023-06-09T11:57:51+02:00
New Revision: e967638947603d5c4260696af79f965a426e8a46
URL: https://github.com/llvm/llvm-project/commit/e967638947603d5c4260696af79f965a426e8a46
DIFF: https://github.com/llvm/llvm-project/commit/e967638947603d5c4260696af79f965a426e8a46.diff
LOG: [JITLink][AArch64] Implement R_AARCH64_ADR_PREL_LO21
This relocation is used for the 21-bit immediate in ADR instructions.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D151305
Added:
Modified:
llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
llvm/lib/ExecutionEngine/JITLink/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 e7e8b99ad4562..50bebf335de1a 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
@@ -180,6 +180,20 @@ enum EdgeKind_aarch64 : Edge::Kind {
/// out-of-range error will be returned.
LDRLiteral19,
+ /// The signed 21-bit delta from the fixup to the target.
+ ///
+ /// Fixup expression:
+ ///
+ /// Fixup <- Target - Fixup + Addend : int21
+ ///
+ /// Notes:
+ /// For ADR fixups.
+ ///
+ /// Errors:
+ /// - The result of the fixup expression must fit into an int21 otherwise an
+ /// out-of-range error will be returned.
+ ADRLiteral21,
+
/// The signed 21-bit delta from the fixup page to the page containing the
/// target.
///
@@ -358,6 +372,11 @@ inline bool isCompAndBranchImm19(uint32_t Instr) {
return (Instr & CompAndBranchImm19Mask) == 0x34000000;
}
+inline bool isADR(uint32_t Instr) {
+ constexpr uint32_t ADRMask = 0x9f000000;
+ return (Instr & ADRMask) == 0x10000000;
+}
+
// Returns the amount the address operand of LD/ST (imm12)
// should be shifted right by.
//
@@ -490,6 +509,20 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
*(ulittle32_t *)FixupPtr = FixedInstr;
break;
}
+ case ADRLiteral21: {
+ assert((FixupAddress.getValue() & 0x3) == 0 && "ADR is not 32-bit aligned");
+ uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
+ assert(isADR(RawInstr) && "RawInstr is not an ADR");
+ int64_t Delta = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+ if (!isInt<21>(Delta))
+ return makeTargetOutOfRangeError(G, B, E);
+ auto UDelta = static_cast<uint32_t>(Delta);
+ uint32_t EncodedImmHi = ((UDelta >> 2) & 0x7ffff) << 5;
+ uint32_t EncodedImmLo = (UDelta & 0x3) << 29;
+ uint32_t FixedInstr = RawInstr | EncodedImmHi | EncodedImmLo;
+ *(ulittle32_t *)FixupPtr = FixedInstr;
+ break;
+ }
case TestAndBranch14PCRel: {
assert((FixupAddress.getValue() & 0x3) == 0 &&
"Test and branch is not 32-bit aligned");
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index a062a6653bec7..fac320773d6f8 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,
+ ELFAdrLo21,
ELFAdrPage21,
ELFAddAbs12,
ELFLdSt8Abs12,
@@ -79,6 +80,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
case ELF::R_AARCH64_CALL26:
case ELF::R_AARCH64_JUMP26:
return ELFCall26;
+ case ELF::R_AARCH64_ADR_PREL_LO21:
+ return ELFAdrLo21;
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
return ELFAdrPage21;
case ELF::R_AARCH64_ADD_ABS_LO12_NC:
@@ -186,6 +189,15 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
Kind = aarch64::Branch26PCRel;
break;
}
+ case ELFAdrLo21: {
+ uint32_t Instr = *(const ulittle32_t *)FixupContent;
+ if (!aarch64::isADR(Instr))
+ return make_error<JITLinkError>(
+ "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction");
+
+ Kind = aarch64::ADRLiteral21;
+ break;
+ }
case ELFAdrPage21: {
Kind = aarch64::Page21;
break;
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index 785e8cc24fe2a..cc58255a338df 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
@@ -51,6 +51,8 @@ const char *getEdgeKindName(Edge::Kind R) {
return "TestAndBranch14PCRel";
case CondBranch19PCRel:
return "CondBranch19PCRel";
+ case ADRLiteral21:
+ return "ADRLiteral21";
case Page21:
return "Page21";
case PageOffset12:
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
index e6185bf03491b..b260961f741d7 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
@@ -39,6 +39,18 @@ local_func_jump26:
b local_func
.size local_func_jump26, .-local_func_jump26
+# Check R_AARCH64_ADR_PREL_LO21 relocation of a local symbol
+#
+# jitlink-check: decode_operand(test_adr_prel_lo21, 1) = (adr_data - test_adr_prel_lo21)[20:0]
+ .globl test_adr_prel_lo21, adr_data
+ .p2align 2
+test_adr_prel_lo21:
+ adr x0, adr_data
+ .size test_adr_prel_lo21, .-test_adr_prel_lo21
+## ADR encoding is a bit tricky so use an offset with an irregular bit pattern
+## to test this bit better
+adr_data = test_adr_prel_lo21 + 0xe46f2
+
# 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