Skip to content

Commit 4c5c5e2

Browse files
authored
[JITLink][LoongArch] Add R_LARCH_{B16,B21} relocations support (llvm#121096)
1 parent 34097c0 commit 4c5c5e2

File tree

5 files changed

+130
-1
lines changed

5 files changed

+130
-1
lines changed

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

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,50 @@ enum EdgeKind_loongarch : Edge::Kind {
4141
///
4242
Pointer32,
4343

44+
/// A 16-bit PC-relative branch.
45+
///
46+
/// Represents a PC-relative branch to a target within +/-128Kb. The target
47+
/// must be 4-byte aligned.
48+
///
49+
/// Fixup expression:
50+
/// Fixup <- (Target - Fixup + Addend) >> 2 : int16
51+
///
52+
/// Notes:
53+
/// The '16' in the name refers to the number operand bits and follows the
54+
/// naming convention used by the corresponding ELF relocations. Since the low
55+
/// two bits must be zero (because of the 4-byte alignment of the target) the
56+
/// operand is effectively a signed 18-bit number.
57+
///
58+
/// Errors:
59+
/// - The result of the unshifted part of the fixup expression must be
60+
/// 4-byte aligned otherwise an alignment error will be returned.
61+
/// - The result of the fixup expression must fit into an int16 otherwise an
62+
/// out-of-range error will be returned.
63+
///
64+
Branch16PCRel,
65+
66+
/// A 21-bit PC-relative branch.
67+
///
68+
/// Represents a PC-relative branch to a target within +/-4Mb. The Target must
69+
/// be 4-byte aligned.
70+
///
71+
/// Fixup expression:
72+
/// Fixup <- (Target - Fixup + Addend) >> 2 : int21
73+
///
74+
/// Notes:
75+
/// The '21' in the name refers to the number operand bits and follows the
76+
/// naming convention used by the corresponding ELF relocations. Since the low
77+
/// two bits must be zero (because of the 4-byte alignment of the target) the
78+
/// operand is effectively a signed 23-bit number.
79+
///
80+
/// Errors:
81+
/// - The result of the unshifted part of the fixup expression must be
82+
/// 4-byte aligned otherwise an alignment error will be returned.
83+
/// - The result of the fixup expression must fit into an int21 otherwise an
84+
/// out-of-range error will be returned.
85+
///
86+
Branch21PCRel,
87+
4488
/// A 26-bit PC-relative branch.
4589
///
4690
/// Represents a PC-relative call or branch to a target within +/-128Mb. The
@@ -213,6 +257,37 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
213257
*(ulittle32_t *)FixupPtr = Value;
214258
break;
215259
}
260+
case Branch16PCRel: {
261+
int64_t Value = TargetAddress - FixupAddress + Addend;
262+
263+
if (!isInt<18>(Value))
264+
return makeTargetOutOfRangeError(G, B, E);
265+
266+
if (!isShiftedInt<16, 2>(Value))
267+
return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
268+
269+
uint32_t RawInstr = *(little32_t *)FixupPtr;
270+
uint32_t Imm = static_cast<uint32_t>(Value >> 2);
271+
uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10;
272+
*(little32_t *)FixupPtr = RawInstr | Imm15_0;
273+
break;
274+
}
275+
case Branch21PCRel: {
276+
int64_t Value = TargetAddress - FixupAddress + Addend;
277+
278+
if (!isInt<23>(Value))
279+
return makeTargetOutOfRangeError(G, B, E);
280+
281+
if (!isShiftedInt<21, 2>(Value))
282+
return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
283+
284+
uint32_t RawInstr = *(little32_t *)FixupPtr;
285+
uint32_t Imm = static_cast<uint32_t>(Value >> 2);
286+
uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10;
287+
uint32_t Imm20_16 = extractBits(Imm, /*Hi=*/20, /*Lo=*/16);
288+
*(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm20_16;
289+
break;
290+
}
216291
case Branch26PCRel: {
217292
int64_t Value = TargetAddress - FixupAddress + Addend;
218293

llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
5858
return Pointer32;
5959
case ELF::R_LARCH_32_PCREL:
6060
return Delta32;
61+
case ELF::R_LARCH_B16:
62+
return Branch16PCRel;
63+
case ELF::R_LARCH_B21:
64+
return Branch21PCRel;
6165
case ELF::R_LARCH_B26:
6266
return Branch26PCRel;
6367
case ELF::R_LARCH_PCALA_HI20:

llvm/lib/ExecutionEngine/JITLink/loongarch.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const char *getEdgeKindName(Edge::Kind K) {
4444
KIND_NAME_CASE(Delta32)
4545
KIND_NAME_CASE(NegDelta32)
4646
KIND_NAME_CASE(Delta64)
47+
KIND_NAME_CASE(Branch16PCRel)
48+
KIND_NAME_CASE(Branch21PCRel)
4749
KIND_NAME_CASE(Branch26PCRel)
4850
KIND_NAME_CASE(Page20)
4951
KIND_NAME_CASE(PageOffset12)

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,30 @@ test_gotoffset12_external:
103103
ld.w $a0, $a0, %got_pc_lo12(external_data)
104104
.size test_gotoffset12_external, .-test_gotoffset12_external
105105

106+
## Check R_LARCH_B16 relocation for compare and branch instructions.
107+
108+
# jitlink-check: decode_operand(test_br16, 2)[17:0] = \
109+
# jitlink-check: (test_br16_target - test_br16)[17:0]
110+
.globl test_br16, test_br16_target
111+
.p2align 2
112+
test_br16:
113+
beq $t1, $t2, %b16(test_br16_target)
114+
.skip (1 << 16)
115+
test_br16_target:
116+
.size test_br16, .-test_br16
117+
118+
## Check R_LARCH_B21 relocation for compare and branch instructions.
119+
120+
# jitlink-check: decode_operand(test_br21, 1)[22:0] = \
121+
# jitlink-check: (test_br21_target - test_br21)[22:0]
122+
.globl test_br21, test_br21_target
123+
.p2align 2
124+
test_br21:
125+
beqz $t1, %b21(test_br21_target)
126+
.skip (1 << 21)
127+
test_br21_target:
128+
.size test_br21, .-test_br21
129+
106130

107131
.globl named_data
108132
.p2align 4

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ test_gotoffset12_external:
116116
ld.d $a0, $a0, %got_pc_lo12(external_data)
117117
.size test_gotoffset12_external, .-test_gotoffset12_external
118118

119-
120119
## Check R_LARCH_CALL36 relocation of a local function call.
121120

122121
# jitlink-check: decode_operand(local_func_call36, 1)[19:0] = \
@@ -130,6 +129,31 @@ local_func_call36:
130129
jirl $ra, $ra, 0
131130
.size local_func_call36, .-local_func_call36
132131

132+
## Check R_LARCH_B16 relocation for compare and branch instructions.
133+
134+
# jitlink-check: decode_operand(test_br16, 2)[17:0] = \
135+
# jitlink-check: (test_br16_target - test_br16)[17:0]
136+
.globl test_br16, test_br16_target
137+
.p2align 2
138+
test_br16:
139+
beq $t1, $t2, %b16(test_br16_target)
140+
.skip (1 << 16)
141+
test_br16_target:
142+
.size test_br16, .-test_br16
143+
144+
## Check R_LARCH_B21 relocation for compare and branch instructions.
145+
146+
# jitlink-check: decode_operand(test_br21, 1)[22:0] = \
147+
# jitlink-check: (test_br21_target - test_br21)[22:0]
148+
.globl test_br21, test_br21_target
149+
.p2align 2
150+
test_br21:
151+
beqz $t1, %b21(test_br21_target)
152+
.skip (1 << 21)
153+
test_br21_target:
154+
.size test_br21, .-test_br21
155+
156+
133157
.globl named_data
134158
.p2align 4
135159
.type named_data,@object

0 commit comments

Comments
 (0)