[llvm] [JITLink][LoongArch] Add support for R_LARCH_CALL36 relocation (PR #117127)

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 21 00:34:28 PST 2024


https://github.com/wangleiat created https://github.com/llvm/llvm-project/pull/117127

This relocation is used for function calls with medium code model.


>From 2b901e6a8dc2170348a3e8a6c83b4ec89823097e Mon Sep 17 00:00:00 2001
From: wanglei <wanglei at loongson.cn>
Date: Thu, 21 Nov 2024 16:34:14 +0800
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.5-bogner
---
 .../llvm/ExecutionEngine/JITLink/loongarch.h  | 47 +++++++++++++++++--
 .../ExecutionEngine/JITLink/ELF_loongarch.cpp |  2 +
 .../lib/ExecutionEngine/JITLink/loongarch.cpp |  1 +
 .../LoongArch/ELF_loongarch64_relocations.s   | 26 ++++++++++
 4 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
index 26351ed9971cc4..39a7db32258ce7 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
@@ -158,6 +158,29 @@ enum EdgeKind_loongarch : Edge::Kind {
   ///   NONE
   ///
   RequestGOTAndTransformToPageOffset12,
+
+  /// A 36-bit PC-relative call.
+  ///
+  /// Represents a PC-relative call to a target within [-128G - 0x20000, +128G
+  /// - 0x20000). The target must be 4-byte aligned. For adjacent pcaddu18i+jirl
+  /// instruction pairs.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target - Fixup + Addend) >> 2 : int36
+  ///
+  /// Notes:
+  ///   The '36' in the name refers to the number operand bits and follows the
+  /// naming convention used by the corresponding ELF relocations. Since the low
+  /// two bits must be zero (because of the 4-byte alignment of the target) the
+  /// operand is effectively a signed 38-bit number.
+  ///
+  /// Errors:
+  ///   - The result of the unshifted part of the fixup expression must be
+  ///     4-byte aligned otherwise an alignment error will be returned.
+  ///   - The result of the fixup expression must fit into an int36 otherwise an
+  ///     out-of-range error will be returned.
+  ///
+  Call36PCRel,
 };
 
 /// Returns a string name for the given loongarch edge. For debugging purposes
@@ -165,8 +188,8 @@ enum EdgeKind_loongarch : Edge::Kind {
 const char *getEdgeKindName(Edge::Kind K);
 
 // Returns extract bits Val[Hi:Lo].
-inline uint32_t extractBits(uint32_t Val, unsigned Hi, unsigned Lo) {
-  return (Val & (((1UL << (Hi + 1)) - 1))) >> Lo;
+inline uint32_t extractBits(uint64_t Val, unsigned Hi, unsigned Lo) {
+  return Hi == 63 ? Val >> Lo : (Val & (((1UL << (Hi + 1)) - 1))) >> Lo;
 }
 
 /// Apply fixup expression for edge to block content.
@@ -247,6 +270,23 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
     *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0;
     break;
   }
+  case Call36PCRel: {
+    int64_t Value = TargetAddress - FixupAddress + Addend;
+
+    if ((Value + 0x20000) != llvm::SignExtend64(Value + 0x20000, 38))
+      return makeTargetOutOfRangeError(G, B, E);
+
+    if (!isShiftedInt<36, 2>(Value))
+      return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
+
+    uint32_t Pcaddu18i = *(little32_t *)FixupPtr;
+    uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/37, /*Lo=*/18) << 5;
+    *(little32_t *)FixupPtr = Pcaddu18i | Hi20;
+    uint32_t Jirl = *(little32_t *)(FixupPtr + 4);
+    uint32_t Lo16 = extractBits(Value, /*Hi=*/17, /*Lo=*/2) << 10;
+    *(little32_t *)(FixupPtr + 4) = Jirl | Lo16;
+    break;
+  }
   default:
     return make_error<JITLinkError>(
         "In graph " + G.getName() + ", section " + B.getSection().getName() +
@@ -363,7 +403,8 @@ class PLTTableManager : public TableManager<PLTTableManager> {
   static StringRef getSectionName() { return "$__STUBS"; }
 
   bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
-    if (E.getKind() == Branch26PCRel && !E.getTarget().isDefined()) {
+    if ((E.getKind() == Branch26PCRel || E.getKind() == Call36PCRel) &&
+        !E.getTarget().isDefined()) {
       DEBUG_WITH_TYPE("jitlink", {
         dbgs() << "  Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
                << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
index aa9385fcb183dd..42fcfebd12d616 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
@@ -68,6 +68,8 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
       return RequestGOTAndTransformToPage20;
     case ELF::R_LARCH_GOT_PC_LO12:
       return RequestGOTAndTransformToPageOffset12;
+    case ELF::R_LARCH_CALL36:
+      return Call36PCRel;
     }
 
     return make_error<JITLinkError>(
diff --git a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
index d1e44ec187cc80..010c0ed6713d49 100644
--- a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
@@ -49,6 +49,7 @@ const char *getEdgeKindName(Edge::Kind K) {
     KIND_NAME_CASE(PageOffset12)
     KIND_NAME_CASE(RequestGOTAndTransformToPage20)
     KIND_NAME_CASE(RequestGOTAndTransformToPageOffset12)
+    KIND_NAME_CASE(Call36PCRel)
   default:
     return getGenericEdgeKindName(K);
   }
diff --git a/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_loongarch64_relocations.s b/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_loongarch64_relocations.s
index 74eb8118d10e3c..f07ac5422b8fc8 100644
--- a/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_loongarch64_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_loongarch64_relocations.s
@@ -68,6 +68,12 @@ test_addi_pcrel_lo12:
 # jitlink-check: decode_operand(test_external_jump, 0) = \
 # jitlink-check:   (stub_addr(elf_reloc.o, external_func) - \
 # jitlink-check:      test_external_jump)[27:0]
+# jitlink-check: decode_operand(test_external_call36, 1)[19:0] = \
+# jitlink-check:   (stub_addr(elf_reloc.o, external_func) - \
+# jitlink-check:      test_external_call36 + (1<<17))[37:18]
+# jitlink-check: decode_operand(test_external_call36 + 4, 2)[17:0] = \
+# jitlink-check:   (stub_addr(elf_reloc.o, external_func) - \
+# jitlink-check:      test_external_call36)[17:0]
     .globl test_external_call
     .p2align  2
 test_external_call:
@@ -80,6 +86,13 @@ test_external_jump:
     b external_func
     .size test_external_jump, .-test_external_jump
 
+    .globl test_external_call36
+    .p2align  2
+test_external_call36:
+    pcaddu18i $ra, %call36(external_func)
+    jirl $ra, $ra, 0
+    .size test_external_call36, .-test_external_call36
+
 ## Check R_LARCH_GOT_PC_HI20 / R_LARCH_GOT_PC_LO12 handling with a reference to
 ## an external symbol. Validate both the reference to the GOT entry, and also
 ## the content of the GOT entry.
@@ -104,6 +117,19 @@ test_gotoffset12_external:
     .size test_gotoffset12_external, .-test_gotoffset12_external
 
 
+## Check R_LARCH_CALL36 relocation of a local function call.
+
+# jitlink-check: decode_operand(local_func_call36, 1)[19:0] = \
+# jitlink-check:   ((local_func - local_func_call36) + (1<<17))[37:18]
+# jitlink-check: decode_operand(local_func_call36 + 4, 2)[17:0] = \
+# jitlink-check:   (local_func - local_func_call36)[17:0]
+    .globl local_func_call36
+    .p2align 2
+local_func_call36:
+    pcaddu18i $ra, %call36(local_func)
+    jirl $ra, $ra, 0
+    .size local_func_call36, .-local_func_call36
+
     .globl named_data
     .p2align 4
     .type named_data, at object



More information about the llvm-commits mailing list