[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