https://github.com/heiher created https://github.com/llvm/llvm-project/pull/175353
None >From 5c03040af7b680b051fd5a938fcd16f3454876a2 Mon Sep 17 00:00:00 2001 From: WANG Rui <[email protected]> Date: Wed, 31 Dec 2025 09:51:43 +0800 Subject: [PATCH] [JITLink][LoongArch] Add reloc types for LA32R/LA32S --- .../llvm/ExecutionEngine/JITLink/loongarch.h | 73 +++++++++++++++- .../ExecutionEngine/JITLink/ELF_loongarch.cpp | 85 ++++++++++++++++++- .../lib/ExecutionEngine/JITLink/loongarch.cpp | 4 + 3 files changed, 160 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h index 1bb18e38bab33..cb3c1919d65d1 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h @@ -170,6 +170,30 @@ enum EdgeKind_loongarch : Edge::Kind { /// PageOffset12, + /// The upper 20 bits of the offset from the fixup to the target. + /// + /// Fixup expression: + /// Fixup <- (Target + Addend - Fixup + 0x800) >> 12 : int20 + /// + /// Notes: + /// For PCADDU12I fixups. + /// + /// Errors: + /// - The result of the fixup expression must fit into an int20 otherwise an + /// out-of-range error will be returned. + /// + PCAdd20, + + /// The lower 12 bits of the offset from the paired PCADDU12I (the initial + /// target) to the final target it points to. + /// + /// Typically used to fix up ADDI/LD_W/LD_D immediates. + /// + /// Fixup expression: + /// Fixup <- (FinalTarget - InitialTarget) & 0xfff : int12 + /// + PCAdd12, + /// A GOT entry getter/constructor, transformed to Page20 pointing at the GOT /// entry for the original target. /// @@ -206,6 +230,49 @@ enum EdgeKind_loongarch : Edge::Kind { /// RequestGOTAndTransformToPageOffset12, + /// A GOT entry getter/constructor, transformed to PCAdd20 pointing at the GOT + /// entry for the original target. + /// + /// Indicates that this edge should be transformed into a PCAdd20 targeting + /// the GOT entry for the edge's current target, maintaining the same addend. + /// A GOT entry for the target should be created if one does not already + /// exist. + /// + /// Edges of this kind are usually handled by a GOT/PLT builder pass inserted + /// by default. + /// + /// Fixup expression: + /// NONE + /// + /// Errors: + /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup + /// phase will result in an assert/unreachable during the fixup phase. + /// + RequestGOTAndTransformToPCAdd20, + + /// A 30-bit PC-relative call. + /// + /// Represents a PC-relative call to a target within [-4G, +4G) + /// The target must be 4-byte aligned. For adjacent pcaddu12i+jirl + /// instruction pairs. + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) >> 2 : int30 + /// + /// Notes: + /// The '30' 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 32-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 int30 otherwise an + /// out-of-range error will be returned. + /// + Call30PCRel, + /// A 36-bit PC-relative call. /// /// Represents a PC-relative call to a target within [-128G - 0x20000, +128G @@ -399,6 +466,9 @@ class GOTTableManager : public TableManager<GOTTableManager> { case RequestGOTAndTransformToPageOffset12: KindToSet = PageOffset12; break; + case RequestGOTAndTransformToPCAdd20: + KindToSet = PCAdd20; + break; default: return false; } @@ -437,7 +507,8 @@ class PLTTableManager : public TableManager<PLTTableManager> { static StringRef getSectionName() { return "$__STUBS"; } bool visitEdge(LinkGraph &G, Block *B, Edge &E) { - if ((E.getKind() == Branch26PCRel || E.getKind() == Call36PCRel) && + if ((E.getKind() == Branch26PCRel || E.getKind() == Call36PCRel || + E.getKind() == Call30PCRel) && !E.getTarget().isDefined()) { DEBUG_WITH_TYPE("jitlink", { dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp index ee4a3280f18c4..497635941a887 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp @@ -37,9 +37,41 @@ class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> { ELFJITLinker_loongarch(std::unique_ptr<JITLinkContext> Ctx, std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig) - : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {} + : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) { + JITLinkerBase::getPassConfig().PostAllocationPasses.push_back( + [this](LinkGraph &G) { return gatherLoongArchPCAdd20(G); }); + } private: + DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *> + RelPCAdd20Map; + + Error gatherLoongArchPCAdd20(LinkGraph &G) { + for (Block *B : G.blocks()) + for (Edge &E : B->edges()) + if (E.getKind() == PCAdd20) + RelPCAdd20Map[{B, E.getOffset()}] = &E; + + return Error::success(); + } + + Expected<const Edge &> getLoongArchPCAdd20(const Edge &E) const { + using namespace loongarch; + assert((E.getKind() == PCAdd12) && + "Can only have high relocation for PCAdd12"); + + const Symbol &Sym = E.getTarget(); + const Block &B = Sym.getBlock(); + orc::ExecutorAddrDiff Offset = Sym.getOffset() + E.getAddend(); + + auto It = RelPCAdd20Map.find({&B, Offset}); + if (It != RelPCAdd20Map.end()) + return *It->second; + + return make_error<JITLinkError>("No PCAdd20 relocation type be found " + "for PCAdd12 relocation type"); + } + /// Apply fixup expression for edge to block content. Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { using namespace support; @@ -149,6 +181,48 @@ class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> { *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0; break; } + case PCAdd20: { + uint64_t Target = TargetAddress + Addend; + int64_t Delta = Target - FixupAddress + 0x800; + + if (!isInt<32>(Delta)) + return makeTargetOutOfRangeError(G, B, E); + + uint32_t RawInstr = *(little32_t *)FixupPtr; + uint32_t Imm31_12 = extractBits(Delta, /*Hi=*/31, /*Lo=*/12) << 5; + *(little32_t *)FixupPtr = RawInstr | Imm31_12; + break; + } + case PCAdd12: { + auto RelPCAdd20 = getLoongArchPCAdd20(E); + if (!RelPCAdd20) + return RelPCAdd20.takeError(); + int64_t Delta = + (RelPCAdd20->getTarget().getAddress() + RelPCAdd20->getAddend()) - + (E.getTarget().getAddress() + E.getAddend()); + + uint32_t RawInstr = *(ulittle32_t *)FixupPtr; + uint32_t Imm11_0 = extractBits(Delta, /*Hi=*/11, /*Lo=*/0) << 10; + *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0; + break; + } + case Call30PCRel: { + int64_t Value = TargetAddress - FixupAddress + Addend; + + if (Value != llvm::SignExtend64(Value, 32)) + return makeTargetOutOfRangeError(G, B, E); + + if (!isShiftedInt<30, 2>(Value)) + return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); + + uint32_t Pcaddu12i = *(little32_t *)FixupPtr; + uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/31, /*Lo=*/12) << 5; + *(little32_t *)FixupPtr = Pcaddu12i | Hi20; + uint32_t Jirl = *(little32_t *)(FixupPtr + 4); + uint32_t Lo10 = extractBits(Value, /*Hi=*/11, /*Lo=*/2) << 10; + *(little32_t *)(FixupPtr + 4) = Jirl | Lo10; + break; + } case Call36PCRel: { int64_t Value = TargetAddress - FixupAddress + Addend; @@ -534,6 +608,8 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> { return RequestGOTAndTransformToPage20; case ELF::R_LARCH_GOT_PC_LO12: return RequestGOTAndTransformToPageOffset12; + case ELF::R_LARCH_CALL30: + return Call30PCRel; case ELF::R_LARCH_CALL36: return Call36PCRel; case ELF::R_LARCH_ADD6: @@ -562,6 +638,13 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> { return SubUleb128; case ELF::R_LARCH_ALIGN: return AlignRelaxable; + case ELF::R_LARCH_PCADD_HI20: + return PCAdd20; + case ELF::R_LARCH_PCADD_LO12: + case ELF::R_LARCH_GOT_PCADD_LO12: + return PCAdd12; + case ELF::R_LARCH_GOT_PCADD_HI20: + return RequestGOTAndTransformToPCAdd20; } return make_error<JITLinkError>( diff --git a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp index 55389adb31b60..3c37c934fcd53 100644 --- a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp @@ -49,8 +49,12 @@ const char *getEdgeKindName(Edge::Kind K) { KIND_NAME_CASE(Branch26PCRel) KIND_NAME_CASE(Page20) KIND_NAME_CASE(PageOffset12) + KIND_NAME_CASE(PCAdd20) + KIND_NAME_CASE(PCAdd12) KIND_NAME_CASE(RequestGOTAndTransformToPage20) KIND_NAME_CASE(RequestGOTAndTransformToPageOffset12) + KIND_NAME_CASE(RequestGOTAndTransformToPCAdd20) + KIND_NAME_CASE(Call30PCRel) KIND_NAME_CASE(Call36PCRel) KIND_NAME_CASE(Add6) KIND_NAME_CASE(Add8) _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
