[llvm] a9a2eb8 - [JITLink][AArch64] Implement R_AARCH64_TSTBR14

Job Noorman via llvm-commits llvm-commits at lists.llvm.org
Thu May 18 23:10:27 PDT 2023


Author: Job Noorman
Date: 2023-05-19T08:10:14+02:00
New Revision: a9a2eb81000dfd80978151dde8fd690df298394c

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

LOG: [JITLink][AArch64] Implement R_AARCH64_TSTBR14

This relocation is used for the 14-bit immediate in test and branch
instructions.

Reviewed By: lhames

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

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 b8d83ccaddc60..e7e8b99ad4562 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 14-bit PC-relative test and branch.
+  ///
+  /// Represents a PC-relative test and branch to a target within +/-32Kb. The
+  /// target must be 32-bit aligned.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target - Fixup + Addend) >> 2 : int14
+  ///
+  /// Notes:
+  ///   The '14' 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 16-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 int14 otherwise an
+  ///     out-of-range error will be returned.
+  TestAndBranch14PCRel,
+
   /// A 19-bit PC-relative conditional branch.
   ///
   /// Represents a PC-relative conditional branch to a target within +/-1Mb. The
@@ -321,6 +343,11 @@ inline bool isLoadStoreImm12(uint32_t Instr) {
   return (Instr & LoadStoreImm12Mask) == 0x39000000;
 }
 
+inline bool isTestAndBranchImm14(uint32_t Instr) {
+  constexpr uint32_t TestAndBranchImm14Mask = 0x7e000000;
+  return (Instr & TestAndBranchImm14Mask) == 0x36000000;
+}
+
 inline bool isCondBranchImm19(uint32_t Instr) {
   constexpr uint32_t CondBranchImm19Mask = 0xfe000000;
   return (Instr & CondBranchImm19Mask) == 0x54000000;
@@ -463,6 +490,23 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
     *(ulittle32_t *)FixupPtr = FixedInstr;
     break;
   }
+  case TestAndBranch14PCRel: {
+    assert((FixupAddress.getValue() & 0x3) == 0 &&
+           "Test and branch is not 32-bit aligned");
+    uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
+    assert(isTestAndBranchImm14(RawInstr) &&
+           "RawInstr is not a test and branch");
+    int64_t Delta = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+    if (Delta & 0x3)
+      return make_error<JITLinkError>(
+          "Test and branch literal target is not 32-bit aligned");
+    if (!isInt<16>(Delta))
+      return makeTargetOutOfRangeError(G, B, E);
+    uint32_t EncodedImm = ((static_cast<uint32_t>(Delta) >> 2) & 0x3fff) << 5;
+    uint32_t FixedInstr = RawInstr | EncodedImm;
+    *(ulittle32_t *)FixupPtr = FixedInstr;
+    break;
+  }
   case CondBranch19PCRel: {
     assert((FixupAddress.getValue() & 0x3) == 0 &&
            "Conditional 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 23ad696a2ba63..a062a6653bec7 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,
+    ELFTstBr14,
     ELFCondBr19,
     ELFAbs32,
     ELFAbs64,
@@ -100,6 +101,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       return ELFMovwAbsG2;
     case ELF::R_AARCH64_MOVW_UABS_G3:
       return ELFMovwAbsG3;
+    case ELF::R_AARCH64_TSTBR14:
+      return ELFTstBr14;
     case ELF::R_AARCH64_CONDBR19:
       return ELFCondBr19;
     case ELF::R_AARCH64_ABS32:
@@ -290,6 +293,15 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
       Kind = aarch64::MoveWide16;
       break;
     }
+    case ELFTstBr14: {
+      uint32_t Instr = *(const ulittle32_t *)FixupContent;
+      if (!aarch64::isTestAndBranchImm14(Instr))
+        return make_error<JITLinkError>("R_AARCH64_TSTBR14 target is not a "
+                                        "test and branch instruction");
+
+      Kind = aarch64::TestAndBranch14PCRel;
+      break;
+    }
     case ELFCondBr19: {
       uint32_t Instr = *(const ulittle32_t *)FixupContent;
       if (!aarch64::isCondBranchImm19(Instr) &&

diff  --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index 587b87d1d02f1..785e8cc24fe2a 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 TestAndBranch14PCRel:
+    return "TestAndBranch14PCRel";
   case CondBranch19PCRel:
     return "CondBranch19PCRel";
   case Page21:

diff  --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
index a74f37e22d331..e6185bf03491b 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_TSTBR14 for tbz
+#
+# jitlink-check: decode_operand(test_tstbr14_tbz, 2) = \
+# jitlink-check:     (test_tstbr14_tbz_target - test_tstbr14_tbz)[16:2]
+        .globl test_tstbr14_tbz, test_tstbr14_tbz_target
+        .p2align 2
+test_tstbr14_tbz:
+        tbz x0, 0, test_tstbr14_tbz_target
+        .skip (1 << 14)
+test_tstbr14_tbz_target:
+        .size test_tstbr14_tbz, .-test_tstbr14_tbz
+
+# Check R_AARCH64_TSTBR14 for tbnz
+#
+# jitlink-check: decode_operand(test_tstbr14_tbnz, 2) = \
+# jitlink-check:     (test_tstbr14_tbnz_target - test_tstbr14_tbnz)[16:2]
+        .globl test_tstbr14_tbnz, test_tstbr14_tbnz_target
+        .p2align 2
+test_tstbr14_tbnz:
+        tbnz x0, 0, test_tstbr14_tbnz_target
+        .skip (1 << 14)
+test_tstbr14_tbnz_target:
+        .size test_tstbr14_tbnz, .-test_tstbr14_tbnz
+
 # Check R_AARCH64_CONDBR19 for compare and branch instructions
 #
 # jitlink-check: decode_operand(test_condbr19_cbz, 1) = \


        


More information about the llvm-commits mailing list