@@ -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.
165188const 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 () << " + "
0 commit comments