[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