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 @@ -57,6 +57,13 @@ /// Fixup <- (Target + Addend + 0x800) >> 12 R_RISCV_HI20, + /// Low 12 bits of 32-bit pointer value relocation, used by S type instruction + /// format + /// + /// Fixup expression + /// Fixup <- (Target + Addend) & 0xFFF + R_RISCV_LO12_S, + /// Low 12 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 @@ -247,6 +247,17 @@ (RawInstr & 0xFFFFF) | (static_cast(Lo & 0xFFF) << 20); break; } + case R_RISCV_LO12_S: { + // FIXME: We assume that R_RISCV_HI20 is present in object code and pairs + // with current relocation R_RISCV_LO12_S. So here may need a check. + int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue(); + int64_t Lo = Value & 0xFFF; + uint32_t Imm31_25 = extractBits(Lo, 5, 7) << 25; + uint32_t Imm11_7 = extractBits(Lo, 0, 5) << 7; + uint32_t RawInstr = *(little32_t *)FixupPtr; + *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7; + break; + } case R_RISCV_CALL: { int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; int64_t Hi = Value + 0x800; @@ -429,6 +440,8 @@ return EdgeKind_riscv::R_RISCV_HI20; case ELF::R_RISCV_LO12_I: return EdgeKind_riscv::R_RISCV_LO12_I; + case ELF::R_RISCV_LO12_S: + return EdgeKind_riscv::R_RISCV_LO12_S; case ELF::R_RISCV_CALL: return EdgeKind_riscv::R_RISCV_CALL; case ELF::R_RISCV_PCREL_HI20: 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 @@ -32,6 +32,8 @@ return "R_RISCV_HI20"; case R_RISCV_LO12_I: return "R_RISCV_LO12_I"; + case R_RISCV_LO12_S: + return "R_RISCV_LO12_S"; case R_RISCV_PCREL_HI20: return "R_RISCV_PCREL_HI20"; case R_RISCV_PCREL_LO12_I: diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_abs_reloc.s b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_abs_reloc.s --- a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_abs_reloc.s +++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_abs_reloc.s @@ -5,11 +5,11 @@ # RUN: -o %t/elf_riscv32_non_pc_indirect_reloc.o %s # RUN: llvm-jitlink -noexec \ # RUN: -slab-allocate 100Kb -slab-address 0x1ff00000 -slab-page-size 4096 \ -# RUN: -abs external_data=0x1ff10000 \ +# RUN: -abs external_data=0x1ff11115 \ # RUN: -check %s %t/elf_riscv64_non_pc_indirect_reloc.o # RUN: llvm-jitlink -noexec \ # RUN: -slab-allocate 100Kb -slab-address 0x1ff00000 -slab-page-size 4096 \ -# RUN: -abs external_data=0x1ff10000 \ +# RUN: -abs external_data=0x1ff11115 \ # RUN: -check %s %t/elf_riscv32_non_pc_indirect_reloc.o # @@ -29,11 +29,13 @@ # jitlink-check: decode_operand(test_abs_rel, 1) = (external_data + 0x800)[31:12] # jitlink-check: decode_operand(test_abs_rel+4, 2)[11:0] = (external_data)[11:0] +# jitlink-check: decode_operand(test_abs_rel+8, 2)[11:0] = (external_data)[11:0] .globl test_abs_rel .p2align 1 .type test_abs_rel,@function test_abs_rel: - lui a0, %hi(external_data) - lw a0, %lo(external_data)(a0) + lui a1, %hi(external_data) + lw a0, %lo(external_data)(a1) + sw a0, %lo(external_data)(a1) .size test_abs_rel, .-test_abs_rel