diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h @@ -82,8 +82,55 @@ /// /// Fixup expression: /// Fixup <- (Target - Fixup + Addend) - R_RISCV_CALL_PLT + R_RISCV_CALL_PLT, + /// 64 bits label addition + /// + /// Fixup expression: + /// Fixup <- (Targat - *{8}Fixup + Addend) + R_RISCV_ADD64, + + /// 32 bits label addition + /// + /// Fixup expression: + /// Fixup <- (Target - *{4}Fixup + Addend) + R_RISCV_ADD32, + + /// 16 bits label addition + /// + /// Fixup expression + /// Fixup <- (Target - *{2}Fixup + Addend) + R_RISCV_ADD16, + + /// 8 bits label addition + /// + /// Fixup expression + /// Fixup <- (Target - *{1}Fixup + Addend) + R_RISCV_ADD8, + + /// 64 bits label addition + /// + /// Fixup expression + /// Fixup <- (Target - *{8}Fixup - Addend) + R_RISCV_SUB64, + + /// 32 bits label addition + /// + /// Fixup expression + /// Fixup <- (Target - *{4}Fixup - Addend) + R_RISCV_SUB32, + + /// 16 bits label addition + /// + /// Fixup expression + /// Fixup <- (Target - *{2}Fixup - Addend) + R_RISCV_SUB16, + + /// 8 bits label addition + /// + /// Fixup expression + /// Fixup <- (Target - *{1}Fixup - Addend) + R_RISCV_SUB8 }; /// Returns a string name for the given riscv edge. For debugging purposes diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -19,6 +19,7 @@ #include "llvm/ExecutionEngine/JITLink/riscv.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Support/Endian.h" #define DEBUG_TYPE "jitlink" using namespace llvm; @@ -245,6 +246,46 @@ *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7; break; } + case R_RISCV_ADD64: { + int64_t Value = E.getTarget().getAddress() + support::endian::read64le(reinterpret_cast(FixupAddress)) + E.getAddend(); + *(little64_t *)FixupPtr = static_cast(Value); + break; + } + case R_RISCV_ADD32: { + int64_t Value = E.getTarget().getAddress() + support::endian::read32le(reinterpret_cast(FixupAddress)) + E.getAddend(); + *(little32_t *)FixupPtr = static_cast(Value); + break; + } + case R_RISCV_ADD16: { + int64_t Value = E.getTarget().getAddress() + support::endian::read16le(reinterpret_cast(FixupAddress)) + E.getAddend(); + *(little16_t *)FixupPtr = static_cast(Value); + break; + } + case R_RISCV_ADD8: { + int64_t Value = E.getTarget().getAddress() + *(reinterpret_cast(FixupAddress)) + E.getAddend(); + *FixupPtr = static_cast(Value); + break; + } + case R_RISCV_SUB64: { + int64_t Value = support::endian::read64le(reinterpret_cast(FixupAddress)) - E.getTarget().getAddress()- E.getAddend(); + *(little64_t *)FixupPtr = static_cast(Value); + break; + } + case R_RISCV_SUB32: { + int64_t Value = support::endian::read32le(reinterpret_cast(FixupAddress)) - E.getTarget().getAddress()- E.getAddend(); + *(little32_t *)FixupPtr = static_cast(Value); + break; + } + case R_RISCV_SUB16: { + int64_t Value = support::endian::read16le(reinterpret_cast(FixupAddress)) - E.getTarget().getAddress() - E.getAddend(); + *(little16_t *)FixupPtr = static_cast(Value); + break; + } + case R_RISCV_SUB8: { + int64_t Value = *(reinterpret_cast(FixupAddress)) - E.getTarget().getAddress() - E.getAddend(); + *FixupPtr = static_cast(Value); + break; + } } return Error::success(); } @@ -277,6 +318,22 @@ return EdgeKind_riscv::R_RISCV_GOT_HI20; case ELF::R_RISCV_CALL_PLT: return EdgeKind_riscv::R_RISCV_CALL_PLT; + case ELF::R_RISCV_ADD64: + return EdgeKind_riscv::R_RISCV_ADD64; + case ELF::R_RISCV_ADD32: + return EdgeKind_riscv::R_RISCV_ADD32; + case ELF::R_RISCV_ADD16: + return EdgeKind_riscv::R_RISCV_ADD16; + case ELF::R_RISCV_ADD8: + return EdgeKind_riscv::R_RISCV_ADD8; + case ELF::R_RISCV_SUB64: + return EdgeKind_riscv::R_RISCV_SUB64; + case ELF::R_RISCV_SUB32: + return EdgeKind_riscv::R_RISCV_SUB32; + case ELF::R_RISCV_SUB16: + return EdgeKind_riscv::R_RISCV_SUB16; + case ELF::R_RISCV_SUB8: + return EdgeKind_riscv::R_RISCV_SUB8; } return make_error("Unsupported riscv relocation:" + diff --git a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp --- a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp @@ -36,6 +36,22 @@ return "R_RISCV_PCREL_LO12_S"; case R_RISCV_CALL: return "R_RISCV_CALL"; + case R_RISCV_ADD64: + return "R_RISCV_ADD64"; + case R_RISCV_ADD32: + return "R_RISCV_ADD32"; + case R_RISCV_ADD16: + return "R_RISCV_ADD16"; + case R_RISCV_ADD8: + return "R_RISCV_ADD8"; + case R_RISCV_SUB64: + return "R_RISCV_SUB64"; + case R_RISCV_SUB32: + return "R_RISCV_SUB32"; + case R_RISCV_SUB16: + return "R_RISCV_SUB16"; + case R_RISCV_SUB8: + return "R_RISCV_SUB8"; } return getGenericEdgeKindName(K); } diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/riscv_reloc_add.s b/llvm/test/ExecutionEngine/JITLink/RISCV/riscv_reloc_add.s new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/RISCV/riscv_reloc_add.s @@ -0,0 +1,27 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t/riscv64_reloc_add.o %s +# RUN: llvm-mc -triple=riscv32 -filetype=obj -o %t/riscv32_reloc_add.o %s +# RUN: llvm-jitlink -noexec -check %s %t/riscv64_reloc_add.o +# RUN: llvm-jitlink -noexec -check %s %t/riscv32_reloc_add.o + +# 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 + +.global main +main: +.L0: +# Referencing named_data symbol to avoid the following .rodata section be skipped +# This instruction will be expand to two instructions (auipc + ld) + lw a0, named_data +.L1: + +.section ".rodata","",@progbits +.type named_data,@object +named_data: +.dword .L1 - .L0 +.word .L1 - .L0 +.half .L1 - .L0 +.byte .L1 - .L0 +.size named_data, 15