[llvm] 193a809 - [JITLink][AArch64] Implement R_AARCH64_CONDBR19

Job Noorman via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 26 01:22:57 PDT 2023


Author: Job Noorman
Date: 2023-04-26T10:22:36+02:00
New Revision: 193a8092fb334dbc24edc3bf47c7884cf124f1ce

URL: https://github.com/llvm/llvm-project/commit/193a8092fb334dbc24edc3bf47c7884cf124f1ce
DIFF: https://github.com/llvm/llvm-project/commit/193a8092fb334dbc24edc3bf47c7884cf124f1ce.diff

LOG: [JITLink][AArch64] Implement R_AARCH64_CONDBR19

This relocation is used for the 19-bit immediate in conditional branch
and compare and branch instructions.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D149138

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 33c09e1a2a315..b8d83ccaddc60 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
@@ -107,6 +107,28 @@ enum EdgeKind_aarch64 : Edge::Kind {
   ///     out-of-range error will be returned.
   Branch26PCRel,
 
+  /// A 19-bit PC-relative conditional branch.
+  ///
+  /// Represents a PC-relative conditional branch to a target within +/-1Mb. The
+  /// target must be 32-bit aligned.
+  ///
+  /// Fixup expression:
+  ///   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
+  ///     32-bit aligned otherwise an alignment error will be returned.
+  ///   - The result of the fixup expression must fit into an int19 otherwise an
+  ///     out-of-range error will be returned.
+  CondBranch19PCRel,
+
   /// A 16-bit slice of the target address (which slice depends on the
   /// instruction at the fixup location).
   ///
@@ -299,6 +321,16 @@ inline bool isLoadStoreImm12(uint32_t Instr) {
   return (Instr & LoadStoreImm12Mask) == 0x39000000;
 }
 
+inline bool isCondBranchImm19(uint32_t Instr) {
+  constexpr uint32_t CondBranchImm19Mask = 0xfe000000;
+  return (Instr & CondBranchImm19Mask) == 0x54000000;
+}
+
+inline bool isCompAndBranchImm19(uint32_t Instr) {
+  constexpr uint32_t CompAndBranchImm19Mask = 0x7e000000;
+  return (Instr & CompAndBranchImm19Mask) == 0x34000000;
+}
+
 // Returns the amount the address operand of LD/ST (imm12)
 // should be shifted right by.
 //
@@ -431,6 +463,24 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
     *(ulittle32_t *)FixupPtr = FixedInstr;
     break;
   }
+  case CondBranch19PCRel: {
+    assert((FixupAddress.getValue() & 0x3) == 0 &&
+           "Conditional branch is not 32-bit aligned");
+    uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
+    assert((isCondBranchImm19(RawInstr) || isCompAndBranchImm19(RawInstr)) &&
+           "RawInstr is not a conditional branch");
+    int64_t Delta = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+    if (Delta & 0x3)
+      return make_error<JITLinkError>(
+          "Conditional branch literal target is not 32-bit "
+          "aligned");
+    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;
+    break;
+  }
   case Page21: {
     uint64_t TargetPage =
         (E.getTarget().getAddress().getValue() + E.getAddend()) &

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index ab47f86859dd6..9df1126277e9a 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -58,6 +58,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
     ELFMovwAbsG1,
     ELFMovwAbsG2,
     ELFMovwAbsG3,
+    ELFCondBr19,
     ELFAbs32,
     ELFAbs64,
     ELFPrel32,
@@ -99,6 +100,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       return ELFMovwAbsG2;
     case ELF::R_AARCH64_MOVW_UABS_G3:
       return ELFMovwAbsG3;
+    case ELF::R_AARCH64_CONDBR19:
+      return ELFCondBr19;
     case ELF::R_AARCH64_ABS32:
       return ELFAbs32;
     case ELF::R_AARCH64_ABS64:
@@ -287,6 +290,16 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       Kind = aarch64::MoveWide16;
       break;
     }
+    case ELFCondBr19: {
+      uint32_t Instr = *(const ulittle32_t *)FixupContent;
+      if (!aarch64::isCondBranchImm19(Instr) &&
+          !aarch64::isCompAndBranchImm19(Instr))
+        return make_error<JITLinkError>("R_AARCH64_CONDBR19 target is not a "
+                                        "conditional branch instruction");
+
+      Kind = aarch64::CondBranch19PCRel;
+      break;
+    }
     case ELFAbs32: {
       Kind = aarch64::Pointer32;
       break;

diff  --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index 1011fa81f750f..587b87d1d02f1 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
@@ -47,6 +47,8 @@ const char *getEdgeKindName(Edge::Kind R) {
     return "MoveWide16";
   case LDRLiteral19:
     return "LDRLiteral19";
+  case CondBranch19PCRel:
+    return "CondBranch19PCRel";
   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 3eb72e5b2456a..a74f37e22d331 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
@@ -241,6 +241,30 @@ test_ld64_gotlo12_external:
         ldr   x0, [x0, :got_lo12:external_data]
         .size test_ld64_gotlo12_external, .-test_ld64_gotlo12_external
 
+# Check R_AARCH64_CONDBR19 for compare and branch instructions
+#
+# jitlink-check: decode_operand(test_condbr19_cbz, 1) = \
+# jitlink-check:     (test_condbr19_cbz_target - test_condbr19_cbz)[21:2]
+        .globl test_condbr19_cbz, test_condbr19_cbz_target
+        .p2align 2
+test_condbr19_cbz:
+        cbz x0, test_condbr19_cbz_target
+        .skip (1 << 19)
+test_condbr19_cbz_target:
+        .size test_condbr19_cbz, .-test_condbr19_cbz
+
+# Check R_AARCH64_CONDBR19 for conditional branch instructions
+#
+# jitlink-check: decode_operand(test_condbr19_bc, 1) = \
+# jitlink-check:     (test_condbr19_bc_target - test_condbr19_bc)[21:2]
+        .globl test_condbr19_bc, test_condbr19_bc_target
+        .p2align 2
+test_condbr19_bc:
+        b.eq test_condbr19_bc_target
+        .skip (1 << 19)
+test_condbr19_bc_target:
+        .size test_condbr19_bc, .-test_condbr19_bc
+
         .globl  named_data
         .p2align  4
         .type   named_data, at object


        


More information about the llvm-commits mailing list