Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 <- (*{1}Fixup + Target + Addend) : int8
///
Add8,

/// 16 bits label addition
///
/// Fixup expression:
/// Fixup <- (*{2}Fixup + Target + Addend) : int16
///
Add16,

/// 32 bits label addition
///
/// Fixup expression:
/// Fixup <- (*{4}Fixup + Target + Addend) : int32
///
Add32,

/// 64 bits label addition
///
/// Fixup expression:
/// Fixup <- (*{8}Fixup + Target + Addend) : int64
///
Add64,

/// ULEB128 bits label addition
///
/// Fixup expression:
/// Fixup <- (Fixup + Target + 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 <- (Fixup - Target - Addend) : uleb128
///
SubUleb128,

/// Alignment requirement used by linker relaxation.
///
/// Linker relaxation will use this to ensure all code sequences are properly
Expand Down Expand Up @@ -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;
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
53 changes: 53 additions & 0 deletions llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s
Original file line number Diff line number Diff line change
@@ -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
Loading