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

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 28 05:48:27 PDT 2025


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

>From 917eeb0f2931b33423b4ddcf8265734ec0f2350e Mon Sep 17 00:00:00 2001
From: Ami-zhang <zhanglimin at loongson.cn>
Date: Thu, 28 Aug 2025 16:11:01 +0800
Subject: [PATCH] [JITLink][LoongArch] Support large code model

---
 .../llvm/ExecutionEngine/JITLink/loongarch.h  | 87 +++++++++++++++++++
 .../ExecutionEngine/JITLink/ELF_loongarch.cpp |  8 ++
 .../lib/ExecutionEngine/JITLink/loongarch.cpp |  4 +
 .../JITLink/LoongArch/ELF_large.s             | 52 +++++++++++
 4 files changed, 151 insertions(+)
 create mode 100644 llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_large.s

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
index 04c5a67ac4fe3..a0e0045f80925 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
@@ -161,6 +161,17 @@ 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, Kind)
+  ///
+  /// 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 +181,16 @@ enum EdgeKind_loongarch : Edge::Kind {
   ///
   PageOffset12,
 
+  /// The 12-bit high part of the 64-bit page delta.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- getLoongArchPageDelta(Target + Addend, FixupAddress, Kind)
+  ///
+  /// 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 +227,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 +361,32 @@ inline uint32_t extractBits(uint64_t Val, unsigned Hi, unsigned Lo) {
   return Hi == 63 ? Val >> Lo : (Val & ((((uint64_t)1 << (Hi + 1)) - 1))) >> Lo;
 }
 
+static uint64_t getLoongArchPageDelta(uint64_t dest, uint64_t pc,
+                                      Edge::Kind kind) {
+  uint64_t pcalau12i_pc;
+  switch (kind) {
+  case RequestGOTAndTransformToPage64LO20:
+  case Page64LO20:
+    pcalau12i_pc = pc - 8;
+    break;
+  case RequestGOTAndTransformToPage64HI12:
+  case Page64HI12:
+    pcalau12i_pc = pc - 12;
+    break;
+  default:
+    pcalau12i_pc = pc;
+    break;
+  }
+
+  uint64_t result = (dest & ~0xfffULL) - (pcalau12i_pc & ~0xfffULL);
+  if (dest & 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 +513,30 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
     *(little32_t *)(FixupPtr + 4) = Jirl | Lo16;
     break;
   }
+  case RequestGOTAndTransformToPage64HI12:
+  case Page64HI12: {
+    uint64_t Target = TargetAddress + Addend;
+    uint64_t pageDelta =
+        getLoongArchPageDelta(Target, FixupAddress, E.getKind());
+    uint32_t imm = extractBits(pageDelta, 63, 52) << 10;
+
+    uint32_t instr = *(little32_t *)FixupPtr;
+    instr = (instr & 0xFFC003FF) | imm;
+    *(little32_t *)FixupPtr = instr;
+    break;
+  }
+  case RequestGOTAndTransformToPage64LO20:
+  case Page64LO20: {
+    uint64_t Target = TargetAddress + Addend;
+    uint64_t pageDelta =
+        getLoongArchPageDelta(Target, FixupAddress, E.getKind());
+    uint32_t imm = extractBits(pageDelta, 51, 32) << 5;
+
+    uint32_t instr = *(little32_t *)FixupPtr;
+    instr = (instr & 0xFE00001F) | imm;
+    *(little32_t *)FixupPtr = instr;
+    break;
+  }
   case Add6: {
     int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr));
     Value += ((TargetAddress + Addend) & 0x3f);
