- Notifications
You must be signed in to change notification settings - Fork 15.6k
[llvm][LoongArch] Add reloc types for LA32R/LA32S #172617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This patch introduces the relocation types added in la-abi-sepcs v2.50, enabling support for LoongArch32 Reduced and Standard variants. Link: loongson/la-abi-specs#16 Link: https://sourceware.org/pipermail/binutils/2025-December/146091.html Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-December/703312.html
| @llvm/pr-subscribers-lld-elf @llvm/pr-subscribers-lld Author: hev (heiher) ChangesThis patch introduces the relocation types added in la-abi-sepcs v2.50, enabling support for LoongArch32 Reduced and Standard variants. Link: loongson/la-abi-specs#16 Patch is 173.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/172617.diff 54 Files Affected:
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s index 79353f2a3be47..b9da1322a8c00 100644 --- a/lld/test/ELF/loongarch-relax-align.s +++ b/lld/test/ELF/loongarch-relax-align.s @@ -1,7 +1,7 @@ # REQUIRES: loongarch -# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o -# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s,+relax %s -o %t.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+32s,+relax %s -o %t.64.o # RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o -o %t.32 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o -o %t.64 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.32.o -o %t.32n diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s index 909b65075a695..6e1e85c004439 100644 --- a/lld/test/ELF/loongarch-relax-emit-relocs.s +++ b/lld/test/ELF/loongarch-relax-emit-relocs.s @@ -1,7 +1,7 @@ # REQUIRES: loongarch ## Test that we can handle --emit-relocs while relaxing. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s,+relax %s -o %t.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax --defsym ELF64=1 %s -o %t.64.o # RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.32.o -o %t.32 # RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.64.o -o %t.64 diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s index f37de8e3b7c83..fe243397af346 100644 --- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s +++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s @@ -4,9 +4,9 @@ # REQUIRES: loongarch # RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax symbols.s -o symbols.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax symbols.s -o symbols.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax symbols.s -o symbols.64.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax abs.s -o abs.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax abs.s -o abs.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax abs.s -o abs.64.o # RUN: ld.lld --shared -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s index 08d5d3e950d84..28ce704d2ea42 100644 --- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s +++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s @@ -1,7 +1,7 @@ # REQUIRES: loongarch # RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax a.s -o a.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax a.s -o a.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax a.s -o a.64.o # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.32.o -o a.32 @@ -54,7 +54,7 @@ ## GOT references with non-zero addends. No relaxation. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax nonzero.s -o nonzero.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax nonzero.s -o nonzero.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax nonzero.s -o nonzero.64.o # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.32.o -o nonzero.32 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.64.o -o nonzero.64 diff --git a/lld/test/ELF/loongarch-relocatable-align.s b/lld/test/ELF/loongarch-relocatable-align.s index 747a58ed61eaa..c02007f9f719b 100644 --- a/lld/test/ELF/loongarch-relocatable-align.s +++ b/lld/test/ELF/loongarch-relocatable-align.s @@ -57,8 +57,8 @@ # CHECK-REL: Relocation section '.rela.text1' at offset {{.*}} contains 5 entries: ## Test LA32. -# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+relax a.s -o a.32.o -# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+relax b.s -o b.32.o +# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+32s,+relax a.s -o a.32.o +# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+32s,+relax b.s -o b.32.o # RUN: ld.lld -r a.32.o b.32.o -o out.32.ro # RUN: ld.lld -Ttext=0x10000 out.32.ro -o out32 # RUN: llvm-objdump -dr --no-show-raw-insn out32 | FileCheck %s --check-prefix=CHECK32 diff --git a/lld/test/ELF/loongarch-tls-gd-edge-case.s b/lld/test/ELF/loongarch-tls-gd-edge-case.s index 9f25f10c73b44..dd87d3002b180 100644 --- a/lld/test/ELF/loongarch-tls-gd-edge-case.s +++ b/lld/test/ELF/loongarch-tls-gd-edge-case.s @@ -3,7 +3,7 @@ ## Edge case: when a TLS symbol is being accessed in both GD and IE manners, ## correct reloc behavior should be preserved for both kinds of accesses. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %s -o %t.la32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s %s -o %t.la32.o # RUN: ld.lld %t.la32.o -shared -o %t.la32 # RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t.la64.o # RUN: ld.lld %t.la64.o -shared -o %t.la64 diff --git a/lld/test/ELF/loongarch-tls-gd.s b/lld/test/ELF/loongarch-tls-gd.s index 140aa4cea6bad..9a4ccfa2201a4 100644 --- a/lld/test/ELF/loongarch-tls-gd.s +++ b/lld/test/ELF/loongarch-tls-gd.s @@ -5,11 +5,11 @@ ## (a) code sequence can be converted from `pcalau12i+addi.[wd]` to `pcaddi`. ## (b) dynamic relocations can be omitted for GD->LE relaxation. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/a.s -o %t/a.32.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %t/a.s -o %t/a.32.relax.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/bc.s -o %t/bc.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s %t/a.s -o %t/a.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax %t/a.s -o %t/a.32.relax.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s %t/bc.s -o %t/bc.32.o # RUN: ld.lld -shared -soname=bc.so %t/bc.32.o -o %t/bc.32.so -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/tga.s -o %t/tga.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s %t/tga.s -o %t/tga.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/a.s -o %t/a.64.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/a.s -mattr=+relax -o %t/a.64.relax.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/bc.s -o %t/bc.64.o diff --git a/lld/test/ELF/loongarch-tls-ie.s b/lld/test/ELF/loongarch-tls-ie.s index ddfd9c976cb9b..e7e9617dd3efc 100644 --- a/lld/test/ELF/loongarch-tls-ie.s +++ b/lld/test/ELF/loongarch-tls-ie.s @@ -1,7 +1,7 @@ # REQUIRES: loongarch # RUN: rm -rf %t && split-file %s %t -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/32.s -o %t/32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s %t/32.s -o %t/32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/64.s -o %t/64.o ## LA32 IE diff --git a/lld/test/ELF/loongarch-tls-ld.s b/lld/test/ELF/loongarch-tls-ld.s index 27adb1e17702a..65be2f8fd36e4 100644 --- a/lld/test/ELF/loongarch-tls-ld.s +++ b/lld/test/ELF/loongarch-tls-ld.s @@ -5,9 +5,9 @@ ## (a) code sequence can be converted from `pcalau12i+addi.[wd]` to `pcaddi`. ## (b) dynamic relocations can be omitted for LD->LE relaxation. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent %t/a.s -o %t/a.32.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent -mattr=+relax %t/a.s -o %t/a.32.relax.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/tga.s -o %t/tga.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent -mattr=+32s %t/a.s -o %t/a.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent -mattr=+32s,+relax %t/a.s -o %t/a.32.relax.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s %t/tga.s -o %t/tga.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 --position-independent %t/a.s -o %t/a.64.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 --position-independent -mattr=+relax %t/a.s -o %t/a.64.relax.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/tga.s -o %t/tga.64.o diff --git a/lld/test/ELF/loongarch-tlsdesc.s b/lld/test/ELF/loongarch-tlsdesc.s index 3dc31210d7ddb..7d07c66606a87 100644 --- a/lld/test/ELF/loongarch-tlsdesc.s +++ b/lld/test/ELF/loongarch-tlsdesc.s @@ -3,8 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple=loongarch64 a.s -o a.64.o # RUN: llvm-mc -filetype=obj -triple=loongarch64 c.s -o c.64.o # RUN: ld.lld -shared -soname=c.64.so c.64.o -o c.64.so -# RUN: llvm-mc -filetype=obj -triple=loongarch32 --defsym ELF32=1 a.s -o a.32.o -# RUN: llvm-mc -filetype=obj -triple=loongarch32 --defsym ELF32=1 c.s -o c.32.o +# RUN: llvm-mc -filetype=obj -triple=loongarch32 --mattr=+32s --defsym ELF32=1 a.s -o a.32.o +# RUN: llvm-mc -filetype=obj -triple=loongarch32 --mattr=+32s --defsym ELF32=1 c.s -o c.32.o # RUN: ld.lld -shared -soname=c.32.so c.32.o -o c.32.so # RUN: ld.lld -shared -z now a.64.o c.64.o -o a.64.so diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def index 4859057abcbb9..96e2c1645b57a 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def @@ -149,3 +149,21 @@ ELF_RELOC(R_LARCH_TLS_LE_LO12_R, 123) ELF_RELOC(R_LARCH_TLS_LD_PCREL20_S2, 124) ELF_RELOC(R_LARCH_TLS_GD_PCREL20_S2, 125) ELF_RELOC(R_LARCH_TLS_DESC_PCREL20_S2, 126) + +// Relocs added in ELF for the LoongArch™ Architecture v20251210, part of the +// v2.50 LoongArch ABI specs. +// +// Spec addition: https://github.com/loongson/la-abi-specs/pull/16 +ELF_RELOC(R_LARCH_CALL30, 127) +ELF_RELOC(R_LARCH_PCADD_HI20, 128) +ELF_RELOC(R_LARCH_PCADD_LO12, 129) +ELF_RELOC(R_LARCH_GOT_PCADD_HI20, 130) +ELF_RELOC(R_LARCH_GOT_PCADD_LO12, 131) +ELF_RELOC(R_LARCH_TLS_IE_PCADD_HI20, 132) +ELF_RELOC(R_LARCH_TLS_IE_PCADD_LO12, 133) +ELF_RELOC(R_LARCH_TLS_LD_PCADD_HI20, 134) +ELF_RELOC(R_LARCH_TLS_LD_PCADD_LO12, 135) +ELF_RELOC(R_LARCH_TLS_GD_PCADD_HI20, 136) +ELF_RELOC(R_LARCH_TLS_GD_PCADD_LO12, 137) +ELF_RELOC(R_LARCH_TLS_DESC_PCADD_HI20, 138) +ELF_RELOC(R_LARCH_TLS_DESC_PCADD_LO12, 139) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h index 04c5a67ac4fe3..1d9038a6fe2d8 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 @@ -330,238 +397,6 @@ inline uint32_t extractBits(uint64_t Val, unsigned Hi, unsigned Lo) { return Hi == 63 ? Val >> Lo : (Val & ((((uint64_t)1 << (Hi + 1)) - 1))) >> Lo; } -/// Apply fixup expression for edge to block content. -inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) { - using namespace support; - - char *BlockWorkingMem = B.getAlreadyMutableContent().data(); - char *FixupPtr = BlockWorkingMem + E.getOffset(); - uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue(); - uint64_t TargetAddress = E.getTarget().getAddress().getValue(); - int64_t Addend = E.getAddend(); - - switch (E.getKind()) { - case Pointer64: - *(ulittle64_t *)FixupPtr = TargetAddress + Addend; - break; - case Pointer32: { - uint64_t Value = TargetAddress + Addend; - if (Value > std::numeric_limits<uint32_t>::max()) - return makeTargetOutOfRangeError(G, B, E); - *(ulittle32_t *)FixupPtr = Value; - break; - } - case Branch16PCRel: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if (!isInt<18>(Value)) - return makeTargetOutOfRangeError(G, B, E); - - if (!isShiftedInt<16, 2>(Value)) - return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); - - uint32_t RawInstr = *(little32_t *)FixupPtr; - uint32_t Imm = static_cast<uint32_t>(Value >> 2); - uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10; - *(little32_t *)FixupPtr = RawInstr | Imm15_0; - break; - } - case Branch21PCRel: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if (!isInt<23>(Value)) - return makeTargetOutOfRangeError(G, B, E); - - if (!isShiftedInt<21, 2>(Value)) - return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); - - uint32_t RawInstr = *(little32_t *)FixupPtr; - uint32_t Imm = static_cast<uint32_t>(Value >> 2); - uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10; - uint32_t Imm20_16 = extractBits(Imm, /*Hi=*/20, /*Lo=*/16); - *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm20_16; - break; - } - case Branch26PCRel: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if (!isInt<28>(Value)) - return makeTargetOutOfRangeError(G, B, E); - - if (!isShiftedInt<26, 2>(Value)) - return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); - - uint32_t RawInstr = *(little32_t *)FixupPtr; - uint32_t Imm = static_cast<uint32_t>(Value >> 2); - uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10; - uint32_t Imm25_16 = extractBits(Imm, /*Hi=*/25, /*Lo=*/16); - *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm25_16; - break; - } - case Delta32: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if (!isInt<32>(Value)) - return makeTargetOutOfRangeError(G, B, E); - *(little32_t *)FixupPtr = Value; - break; - } - case NegDelta32: { - int64_t Value = FixupAddress - TargetAddress + Addend; - if (!isInt<32>(Value)) - return makeTargetOutOfRangeError(G, B, E); - *(little32_t *)FixupPtr = Value; - break; - } - case Delta64: - *(little64_t *)FixupPtr = TargetAddress - FixupAddress + Addend; - break; - case Page20: { - uint64_t Target = TargetAddress + Addend; - uint64_t TargetPage = - (Target + (Target & 0x800)) & ~static_cast<uint64_t>(0xfff); - uint64_t PCPage = FixupAddress & ~static_cast<uint64_t>(0xfff); - - int64_t PageDelta = TargetPage - PCPage; - if (!isInt<32>(PageDelta)) - return makeTargetOutOfRangeError(G, B, E); - - uint32_t RawInstr = *(little32_t *)FixupPtr; - uint32_t Imm31_12 = extractBits(PageDelta, /*Hi=*/31, /*Lo=*/12) << 5; - *(little32_t *)FixupPtr = RawInstr | Imm31_12; - break; - } - case PageOffset12: { - uint64_t TargetOffset = (TargetAddress + Addend) & 0xfff; - - uint32_t RawInstr = *(ulittle32_t *)FixupPtr; - uint32_t Imm11_0 = TargetOffset << 10; - *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0; - break; - } - case Call36PCRel: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if ((Value + 0x20000) != llvm::SignExtend64(Value + 0x20000, 38)) - return makeTargetOutOfRangeError(G, B, E); - - if (!isShiftedInt<36, 2>(Value)) - return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); - - uint32_t Pcaddu18i = *(little32_t *)FixupPtr; - uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/37, /*Lo=*/18) << 5; - *(little32_t *)FixupPtr = Pcaddu18i | Hi20; - uint32_t Jirl = *(little32_t *)(FixupPtr + 4); - uint32_t Lo16 = extractBits(Value, /*Hi=*/17, /*Lo=*/2) << 10; - *(little32_t *)(FixupPtr + 4) = Jirl | Lo16; - break; - } - case Add6: { - int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr)); - Value += ((TargetAddress + Addend) & 0x3f); - *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<int8_t>(Value) & 0x3f); - break; - } - case Add8: { - int64_t Value = - TargetAddress + *(reinterpret_cast<const int8_t *>(FixupPtr)) + Addend; - *FixupPtr = static_cast<int8_t>(Value); - break; - } - case Add16: { - int64_t Value = - TargetAddress + support::endian::read16le(FixupPtr) + Addend; - *(little16_t *)FixupPtr = static_cast<int16_t>(Value); - break; - } - case Add32: { - int64_t Value = - TargetAddress + support::endian::read32le(FixupPtr) + Addend; - *(little32_t *)FixupPtr = static_cast<int32_t>(Value); - break; - } - case Add64: { - int64_t Value = - TargetAddress + support::endian::read64le(FixupPtr) + Addend; - *(little64_t *)FixupPtr = static_cast<int64_t>(Value); - break; - } - case AddUleb128: { - const uint32_t Maxcount = 1 + 64 / 7; - uint32_t Count; - const char *Error = nullptr; - uint64_t Orig = decodeULEB128((reinterpret_cast<const uint8_t *>(FixupPtr)), - &Count, nullptr, &Error); - - if (Count > Maxcount || (Count == Maxcount && Error)) - return make_error<JITLinkError>( - "0x" + llvm::utohexstr(orc::ExecutorAddr(FixupAddress).getValue()) + - ": extra space for uleb128"); - - uint64_t Mask = Count < Maxcount ? (1ULL << 7 * Count) - 1 : -1ULL; - encodeULEB128((Orig + TargetAddress + Addend) & Mask, - (reinterpret_cast<uint8_t *>(FixupPtr)), Count); - break; - } - case Sub6: { - int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr)); - Value -= ((TargetAddress + Addend) & 0x3f); - *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<int8_t>(Value) & 0x3f); - break; - } - case Sub8: { - int64_t Value = - *(reinterpret_cast<const int8_... [truncated] |
| @llvm/pr-subscribers-llvm-binary-utilities Author: hev (heiher) ChangesThis patch introduces the relocation types added in la-abi-sepcs v2.50, enabling support for LoongArch32 Reduced and Standard variants. Link: loongson/la-abi-specs#16 Patch is 173.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/172617.diff 54 Files Affected:
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s index 79353f2a3be47..b9da1322a8c00 100644 --- a/lld/test/ELF/loongarch-relax-align.s +++ b/lld/test/ELF/loongarch-relax-align.s @@ -1,7 +1,7 @@ # REQUIRES: loongarch -# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o -# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s,+relax %s -o %t.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+32s,+relax %s -o %t.64.o # RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o -o %t.32 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o -o %t.64 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.32.o -o %t.32n diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s index 909b65075a695..6e1e85c004439 100644 --- a/lld/test/ELF/loongarch-relax-emit-relocs.s +++ b/lld/test/ELF/loongarch-relax-emit-relocs.s @@ -1,7 +1,7 @@ # REQUIRES: loongarch ## Test that we can handle --emit-relocs while relaxing. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s,+relax %s -o %t.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax --defsym ELF64=1 %s -o %t.64.o # RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.32.o -o %t.32 # RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.64.o -o %t.64 diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s index f37de8e3b7c83..fe243397af346 100644 --- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s +++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s @@ -4,9 +4,9 @@ # REQUIRES: loongarch # RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax symbols.s -o symbols.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax symbols.s -o symbols.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax symbols.s -o symbols.64.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax abs.s -o abs.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax abs.s -o abs.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax abs.s -o abs.64.o # RUN: ld.lld --shared -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s index 08d5d3e950d84..28ce704d2ea42 100644 --- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s +++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s @@ -1,7 +1,7 @@ # REQUIRES: loongarch # RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax a.s -o a.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax a.s -o a.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax a.s -o a.64.o # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.32.o -o a.32 @@ -54,7 +54,7 @@ ## GOT references with non-zero addends. No relaxation. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax nonzero.s -o nonzero.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax nonzero.s -o nonzero.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax nonzero.s -o nonzero.64.o # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.32.o -o nonzero.32 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.64.o -o nonzero.64 diff --git a/lld/test/ELF/loongarch-relocatable-align.s b/lld/test/ELF/loongarch-relocatable-align.s index 747a58ed61eaa..c02007f9f719b 100644 --- a/lld/test/ELF/loongarch-relocatable-align.s +++ b/lld/test/ELF/loongarch-relocatable-align.s @@ -57,8 +57,8 @@ # CHECK-REL: Relocation section '.rela.text1' at offset {{.*}} contains 5 entries: ## Test LA32. -# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+relax a.s -o a.32.o -# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+relax b.s -o b.32.o +# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+32s,+relax a.s -o a.32.o +# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+32s,+relax b.s -o b.32.o # RUN: ld.lld -r a.32.o b.32.o -o out.32.ro # RUN: ld.lld -Ttext=0x10000 out.32.ro -o out32 # RUN: llvm-objdump -dr --no-show-raw-insn out32 | FileCheck %s --check-prefix=CHECK32 diff --git a/lld/test/ELF/loongarch-tls-gd-edge-case.s b/lld/test/ELF/loongarch-tls-gd-edge-case.s index 9f25f10c73b44..dd87d3002b180 100644 --- a/lld/test/ELF/loongarch-tls-gd-edge-case.s +++ b/lld/test/ELF/loongarch-tls-gd-edge-case.s @@ -3,7 +3,7 @@ ## Edge case: when a TLS symbol is being accessed in both GD and IE manners, ## correct reloc behavior should be preserved for both kinds of accesses. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %s -o %t.la32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s %s -o %t.la32.o # RUN: ld.lld %t.la32.o -shared -o %t.la32 # RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t.la64.o # RUN: ld.lld %t.la64.o -shared -o %t.la64 diff --git a/lld/test/ELF/loongarch-tls-gd.s b/lld/test/ELF/loongarch-tls-gd.s index 140aa4cea6bad..9a4ccfa2201a4 100644 --- a/lld/test/ELF/loongarch-tls-gd.s +++ b/lld/test/ELF/loongarch-tls-gd.s @@ -5,11 +5,11 @@ ## (a) code sequence can be converted from `pcalau12i+addi.[wd]` to `pcaddi`. ## (b) dynamic relocations can be omitted for GD->LE relaxation. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/a.s -o %t/a.32.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %t/a.s -o %t/a.32.relax.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/bc.s -o %t/bc.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s %t/a.s -o %t/a.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax %t/a.s -o %t/a.32.relax.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s %t/bc.s -o %t/bc.32.o # RUN: ld.lld -shared -soname=bc.so %t/bc.32.o -o %t/bc.32.so -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/tga.s -o %t/tga.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s %t/tga.s -o %t/tga.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/a.s -o %t/a.64.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/a.s -mattr=+relax -o %t/a.64.relax.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/bc.s -o %t/bc.64.o diff --git a/lld/test/ELF/loongarch-tls-ie.s b/lld/test/ELF/loongarch-tls-ie.s index ddfd9c976cb9b..e7e9617dd3efc 100644 --- a/lld/test/ELF/loongarch-tls-ie.s +++ b/lld/test/ELF/loongarch-tls-ie.s @@ -1,7 +1,7 @@ # REQUIRES: loongarch # RUN: rm -rf %t && split-file %s %t -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/32.s -o %t/32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s %t/32.s -o %t/32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/64.s -o %t/64.o ## LA32 IE diff --git a/lld/test/ELF/loongarch-tls-ld.s b/lld/test/ELF/loongarch-tls-ld.s index 27adb1e17702a..65be2f8fd36e4 100644 --- a/lld/test/ELF/loongarch-tls-ld.s +++ b/lld/test/ELF/loongarch-tls-ld.s @@ -5,9 +5,9 @@ ## (a) code sequence can be converted from `pcalau12i+addi.[wd]` to `pcaddi`. ## (b) dynamic relocations can be omitted for LD->LE relaxation. -# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent %t/a.s -o %t/a.32.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent -mattr=+relax %t/a.s -o %t/a.32.relax.o -# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/tga.s -o %t/tga.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent -mattr=+32s %t/a.s -o %t/a.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent -mattr=+32s,+relax %t/a.s -o %t/a.32.relax.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s %t/tga.s -o %t/tga.32.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 --position-independent %t/a.s -o %t/a.64.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 --position-independent -mattr=+relax %t/a.s -o %t/a.64.relax.o # RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/tga.s -o %t/tga.64.o diff --git a/lld/test/ELF/loongarch-tlsdesc.s b/lld/test/ELF/loongarch-tlsdesc.s index 3dc31210d7ddb..7d07c66606a87 100644 --- a/lld/test/ELF/loongarch-tlsdesc.s +++ b/lld/test/ELF/loongarch-tlsdesc.s @@ -3,8 +3,8 @@ # RUN: llvm-mc -filetype=obj -triple=loongarch64 a.s -o a.64.o # RUN: llvm-mc -filetype=obj -triple=loongarch64 c.s -o c.64.o # RUN: ld.lld -shared -soname=c.64.so c.64.o -o c.64.so -# RUN: llvm-mc -filetype=obj -triple=loongarch32 --defsym ELF32=1 a.s -o a.32.o -# RUN: llvm-mc -filetype=obj -triple=loongarch32 --defsym ELF32=1 c.s -o c.32.o +# RUN: llvm-mc -filetype=obj -triple=loongarch32 --mattr=+32s --defsym ELF32=1 a.s -o a.32.o +# RUN: llvm-mc -filetype=obj -triple=loongarch32 --mattr=+32s --defsym ELF32=1 c.s -o c.32.o # RUN: ld.lld -shared -soname=c.32.so c.32.o -o c.32.so # RUN: ld.lld -shared -z now a.64.o c.64.o -o a.64.so diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def index 4859057abcbb9..96e2c1645b57a 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def @@ -149,3 +149,21 @@ ELF_RELOC(R_LARCH_TLS_LE_LO12_R, 123) ELF_RELOC(R_LARCH_TLS_LD_PCREL20_S2, 124) ELF_RELOC(R_LARCH_TLS_GD_PCREL20_S2, 125) ELF_RELOC(R_LARCH_TLS_DESC_PCREL20_S2, 126) + +// Relocs added in ELF for the LoongArch™ Architecture v20251210, part of the +// v2.50 LoongArch ABI specs. +// +// Spec addition: https://github.com/loongson/la-abi-specs/pull/16 +ELF_RELOC(R_LARCH_CALL30, 127) +ELF_RELOC(R_LARCH_PCADD_HI20, 128) +ELF_RELOC(R_LARCH_PCADD_LO12, 129) +ELF_RELOC(R_LARCH_GOT_PCADD_HI20, 130) +ELF_RELOC(R_LARCH_GOT_PCADD_LO12, 131) +ELF_RELOC(R_LARCH_TLS_IE_PCADD_HI20, 132) +ELF_RELOC(R_LARCH_TLS_IE_PCADD_LO12, 133) +ELF_RELOC(R_LARCH_TLS_LD_PCADD_HI20, 134) +ELF_RELOC(R_LARCH_TLS_LD_PCADD_LO12, 135) +ELF_RELOC(R_LARCH_TLS_GD_PCADD_HI20, 136) +ELF_RELOC(R_LARCH_TLS_GD_PCADD_LO12, 137) +ELF_RELOC(R_LARCH_TLS_DESC_PCADD_HI20, 138) +ELF_RELOC(R_LARCH_TLS_DESC_PCADD_LO12, 139) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h index 04c5a67ac4fe3..1d9038a6fe2d8 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 @@ -330,238 +397,6 @@ inline uint32_t extractBits(uint64_t Val, unsigned Hi, unsigned Lo) { return Hi == 63 ? Val >> Lo : (Val & ((((uint64_t)1 << (Hi + 1)) - 1))) >> Lo; } -/// Apply fixup expression for edge to block content. -inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) { - using namespace support; - - char *BlockWorkingMem = B.getAlreadyMutableContent().data(); - char *FixupPtr = BlockWorkingMem + E.getOffset(); - uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue(); - uint64_t TargetAddress = E.getTarget().getAddress().getValue(); - int64_t Addend = E.getAddend(); - - switch (E.getKind()) { - case Pointer64: - *(ulittle64_t *)FixupPtr = TargetAddress + Addend; - break; - case Pointer32: { - uint64_t Value = TargetAddress + Addend; - if (Value > std::numeric_limits<uint32_t>::max()) - return makeTargetOutOfRangeError(G, B, E); - *(ulittle32_t *)FixupPtr = Value; - break; - } - case Branch16PCRel: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if (!isInt<18>(Value)) - return makeTargetOutOfRangeError(G, B, E); - - if (!isShiftedInt<16, 2>(Value)) - return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); - - uint32_t RawInstr = *(little32_t *)FixupPtr; - uint32_t Imm = static_cast<uint32_t>(Value >> 2); - uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10; - *(little32_t *)FixupPtr = RawInstr | Imm15_0; - break; - } - case Branch21PCRel: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if (!isInt<23>(Value)) - return makeTargetOutOfRangeError(G, B, E); - - if (!isShiftedInt<21, 2>(Value)) - return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); - - uint32_t RawInstr = *(little32_t *)FixupPtr; - uint32_t Imm = static_cast<uint32_t>(Value >> 2); - uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10; - uint32_t Imm20_16 = extractBits(Imm, /*Hi=*/20, /*Lo=*/16); - *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm20_16; - break; - } - case Branch26PCRel: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if (!isInt<28>(Value)) - return makeTargetOutOfRangeError(G, B, E); - - if (!isShiftedInt<26, 2>(Value)) - return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); - - uint32_t RawInstr = *(little32_t *)FixupPtr; - uint32_t Imm = static_cast<uint32_t>(Value >> 2); - uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10; - uint32_t Imm25_16 = extractBits(Imm, /*Hi=*/25, /*Lo=*/16); - *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm25_16; - break; - } - case Delta32: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if (!isInt<32>(Value)) - return makeTargetOutOfRangeError(G, B, E); - *(little32_t *)FixupPtr = Value; - break; - } - case NegDelta32: { - int64_t Value = FixupAddress - TargetAddress + Addend; - if (!isInt<32>(Value)) - return makeTargetOutOfRangeError(G, B, E); - *(little32_t *)FixupPtr = Value; - break; - } - case Delta64: - *(little64_t *)FixupPtr = TargetAddress - FixupAddress + Addend; - break; - case Page20: { - uint64_t Target = TargetAddress + Addend; - uint64_t TargetPage = - (Target + (Target & 0x800)) & ~static_cast<uint64_t>(0xfff); - uint64_t PCPage = FixupAddress & ~static_cast<uint64_t>(0xfff); - - int64_t PageDelta = TargetPage - PCPage; - if (!isInt<32>(PageDelta)) - return makeTargetOutOfRangeError(G, B, E); - - uint32_t RawInstr = *(little32_t *)FixupPtr; - uint32_t Imm31_12 = extractBits(PageDelta, /*Hi=*/31, /*Lo=*/12) << 5; - *(little32_t *)FixupPtr = RawInstr | Imm31_12; - break; - } - case PageOffset12: { - uint64_t TargetOffset = (TargetAddress + Addend) & 0xfff; - - uint32_t RawInstr = *(ulittle32_t *)FixupPtr; - uint32_t Imm11_0 = TargetOffset << 10; - *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0; - break; - } - case Call36PCRel: { - int64_t Value = TargetAddress - FixupAddress + Addend; - - if ((Value + 0x20000) != llvm::SignExtend64(Value + 0x20000, 38)) - return makeTargetOutOfRangeError(G, B, E); - - if (!isShiftedInt<36, 2>(Value)) - return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E); - - uint32_t Pcaddu18i = *(little32_t *)FixupPtr; - uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/37, /*Lo=*/18) << 5; - *(little32_t *)FixupPtr = Pcaddu18i | Hi20; - uint32_t Jirl = *(little32_t *)(FixupPtr + 4); - uint32_t Lo16 = extractBits(Value, /*Hi=*/17, /*Lo=*/2) << 10; - *(little32_t *)(FixupPtr + 4) = Jirl | Lo16; - break; - } - case Add6: { - int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr)); - Value += ((TargetAddress + Addend) & 0x3f); - *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<int8_t>(Value) & 0x3f); - break; - } - case Add8: { - int64_t Value = - TargetAddress + *(reinterpret_cast<const int8_t *>(FixupPtr)) + Addend; - *FixupPtr = static_cast<int8_t>(Value); - break; - } - case Add16: { - int64_t Value = - TargetAddress + support::endian::read16le(FixupPtr) + Addend; - *(little16_t *)FixupPtr = static_cast<int16_t>(Value); - break; - } - case Add32: { - int64_t Value = - TargetAddress + support::endian::read32le(FixupPtr) + Addend; - *(little32_t *)FixupPtr = static_cast<int32_t>(Value); - break; - } - case Add64: { - int64_t Value = - TargetAddress + support::endian::read64le(FixupPtr) + Addend; - *(little64_t *)FixupPtr = static_cast<int64_t>(Value); - break; - } - case AddUleb128: { - const uint32_t Maxcount = 1 + 64 / 7; - uint32_t Count; - const char *Error = nullptr; - uint64_t Orig = decodeULEB128((reinterpret_cast<const uint8_t *>(FixupPtr)), - &Count, nullptr, &Error); - - if (Count > Maxcount || (Count == Maxcount && Error)) - return make_error<JITLinkError>( - "0x" + llvm::utohexstr(orc::ExecutorAddr(FixupAddress).getValue()) + - ": extra space for uleb128"); - - uint64_t Mask = Count < Maxcount ? (1ULL << 7 * Count) - 1 : -1ULL; - encodeULEB128((Orig + TargetAddress + Addend) & Mask, - (reinterpret_cast<uint8_t *>(FixupPtr)), Count); - break; - } - case Sub6: { - int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr)); - Value -= ((TargetAddress + Addend) & 0x3f); - *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<int8_t>(Value) & 0x3f); - break; - } - case Sub8: { - int64_t Value = - *(reinterpret_cast<const int8_... [truncated] |
This patch introduces the relocation types added in la-abi-sepcs v2.50, enabling support for LoongArch32 Reduced and Standard variants.
Link: loongson/la-abi-specs#16
Link: https://sourceware.org/pipermail/binutils/2025-December/146091.html
Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-December/703312.html