[llvm-branch-commits] [llvm] [JITLink][LoongArch] Add reloc types for LA32R/LA32S (PR #175353)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Jan 10 08:54:40 PST 2026
https://github.com/heiher created https://github.com/llvm/llvm-project/pull/175353
None
>From 5c03040af7b680b051fd5a938fcd16f3454876a2 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Wed, 31 Dec 2025 09:51:43 +0800
Subject: [PATCH] [JITLink][LoongArch] Add reloc types for LA32R/LA32S
---
.../llvm/ExecutionEngine/JITLink/loongarch.h | 73 +++++++++++++++-
.../ExecutionEngine/JITLink/ELF_loongarch.cpp | 85 ++++++++++++++++++-
.../lib/ExecutionEngine/JITLink/loongarch.cpp | 4 +
3 files changed, 160 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
index 1bb18e38bab33..cb3c1919d65d1 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
@@ -170,6 +170,30 @@ enum EdgeKind_loongarch : Edge::Kind {
///
PageOffset12,
+ /// The upper 20 bits of the offset from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target + Addend - Fixup + 0x800) >> 12 : int20
+ ///
+ /// Notes:
+ /// For PCADDU12I fixups.
+ ///
+ /// Errors:
+ /// - The result of the fixup expression must fit into an int20 otherwise an
+ /// out-of-range error will be returned.
+ ///
+ PCAdd20,
+
+ /// The lower 12 bits of the offset from the paired PCADDU12I (the initial
+ /// target) to the final target it points to.
+ ///
+ /// Typically used to fix up ADDI/LD_W/LD_D immediates.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (FinalTarget - InitialTarget) & 0xfff : int12
+ ///
+ PCAdd12,
+
/// A GOT entry getter/constructor, transformed to Page20 pointing at the GOT
/// entry for the original target.
///
@@ -206,6 +230,49 @@ enum EdgeKind_loongarch : Edge::Kind {
///
RequestGOTAndTransformToPageOffset12,
+ /// A GOT entry getter/constructor, transformed to PCAdd20 pointing at the GOT
+ /// entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a PCAdd20 targeting
+ /// the GOT entry for the edge's current target, maintaining the same addend.
+ /// A GOT entry for the target should be created if one does not already
+ /// exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT/PLT builder pass inserted
+ /// by default.
+ ///
+ /// Fixup expression:
+ /// NONE
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ /// phase will result in an assert/unreachable during the fixup phase.
+ ///
+ RequestGOTAndTransformToPCAdd20,
+
+ /// A 30-bit PC-relative call.
+ ///
+ /// Represents a PC-relative call to a target within [-4G, +4G)
+ /// The target must be 4-byte aligned. For adjacent pcaddu12i+jirl
+ /// instruction pairs.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 2 : int30
+ ///
+ /// Notes:
+ /// The '30' 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 32-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 int30 otherwise an
+ /// out-of-range error will be returned.
+ ///
+ Call30PCRel,
+
/// A 36-bit PC-relative call.
///
/// Represents a PC-relative call to a target within [-128G - 0x20000, +128G
@@ -399,6 +466,9 @@ class GOTTableManager : public TableManager<GOTTableManager> {
case RequestGOTAndTransformToPageOffset12:
KindToSet = PageOffset12;
break;
+ case RequestGOTAndTransformToPCAdd20:
+ KindToSet = PCAdd20;
+ break;
default:
return false;
}
@@ -437,7 +507,8 @@ class PLTTableManager : public TableManager<PLTTableManager> {
static StringRef getSectionName() { return "$__STUBS"; }
bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
- if ((E.getKind() == Branch26PCRel || E.getKind() == Call36PCRel) &&
+ if ((E.getKind() == Branch26PCRel || E.getKind() == Call36PCRel ||
+ E.getKind() == Call30PCRel) &&
!E.getTarget().isDefined()) {
DEBUG_WITH_TYPE("jitlink", {
dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
index ee4a3280f18c4..497635941a887 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
@@ -37,9 +37,41 @@ class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> {
ELFJITLinker_loongarch(std::unique_ptr<JITLinkContext> Ctx,
std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
- : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
+ JITLinkerBase::getPassConfig().PostAllocationPasses.push_back(
+ [this](LinkGraph &G) { return gatherLoongArchPCAdd20(G); });
+ }
private:
+ DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *>
+ RelPCAdd20Map;
+
+ Error gatherLoongArchPCAdd20(LinkGraph &G) {
+ for (Block *B : G.blocks())
+ for (Edge &E : B->edges())
+ if (E.getKind() == PCAdd20)
+ RelPCAdd20Map[{B, E.getOffset()}] = &E;
+
+ return Error::success();
+ }
+
+ Expected<const Edge &> getLoongArchPCAdd20(const Edge &E) const {
+ using namespace loongarch;
+ assert((E.getKind() == PCAdd12) &&
+ "Can only have high relocation for PCAdd12");
+
+ const Symbol &Sym = E.getTarget();
+ const Block &B = Sym.getBlock();
+ orc::ExecutorAddrDiff Offset = Sym.getOffset() + E.getAddend();
+
+ auto It = RelPCAdd20Map.find({&B, Offset});
+ if (It != RelPCAdd20Map.end())
+ return *It->second;
+
+ return make_error<JITLinkError>("No PCAdd20 relocation type be found "
+ "for PCAdd12 relocation type");
+ }
+
/// Apply fixup expression for edge to block content.
Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
using namespace support;
@@ -149,6 +181,48 @@ class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> {
*(ulittle32_t *)FixupPtr = RawInstr | Imm11_0;
break;
}
+ case PCAdd20: {
+ uint64_t Target = TargetAddress + Addend;
+ int64_t Delta = Target - FixupAddress + 0x800;
+
+ if (!isInt<32>(Delta))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ uint32_t Imm31_12 = extractBits(Delta, /*Hi=*/31, /*Lo=*/12) << 5;
+ *(little32_t *)FixupPtr = RawInstr | Imm31_12;
+ break;
+ }
+ case PCAdd12: {
+ auto RelPCAdd20 = getLoongArchPCAdd20(E);
+ if (!RelPCAdd20)
+ return RelPCAdd20.takeError();
+ int64_t Delta =
+ (RelPCAdd20->getTarget().getAddress() + RelPCAdd20->getAddend()) -
+ (E.getTarget().getAddress() + E.getAddend());
+
+ uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
+ uint32_t Imm11_0 = extractBits(Delta, /*Hi=*/11, /*Lo=*/0) << 10;
+ *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0;
+ break;
+ }
+ case Call30PCRel: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+
+ if (Value != llvm::SignExtend64(Value, 32))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ if (!isShiftedInt<30, 2>(Value))
+ return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
+
+ uint32_t Pcaddu12i = *(little32_t *)FixupPtr;
+ uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/31, /*Lo=*/12) << 5;
+ *(little32_t *)FixupPtr = Pcaddu12i | Hi20;
+ uint32_t Jirl = *(little32_t *)(FixupPtr + 4);
+ uint32_t Lo10 = extractBits(Value, /*Hi=*/11, /*Lo=*/2) << 10;
+ *(little32_t *)(FixupPtr + 4) = Jirl | Lo10;
+ break;
+ }
case Call36PCRel: {
int64_t Value = TargetAddress - FixupAddress + Addend;
@@ -534,6 +608,8 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
return RequestGOTAndTransformToPage20;
case ELF::R_LARCH_GOT_PC_LO12:
return RequestGOTAndTransformToPageOffset12;
+ case ELF::R_LARCH_CALL30:
+ return Call30PCRel;
case ELF::R_LARCH_CALL36:
return Call36PCRel;
case ELF::R_LARCH_ADD6:
@@ -562,6 +638,13 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
return SubUleb128;
case ELF::R_LARCH_ALIGN:
return AlignRelaxable;
+ case ELF::R_LARCH_PCADD_HI20:
+ return PCAdd20;
+ case ELF::R_LARCH_PCADD_LO12:
+ case ELF::R_LARCH_GOT_PCADD_LO12:
+ return PCAdd12;
+ case ELF::R_LARCH_GOT_PCADD_HI20:
+ return RequestGOTAndTransformToPCAdd20;
}
return make_error<JITLinkError>(
diff --git a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
index 55389adb31b60..3c37c934fcd53 100644
--- a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
@@ -49,8 +49,12 @@ const char *getEdgeKindName(Edge::Kind K) {
KIND_NAME_CASE(Branch26PCRel)
KIND_NAME_CASE(Page20)
KIND_NAME_CASE(PageOffset12)
+ KIND_NAME_CASE(PCAdd20)
+ KIND_NAME_CASE(PCAdd12)
KIND_NAME_CASE(RequestGOTAndTransformToPage20)
KIND_NAME_CASE(RequestGOTAndTransformToPageOffset12)
+ KIND_NAME_CASE(RequestGOTAndTransformToPCAdd20)
+ KIND_NAME_CASE(Call30PCRel)
KIND_NAME_CASE(Call36PCRel)
KIND_NAME_CASE(Add6)
KIND_NAME_CASE(Add8)
More information about the llvm-branch-commits
mailing list