[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