[llvm] [JITLink][LoongArch] Support large code model (PR #155566)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 27 00:28:29 PDT 2025


https://github.com/Ami-zhang created https://github.com/llvm/llvm-project/pull/155566

None

>From cd95f7e2348a93dd4844de1479c12e257e0d6edf Mon Sep 17 00:00:00 2001
From: Ami-zhang <zhanglimin at loongson.cn>
Date: Wed, 27 Aug 2025 14:48:24 +0800
Subject: [PATCH] [JITLink][LoongArch] Support large code model

---
 .../llvm/ExecutionEngine/JITLink/loongarch.h  | 80 +++++++++++++++++++
 .../ExecutionEngine/JITLink/ELF_loongarch.cpp |  8 ++
 .../lib/ExecutionEngine/JITLink/loongarch.cpp |  4 +
 3 files changed, 92 insertions(+)

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
index 04c5a67ac4fe3..c3225d368a45a 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
@@ -161,6 +161,18 @@ enum EdgeKind_loongarch : Edge::Kind {
   ///
   Page20,
 
+  /// The signed 20-bit delta from the fixup page to the page containing the
+  /// target for 64-bit addresses.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- getLoongArchPageDelta(Target + Addend, FixupAddress,
+  ///   Type)[51:32]
+  ///
+  /// Notes:
+  ///   For PCALAU12I fixups in large code model.
+  ///
+  Page64Lo20,
+
   /// The 12-bit offset of the target within its page.
   ///
   /// Typically used to fix up ADDI/LD_W/LD_D immediates.
@@ -170,6 +182,17 @@ enum EdgeKind_loongarch : Edge::Kind {
   ///
   PageOffset12,
 
+  /// The 12-bit high part of the 64-bit page delta.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- getLoongArchPageDelta(Target + Addend, FixupAddress,
+  ///   Type)[63:52]
+  ///
+  /// Notes:
+  ///   For large code model instructions.
+  ///
+  Page64Hi12,
+
   /// A GOT entry getter/constructor, transformed to Page20 pointing at the GOT
   /// entry for the original target.
   ///
@@ -206,6 +229,16 @@ enum EdgeKind_loongarch : Edge::Kind {
   ///
   RequestGOTAndTransformToPageOffset12,
 
+  /// A GOT entry getter/constructor, transformed to Page64Lo20 pointing at the
+  /// GOT entry for the original target.
+  ///
+  RequestGOTAndTransformToPage64Lo20,
+
+  /// A GOT entry getter/constructor, transformed to Page64Hi12 pointing at the
+  /// GOT entry for the original target.
+  ///
+  RequestGOTAndTransformToPage64Hi12,
+
   /// A 36-bit PC-relative call.
   ///
   /// Represents a PC-relative call to a target within [-128G - 0x20000, +128G
@@ -330,6 +363,29 @@ inline uint32_t extractBits(uint64_t Val, unsigned Hi, unsigned Lo) {
   return Hi == 63 ? Val >> Lo : (Val & ((((uint64_t)1 << (Hi + 1)) - 1))) >> Lo;
 }
 
+inline uint64_t getLoongArchPageDelta(uint64_t Target, uint64_t FixupAddr,
+                                      Edge::Kind Kind) {
+  uint64_t PC;
+  switch (Kind) {
+  case Page64Lo20:
+    PC = FixupAddr - 8;
+    break;
+  case Page64Hi12:
+    PC = FixupAddr - 12;
+    break;
+  default:
+    PC = FixupAddr;
+    break;
+  }
+
+  uint64_t Result = (Target & ~0xfffULL) - (PC & ~0xfffULL);
+  if (Target & 0x800)
+    Result += 0x1000 - 0x1'0000'0000;
+  if (Result & 0x8000'0000)
+    Result += 0x1'0000'0000;
+  return Result;
+}
+
 /// Apply fixup expression for edge to block content.
 inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
   using namespace support;
@@ -456,6 +512,24 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
     *(little32_t *)(FixupPtr + 4) = Jirl | Lo16;
     break;
   }
+  case Page64Lo20: {
+    uint64_t Target = TargetAddress + Addend;
+    uint64_t PageDelta =
+        getLoongArchPageDelta(Target, FixupAddress, Page64Lo20);
+    uint32_t Imm51_32 = extractBits(PageDelta, /*Hi=*/51, /*Lo=*/32) << 5;
+    *(ulittle32_t *)FixupPtr =
+        (*(ulittle32_t *)FixupPtr & 0xfe00001f) | Imm51_32;
+    break;
+  }
+  case Page64Hi12: {
+    uint64_t Target = TargetAddress + Addend;
+    uint64_t PageDelta =
+        getLoongArchPageDelta(Target, FixupAddress, Page64Hi12);
+    uint32_t Imm63_52 = extractBits(PageDelta, /*Hi=*/63, /*Lo=*/52) << 10;
+    *(ulittle32_t *)FixupPtr =
+        (*(ulittle32_t *)FixupPtr & 0xffc003ff) | Imm63_52;
+    break;
+  }
   case Add6: {
     int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr));
     Value += ((TargetAddress + Addend) & 0x3f);
@@ -631,6 +705,12 @@ class GOTTableManager : public TableManager<GOTTableManager> {
     case RequestGOTAndTransformToPageOffset12:
       KindToSet = PageOffset12;
       break;
+    case RequestGOTAndTransformToPage64Lo20:
+      KindToSet = Page64Lo20;
+      break;
+    case RequestGOTAndTransformToPage64Hi12:
+      KindToSet = Page64Hi12;
+      break;
     default:
       return false;
     }
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
index f23fb346c55f9..715df5c72f19a 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
@@ -306,6 +306,14 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
       return RequestGOTAndTransformToPageOffset12;
     case ELF::R_LARCH_CALL36:
       return Call36PCRel;
+    case ELF::R_LARCH_PCALA64_LO20:
+      return Page64Lo20;
+    case ELF::R_LARCH_PCALA64_HI12:
+      return Page64Hi12;
+    case ELF::R_LARCH_GOT64_PC_LO20:
+      return RequestGOTAndTransformToPage64Lo20;
+    case ELF::R_LARCH_GOT64_PC_HI12:
+      return RequestGOTAndTransformToPage64Hi12;
     case ELF::R_LARCH_ADD6:
       return Add6;
     case ELF::R_LARCH_ADD8:
diff --git a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
index 55389adb31b60..d59df676c3f41 100644
--- a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
@@ -52,6 +52,10 @@ const char *getEdgeKindName(Edge::Kind K) {
     KIND_NAME_CASE(RequestGOTAndTransformToPage20)
     KIND_NAME_CASE(RequestGOTAndTransformToPageOffset12)
     KIND_NAME_CASE(Call36PCRel)
+    KIND_NAME_CASE(Page64Lo20)
+    KIND_NAME_CASE(Page64Hi12)
+    KIND_NAME_CASE(RequestGOTAndTransformToPage64Lo20)
+    KIND_NAME_CASE(RequestGOTAndTransformToPage64Hi12)
     KIND_NAME_CASE(Add6)
     KIND_NAME_CASE(Add8)
     KIND_NAME_CASE(Add16)



More information about the llvm-commits mailing list