Skip to content

Commit ca9f358

Browse files
authored
[JITLink][LoongArch] Add support for R_LARCH_CALL36 relocation
This relocation is used for function calls with medium code model. Reviewed By: lhames, SixWeining Pull Request: #117127
1 parent 8223982 commit ca9f358

File tree

4 files changed

+73
-3
lines changed

4 files changed

+73
-3
lines changed

llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,38 @@ enum EdgeKind_loongarch : Edge::Kind {
158158
/// NONE
159159
///
160160
RequestGOTAndTransformToPageOffset12,
161+
162+
/// A 36-bit PC-relative call.
163+
///
164+
/// Represents a PC-relative call to a target within [-128G - 0x20000, +128G
165+
/// - 0x20000). The target must be 4-byte aligned. For adjacent pcaddu18i+jirl
166+
/// instruction pairs.
167+
///
168+
/// Fixup expression:
169+
/// Fixup <- (Target - Fixup + Addend) >> 2 : int36
170+
///
171+
/// Notes:
172+
/// The '36' in the name refers to the number operand bits and follows the
173+
/// naming convention used by the corresponding ELF relocations. Since the low
174+
/// two bits must be zero (because of the 4-byte alignment of the target) the
175+
/// operand is effectively a signed 38-bit number.
176+
///
177+
/// Errors:
178+
/// - The result of the unshifted part of the fixup expression must be
179+
/// 4-byte aligned otherwise an alignment error will be returned.
180+
/// - The result of the fixup expression must fit into an int36 otherwise an
181+
/// out-of-range error will be returned.
182+
///
183+
Call36PCRel,
161184
};
162185

163186
/// Returns a string name for the given loongarch edge. For debugging purposes
164187
/// only.
165188
const char *getEdgeKindName(Edge::Kind K);
166189

167190
// Returns extract bits Val[Hi:Lo].
168-
inline uint32_t extractBits(uint32_t Val, unsigned Hi, unsigned Lo) {
169-
return (Val & (((1UL << (Hi + 1)) - 1))) >> Lo;
191+
inline uint32_t extractBits(uint64_t Val, unsigned Hi, unsigned Lo) {
192+
return Hi == 63 ? Val >> Lo : (Val & (((1UL << (Hi + 1)) - 1))) >> Lo;
170193
}
171194

172195
/// Apply fixup expression for edge to block content.
@@ -247,6 +270,23 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
247270
*(ulittle32_t *)FixupPtr = RawInstr | Imm11_0;
248271
break;
249272
}
273+
case Call36PCRel: {
274+
int64_t Value = TargetAddress - FixupAddress + Addend;
275+
276+
if ((Value + 0x20000) != llvm::SignExtend64(Value + 0x20000, 38))
277+
return makeTargetOutOfRangeError(G, B, E);
278+
279+
if (!isShiftedInt<36, 2>(Value))
280+
return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
281+
282+
uint32_t Pcaddu18i = *(little32_t *)FixupPtr;
283+
uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/37, /*Lo=*/18) << 5;
284+
*(little32_t *)FixupPtr = Pcaddu18i | Hi20;
285+
uint32_t Jirl = *(little32_t *)(FixupPtr + 4);
286+
uint32_t Lo16 = extractBits(Value, /*Hi=*/17, /*Lo=*/2) << 10;
287+
*(little32_t *)(FixupPtr + 4) = Jirl | Lo16;
288+
break;
289+
}
250290
default:
251291
return make_error<JITLinkError>(
252292
"In graph " + G.getName() + ", section " + B.getSection().getName() +
@@ -363,7 +403,8 @@ class PLTTableManager : public TableManager<PLTTableManager> {
363403
static StringRef getSectionName() { return "$__STUBS"; }
364404

365405
bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
366-
if (E.getKind() == Branch26PCRel && !E.getTarget().isDefined()) {
406+
if ((E.getKind() == Branch26PCRel || E.getKind() == Call36PCRel) &&
407+
!E.getTarget().isDefined()) {
367408
DEBUG_WITH_TYPE("jitlink", {
368409
dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
369410
<< B->getFixupAddress(E) << " (" << B->getAddress() << " + "

llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
6868
return RequestGOTAndTransformToPage20;
6969
case ELF::R_LARCH_GOT_PC_LO12:
7070
return RequestGOTAndTransformToPageOffset12;
71+
case ELF::R_LARCH_CALL36:
72+
return Call36PCRel;
7173
}
7274

7375
return make_error<JITLinkError>(

llvm/lib/ExecutionEngine/JITLink/loongarch.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const char *getEdgeKindName(Edge::Kind K) {
4949
KIND_NAME_CASE(PageOffset12)
5050
KIND_NAME_CASE(RequestGOTAndTransformToPage20)
5151
KIND_NAME_CASE(RequestGOTAndTransformToPageOffset12)
52+
KIND_NAME_CASE(Call36PCRel)
5253
default:
5354
return getGenericEdgeKindName(K);
5455
}

llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_loongarch64_relocations.s

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ test_addi_pcrel_lo12:
6868
# jitlink-check: decode_operand(test_external_jump, 0) = \
6969
# jitlink-check: (stub_addr(elf_reloc.o, external_func) - \
7070
# jitlink-check: test_external_jump)[27:0]
71+
# jitlink-check: decode_operand(test_external_call36, 1)[19:0] = \
72+
# jitlink-check: (stub_addr(elf_reloc.o, external_func) - \
73+
# jitlink-check: test_external_call36 + (1<<17))[37:18]
74+
# jitlink-check: decode_operand(test_external_call36 + 4, 2)[17:0] = \
75+
# jitlink-check: (stub_addr(elf_reloc.o, external_func) - \
76+
# jitlink-check: test_external_call36)[17:0]
7177
.globl test_external_call
7278
.p2align 2
7379
test_external_call:
@@ -80,6 +86,13 @@ test_external_jump:
8086
b external_func
8187
.size test_external_jump, .-test_external_jump
8288

89+
.globl test_external_call36
90+
.p2align 2
91+
test_external_call36:
92+
pcaddu18i $ra, %call36(external_func)
93+
jirl $ra, $ra, 0
94+
.size test_external_call36, .-test_external_call36
95+
8396
## Check R_LARCH_GOT_PC_HI20 / R_LARCH_GOT_PC_LO12 handling with a reference to
8497
## an external symbol. Validate both the reference to the GOT entry, and also
8598
## the content of the GOT entry.
@@ -104,6 +117,19 @@ test_gotoffset12_external:
104117
.size test_gotoffset12_external, .-test_gotoffset12_external
105118

106119

120+
## Check R_LARCH_CALL36 relocation of a local function call.
121+
122+
# jitlink-check: decode_operand(local_func_call36, 1)[19:0] = \
123+
# jitlink-check: ((local_func - local_func_call36) + (1<<17))[37:18]
124+
# jitlink-check: decode_operand(local_func_call36 + 4, 2)[17:0] = \
125+
# jitlink-check: (local_func - local_func_call36)[17:0]
126+
.globl local_func_call36
127+
.p2align 2
128+
local_func_call36:
129+
pcaddu18i $ra, %call36(local_func)
130+
jirl $ra, $ra, 0
131+
.size local_func_call36, .-local_func_call36
132+
107133
.globl named_data
108134
.p2align 4
109135
.type named_data,@object

0 commit comments

Comments
 (0)