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 @@ -44,6 +44,13 @@ /// R_RISCV_BRANCH, + /// High 20 bits of PC-relative jump pointer value relocation + /// + /// Fixup expression: + /// Fixup <- Target - Fixup + Addend + /// + R_RISCV_JAL, + /// High 20 bits of 32-bit pointer value relocation /// /// Fixup expression 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 @@ -220,6 +220,20 @@ *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7; break; } + case R_RISCV_JAL: { + int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; + Error AlignmentIssue = checkAlignment(FixupAddress, Value, 2, E); + if (AlignmentIssue) { + return AlignmentIssue; + } + uint32_t Imm20 = extractBits(Value, 20, 1) << 31; + uint32_t Imm10_1 = extractBits(Value, 1, 10) << 21; + uint32_t Imm11 = extractBits(Value, 11, 1) << 20; + uint32_t Imm19_12 = extractBits(Value, 12, 8) << 12; + uint32_t RawInstr = *(little32_t *)FixupPtr; + *(little32_t *)FixupPtr = RawInstr | Imm20 | Imm10_1 | Imm11 | Imm19_12; + break; + } case R_RISCV_HI20: { int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue(); int64_t Hi = Value + 0x800; @@ -409,6 +423,8 @@ return EdgeKind_riscv::R_RISCV_64; case ELF::R_RISCV_BRANCH: return EdgeKind_riscv::R_RISCV_BRANCH; + case ELF::R_RISCV_JAL: + return EdgeKind_riscv::R_RISCV_JAL; case ELF::R_RISCV_HI20: return EdgeKind_riscv::R_RISCV_HI20; case ELF::R_RISCV_LO12_I: 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 @@ -26,6 +26,8 @@ return "R_RISCV_64"; case R_RISCV_BRANCH: return "R_RISCV_BRANCH"; + case R_RISCV_JAL: + return "R_RISCV_JAL"; case R_RISCV_HI20: return "R_RISCV_HI20"; case R_RISCV_LO12_I: diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_jal.s b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_jal.s new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_jal.s @@ -0,0 +1,37 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=riscv64 -filetype=obj \ +# RUN: -o %t/elf_riscv64_jal.o %s +# RUN: llvm-mc -triple=riscv32 -filetype=obj \ +# RUN: -o %t/elf_riscv32_jal.o %s +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0x1ff00000 -slab-page-size 4096 \ +# RUN: -abs external_func=0x1fe000fe \ +# RUN: -check %s %t/elf_riscv64_jal.o +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0x1ff00000 -slab-page-size 4096 \ +# RUN: -abs external_func=0x1fe000fe \ +# RUN: -check %s %t/elf_riscv32_jal.o +# + + .text + .file "testcase.c" + +# Empty main entry point. + .globl main + .p2align 1 + .type main,@function +main: + ret + + .size main, .-main + +# Test R_RISCV_JAL + +# jitlink-check: decode_operand(test_jal, 1)[31:12] = (external_func - test_jal)[31:12] + .globl test_jal + .p2align 1 + .type test_jal,@function +test_jal: + jal x0, external_func + + .size test_jal, .-test_jal