Index: llvm/include/llvm/ExecutionEngine/JITLink/riscv.h =================================================================== --- llvm/include/llvm/ExecutionEngine/JITLink/riscv.h +++ llvm/include/llvm/ExecutionEngine/JITLink/riscv.h @@ -37,6 +37,13 @@ /// R_RISCV_64, + /// Low 12 bits of PC-relative branch pointer value relocation + /// + /// Fixup expression: + /// Fixup <- (Target - Fixup + Addend) & 0xFFF + /// + R_RISCV_BRANCH, + /// High 20 bits of 32-bit pointer value relocation /// /// Fixup expression Index: llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp =================================================================== --- llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -161,6 +161,20 @@ return (Num & ((1ULL << (High + 1)) - 1)) >> Low; } +static uint32_t extractBit(uint64_t Num, unsigned Specific) { + return extractBits(Num, Specific, Specific); +} + +inline Error checkAlignment(llvm::JITTargetAddress loc, uint64_t v, int n, + const Edge &E) { + if ((v & (n - 1)) != 0) + return make_error( + llvm::utohexstr(loc) + " improper alignment for relocation " + + formatv("{0:d}", E.getKind()) + ": 0x" + llvm::utohexstr(v) + + " is not aligned to " + Twine(n) + " bytes"); + return Error::success(); +} + class ELFJITLinker_riscv : public JITLinker { friend class JITLinker; @@ -188,6 +202,20 @@ *(little64_t *)FixupPtr = static_cast(Value); break; } + case R_RISCV_BRANCH: { + int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; + Error AlignmentIssue = checkAlignment(FixupAddress, Value, 2, E); + if (AlignmentIssue) { + return AlignmentIssue; + } + int64_t Lo = Value & 0xFFF; + uint32_t Imm31_25 = extractBits(Lo, 10, 5) << 25 | extractBit(Lo, 12) + << 31; + uint32_t Imm11_7 = extractBits(Lo, 4, 1) << 8 | extractBit(Lo, 11) << 7; + uint32_t RawInstr = *(little32_t *)FixupPtr; + *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7; + break; + } case R_RISCV_HI20: { int64_t Value = E.getTarget().getAddress() + E.getAddend(); int32_t Hi = (Value + 0x800) & 0xFFFFF000; @@ -261,6 +289,8 @@ return EdgeKind_riscv::R_RISCV_32; case ELF::R_RISCV_64: return EdgeKind_riscv::R_RISCV_64; + case ELF::R_RISCV_BRANCH: + return EdgeKind_riscv::R_RISCV_BRANCH; case ELF::R_RISCV_HI20: return EdgeKind_riscv::R_RISCV_HI20; case ELF::R_RISCV_LO12_I: Index: llvm/lib/ExecutionEngine/JITLink/riscv.cpp =================================================================== --- llvm/lib/ExecutionEngine/JITLink/riscv.cpp +++ llvm/lib/ExecutionEngine/JITLink/riscv.cpp @@ -24,6 +24,8 @@ return "R_RISCV_32"; case R_RISCV_64: return "R_RISCV_64"; + case R_RISCV_BRANCH: + return "R_RISCV_BRANCH"; case R_RISCV_HI20: return "R_RISCV_HI20"; case R_RISCV_LO12_I: Index: llvm/test/ExecutionEngine/JITLink/RISCV/ELF_branch.s =================================================================== --- /dev/null +++ llvm/test/ExecutionEngine/JITLink/RISCV/ELF_branch.s @@ -0,0 +1,37 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=riscv64 -filetype=obj \ +# RUN: -o %t/elf_riscv64_branch.o %s +# RUN: llvm-mc -triple=riscv32 -filetype=obj \ +# RUN: -o %t/elf_riscv32_branch.o %s +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0xfff00000 -slab-page-size 4096 \ +# RUN: -define-abs external_func=0xfe \ +# RUN: -check %s %t/elf_riscv64_branch.o +# RUN: llvm-jitlink -noexec \ +# RUN: -slab-allocate 100Kb -slab-address 0xfff00000 -slab-page-size 4096 \ +# RUN: -define-abs external_func=0xfe \ +# RUN: -check %s %t/elf_riscv32_branch.o +# + + .text + .file "testcase.c" + +# Empty main entry point. + .globl main + .p2align 1 + .type main,@function +main: + ret + + .size main, .-main + +# Test R_RISCV_BRANCH + +# jitlink-check: decode_operand(test_branch, 2)[11:0] = (external_func - test_branch)[11:0] + .globl test_branch + .p2align 1 + .type test_branch,@function +test_branch: + bge a0, a1, external_func + + .size test_branch, .-test_branch