Skip to content

Conversation

@zhaoqi5
Copy link
Contributor

@zhaoqi5 zhaoqi5 commented Jan 9, 2025

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Jan 9, 2025

@llvm/pr-subscribers-backend-loongarch

Author: ZhaoQi (zhaoqi5)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/122262.diff

4 Files Affected:

  • (modified) llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h (+180)
  • (modified) llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp (+24)
  • (modified) llvm/lib/ExecutionEngine/JITLink/loongarch.cpp (+12)
  • (added) llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s (+53)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
index d6025edf7d110d..1d763e1255fc21 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
@@ -14,8 +14,10 @@
 #define LLVM_EXECUTIONENGINE_JITLINK_LOONGARCH_H
 
 #include "TableManager.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
 #include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h"
+#include "llvm/Support/LEB128.h"
 
 namespace llvm {
 namespace jitlink {
@@ -226,6 +228,90 @@ enum EdgeKind_loongarch : Edge::Kind {
   ///
   Call36PCRel,
 
+  /// low 6 bits label addition
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (*{1}Fixup + (Target + Addend) & 0x3f) : int8
+  ///
+  Add6,
+
+  /// 8 bits label addition
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target + *{1}Fixup + Addend) : int8
+  ///
+  Add8,
+
+  /// 16 bits label addition
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target + *{2}Fixup + Addend) : int16
+  ///
+  Add16,
+
+  /// 32 bits label addition
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target + *{4}Fixup + Addend) : int32
+  ///
+  Add32,
+
+  /// 64 bits label addition
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target + *{8}Fixup + Addend) : int64
+  ///
+  Add64,
+
+  /// ULEB128 bits label addition
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target + *{16}Fixup + Addend) : uleb128
+  ///
+  AddUleb128,
+
+  /// low 6 bits label subtraction
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (*{1}Fixup - (Target + Addend) & 0x3f) : int8
+  ///
+  Sub6,
+
+  /// 8 bits label subtraction
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (*{1}Fixup - Target - Addend) : int8
+  ///
+  Sub8,
+
+  /// 16 bits label subtraction
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (*{2}Fixup - Target - Addend) : int16
+  ///
+  Sub16,
+
+  /// 32 bits label subtraction
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (*{4}Fixup - Target - Addend) : int32
+  ///
+  Sub32,
+
+  /// 64 bits label subtraction
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (*{8}Fixup - Target - Addend) : int64
+  ///
+  Sub64,
+
+  /// ULEB128 bits label subtraction
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (*{16}Fixup - Target - Addend) : uleb128
+  ///
+  SubUleb128,
+
   /// Alignment requirement used by linker relaxation.
   ///
   /// Linker relaxation will use this to ensure all code sequences are properly
@@ -369,6 +455,100 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
     *(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_t *>(FixupPtr)) - TargetAddress - Addend;
+    *FixupPtr = static_cast<int8_t>(Value);
+    break;
+  }
+  case Sub16: {
+    int64_t Value =
+        support::endian::read16le(FixupPtr) - TargetAddress - Addend;
+    *(little16_t *)FixupPtr = static_cast<int16_t>(Value);
+    break;
+  }
+  case Sub32: {
+    int64_t Value =
+        support::endian::read32le(FixupPtr) - TargetAddress - Addend;
+    *(little32_t *)FixupPtr = static_cast<int32_t>(Value);
+    break;
+  }
+  case Sub64: {
+    int64_t Value =
+        support::endian::read64le(FixupPtr) - TargetAddress - Addend;
+    *(little64_t *)FixupPtr = static_cast<int64_t>(Value);
+    break;
+  }
+  case SubUleb128: {
+    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 AlignRelaxable:
     // Ignore when the relaxation pass did not run
     break;
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
index 3f0a7b645e83fc..f23fb346c55f90 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
@@ -306,6 +306,30 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
       return RequestGOTAndTransformToPageOffset12;
     case ELF::R_LARCH_CALL36:
       return Call36PCRel;
+    case ELF::R_LARCH_ADD6:
+      return Add6;
+    case ELF::R_LARCH_ADD8:
+      return Add8;
+    case ELF::R_LARCH_ADD16:
+      return Add16;
+    case ELF::R_LARCH_ADD32:
+      return Add32;
+    case ELF::R_LARCH_ADD64:
+      return Add64;
+    case ELF::R_LARCH_ADD_ULEB128:
+      return AddUleb128;
+    case ELF::R_LARCH_SUB6:
+      return Sub6;
+    case ELF::R_LARCH_SUB8:
+      return Sub8;
+    case ELF::R_LARCH_SUB16:
+      return Sub16;
+    case ELF::R_LARCH_SUB32:
+      return Sub32;
+    case ELF::R_LARCH_SUB64:
+      return Sub64;
+    case ELF::R_LARCH_SUB_ULEB128:
+      return SubUleb128;
     case ELF::R_LARCH_ALIGN:
       return AlignRelaxable;
     }