@@ -631,6 +712,12 @@ class GOTTableManager : public TableManager<GOTTableManager> {
     case RequestGOTAndTransformToPageOffset12:
       KindToSet = PageOffset12;
       break;
+    case RequestGOTAndTransformToPage64HI12:
+      KindToSet = Page64HI12;
+      break;
+    case RequestGOTAndTransformToPage64LO20:
+      KindToSet = Page64LO20;
+      break;
     default:
       return false;
     }
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
index f23fb346c55f9..473c78d327242 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_GOT64_PC_HI12:
+      return RequestGOTAndTransformToPage64HI12;
+    case ELF::R_LARCH_GOT64_PC_LO20:
+      return RequestGOTAndTransformToPage64LO20;
+    case ELF::R_LARCH_PCALA64_HI12:
+      return Page64HI12;
+    case ELF::R_LARCH_PCALA64_LO20:
+      return Page64LO20;
     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..c9c9b50e37ad3 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(RequestGOTAndTransformToPage64HI12)
+    KIND_NAME_CASE(RequestGOTAndTransformToPage64LO20)
+    KIND_NAME_CASE(Page64HI12)
+    KIND_NAME_CASE(Page64LO20)
     KIND_NAME_CASE(Add6)
     KIND_NAME_CASE(Add8)
     KIND_NAME_CASE(Add16)
diff --git a/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_large.s b/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_large.s
new file mode 100644
index 0000000000000..dba10bcf146b0
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_large.s
@@ -0,0 +1,52 @@
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc --triple=loongarch64 --filetype=obj -o %t/elf_large_reloc.o %s
+# RUN: llvm-jitlink --noexec \
+# RUN:              --abs external_data=0x1234 \
+# RUN:              --abs external_func=0xcafef00d \
+# RUN:              --check %s %t/elf_large_reloc.o
+
+    .text
+    .globl main
+    .p2align 2
+    .type main, at function
+main:
+    ret
+    .size main,.-main
+
+    .section .sec.large.pc,"ax", at progbits
+    .globl test_large_pc
+    .p2align 2
+test_large_pc:
+# jitlink-check: *{4}(test_large_pc) = 0x1bffffed
+# jitlink-check: *{4}(test_large_pc + 4) = 0x2c0000c
+# jitlink-check: *{4}(test_large_pc + 8) = 0x1600000c
+# jitlink-check: *{4}(test_large_pc + 12) = 0x300018c
+    pcalau12i $t1, %pc_hi20(named_data)        # R_LARCH_PCALA_HI20
+    addi.d $t0, $zero, %pc_lo12(named_data)    # R_LARCH_PCALA_LO12
+    lu32i.d $t0, %pc64_lo20(named_data)        # R_LARCH_PCALA64_LO20
+    lu52i.d $t0, $t0, %pc64_hi12(named_data)   # R_LARCH_PCALA64_HI12
+    .size test_large_pc, .-test_large_pc
+
+    .section .sec.large.got,"ax", at progbits
+    .globl test_large_got
+    .p2align 2
+test_large_got:
+## Test R_LARCH_GOT64_PC_HI12 and R_LARCH_GOT64_PC_LO20 with external symbol
+# jitlink-check: *{4}(test_large_got) = 0x1a00000d
+# jitlink-check: *{4}(test_large_got + 4) = 0x2c0a00c
+# jitlink-check: *{4}(test_large_got + 8) = 0x1600000c
+# jitlink-check: *{4}(test_large_got + 12) = 0x300018c
+    pcalau12i $t1, %got_pc_hi20(external_data)      # R_LARCH_GOT_PC_HI20
+    addi.d $t0, $zero, %got_pc_lo12(external_data)  # R_LARCH_GOT_PC_LO12
+    lu32i.d $t0, %got64_pc_lo20(external_data)      # R_LARCH_GOT64_PC_LO20
+    lu52i.d $t0, $t0, %got64_pc_hi12(external_data) # R_LARCH_GOT64_PC_HI12
+    .size test_large_got, .-test_large_got
+
+    .data
+    .globl named_data
+    .p2align 4
+    .type named_data, at object
+named_data:
+    .quad 0x1111111111111111
+    .quad 0x2222222222222222
+    .size named_data, .-named_data



More information about the llvm-commits mailing list