@@ -158,15 +158,38 @@ enum EdgeKind_loongarch : Edge::Kind {
158
158
// / NONE
159
159
// /
160
160
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,
161
184
};
162
185
163
186
// / Returns a string name for the given loongarch edge. For debugging purposes
164
187
// / only.
165
188
const char *getEdgeKindName (Edge::Kind K);
166
189
167
190
// 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;
170
193
}
171
194
172
195
// / Apply fixup expression for edge to block content.
@@ -247,6 +270,23 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
247
270
*(ulittle32_t *)FixupPtr = RawInstr | Imm11_0;
248
271
break ;
249
272
}
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
+ }
250
290
default :
251
291
return make_error<JITLinkError>(
252
292
" In graph " + G.getName () + " , section " + B.getSection ().getName () +
@@ -363,7 +403,8 @@ class PLTTableManager : public TableManager<PLTTableManager> {
363
403
static StringRef getSectionName () { return " $__STUBS" ; }
364
404
365
405
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 ()) {
367
408
DEBUG_WITH_TYPE (" jitlink" , {
368
409
dbgs () << " Fixing " << G.getEdgeKindName (E.getKind ()) << " edge at "
369
410
<< B->getFixupAddress (E) << " (" << B->getAddress () << " + "
0 commit comments