diff --git a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
index a5579b074de7cf..55389adb31b60e 100644
--- a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
@@ -52,6 +52,18 @@ const char *getEdgeKindName(Edge::Kind K) {
     KIND_NAME_CASE(RequestGOTAndTransformToPage20)
     KIND_NAME_CASE(RequestGOTAndTransformToPageOffset12)
     KIND_NAME_CASE(Call36PCRel)
+    KIND_NAME_CASE(Add6)
+    KIND_NAME_CASE(Add8)
+    KIND_NAME_CASE(Add16)
+    KIND_NAME_CASE(Add32)
+    KIND_NAME_CASE(Add64)
+    KIND_NAME_CASE(AddUleb128)
+    KIND_NAME_CASE(Sub6)
+    KIND_NAME_CASE(Sub8)
+    KIND_NAME_CASE(Sub16)
+    KIND_NAME_CASE(Sub32)
+    KIND_NAME_CASE(Sub64)
+    KIND_NAME_CASE(SubUleb128)
     KIND_NAME_CASE(AlignRelaxable)
   default:
     return getGenericEdgeKindName(K);
diff --git a/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s b/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s
new file mode 100644
index 00000000000000..86e3008ef40943
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s
@@ -0,0 +1,53 @@
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc --triple=loongarch32 -mattr=+relax --filetype=obj \
+# RUN:     -o %t/la32_reloc_addsub.o %s
+# RUN: llvm-jitlink --noexec --check %s %t/la32_reloc_addsub.o \
+# RUN:     --slab-allocate=1Mb --slab-address=0x1000 --slab-page-size=0x4000
+# RUN: llvm-mc --triple=loongarch64 -mattr=+relax --filetype=obj \
+# RUN:     -o %t/la64_reloc_addsub.o %s
+# RUN: llvm-jitlink --noexec --check %s %t/la64_reloc_addsub.o \
+# RUN:     --slab-allocate=1Mb --slab-address=0x1000 --slab-page-size=0x4000
+
+# jitlink-check: *{8}(named_data) = 0x8
+# jitlink-check: *{4}(named_data+8) = 0x8
+# jitlink-check: *{2}(named_data+12) = 0x8
+# jitlink-check: *{1}(named_data+14) = 0x8
+# jitlink-check: *{1}(named_data+15) = 0x10
+
+# jitlink-check: *{1}(leb_data) = 0x8
+# jitlink-check: *{2}(leb_data+1) = 0x180
+# jitlink-check: *{8}(leb_data+3) = 0xfffffffffffffff8
+# jitlink-check: *{2}(leb_data+11) = 0x1ff
+# jitlink-check: *{1}(leb_data+13) = 0x7f
+# jitlink-check: *{2}(leb_data+14) = 0x181
+
+.section .alloc_data,"ax",@progbits
+.global main
+main:
+.L0:
+# Referencing named_data symbol to avoid the following relocations be
+# skipped. This macro instruction will be expand to two instructions
+# (pcalau12i + ld.w/d).
+  la.global $t0, named_data
+.L1:
+
+named_data:
+.reloc named_data+15, R_LARCH_ADD6, .L1
+.reloc named_data+15, R_LARCH_SUB6, .L0
+.dword .L1 - .L0
+.word .L1 - .L0
+.half .L1 - .L0
+.byte .L1 - .L0
+.byte 0x8
+
+.size named_data, 16
+
+leb_data:
+.uleb128 .L1 - .L0
+.uleb128 .L1 - .L0 + 120
+.uleb128 -(.L1 - .L0)
+.uleb128 leb_end - leb_data + 111
+.uleb128 leb_end - leb_data + 113
+leb_end:
+
+.size leb_data, 16

Linker relaxation is not implemented for jitlink now (maybe
implement in the future). But if relaxation is enabled by clang,
R_LARCH_RELAX and R_LARCH_ALIGN relocations will be emitted.
So we just ignore linker relaxation and check the alignment now.

If not, interpreting C++ code using clang-repl when relaxation
is enabled will occur error: `JIT session error: Unsupported
loongarch relocation:102: R_LARCH_ALIGN`.

Similar to: f5b5398.
Linker relaxation is not implemented for jitlink now. But if
relaxation is enabled by clang, R_LARCH_RELAX and R_LARCH_ALIGN
relocations will be emitted.

This commit adapts lld's algorithm to jitlink. Currently, only
relaxing R_LARCH_ALIGN is implemented. Other relaxable relocs
can be implemented in the future.

Without this, interpreting C++ code using clang-repl or running
ir using lli when relaxation is enabled will occur error: `JIT
session error: Unsupported loongarch relocation:102: R_LARCH_ALIGN`.

Similar to 310473c but only implement align.
@zhaoqi5 zhaoqi5 force-pushed the users/zhaoqi5/jitlink-relax-align branch from 41de630 to 91aea9b Compare January 10, 2025 01:58
@zhaoqi5 zhaoqi5 force-pushed the users/zhaoqi5/jitlink-support-add-sub branch from 92a79be to 4398bd9 Compare January 10, 2025 01:59
@SixWeining SixWeining requested a review from wangleiat January 22, 2025 09:41
Copy link
Contributor

@wangleiat wangleiat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks.

Base automatically changed from users/zhaoqi5/jitlink-relax-align to main January 24, 2025 06:24
@zhaoqi5 zhaoqi5 merged commit f6253f8 into main Jan 24, 2025
8 checks passed
@zhaoqi5 zhaoqi5 deleted the users/zhaoqi5/jitlink-support-add-sub branch January 24, 2025 07:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants