Skip to content

Commit

Permalink
[JITLink] Fix the incorrect relocation behavior for R_RISCV_BRANCH
Browse files Browse the repository at this point in the history
In D116573, the relocation behavior of R_RISCV_BRANCH didn't consider that branch instruction like 'bge' has a branch target address which is given as a PC-relative offset, sign-extend and multiplied by 2.
Although the target address is a 12-bits number, acctually its range is [-4096, 4094].

This patch fix it.

Differential Revision: https://reviews.llvm.org/D118151
  • Loading branch information
luxufan authored and luxufan committed Feb 7, 2022
1 parent 3a3cb92 commit 9920943
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 16 deletions.
4 changes: 2 additions & 2 deletions llvm/include/llvm/ExecutionEngine/JITLink/riscv.h
Expand Up @@ -37,10 +37,10 @@ enum EdgeKind_riscv : Edge::Kind {
///
R_RISCV_64,

/// Low 12 bits of PC-relative branch pointer value relocation
/// PC-relative branch pointer value relocation
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) & 0xFFF
/// Fixup <- (Target - Fixup + Addend)
///
R_RISCV_BRANCH,

Expand Down
11 changes: 5 additions & 6 deletions llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
Expand Up @@ -160,7 +160,7 @@ static Expected<const Edge &> getRISCVPCRelHi20(const Edge &E) {
}

static uint32_t extractBits(uint32_t Num, unsigned Low, unsigned Size) {
return (Num & (((1ULL << (Size + 1)) - 1) << Low)) >> Low;
return (Num & (((1ULL << Size) - 1) << Low)) >> Low;
}

inline Error checkAlignment(llvm::orc::ExecutorAddr loc, uint64_t v, int n,
Expand Down Expand Up @@ -212,11 +212,10 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
if (AlignmentIssue) {
return AlignmentIssue;
}
int64_t Lo = Value & 0xFFF;
uint32_t Imm31_25 = extractBits(Lo, 5, 6) << 25 | extractBits(Lo, 12, 1)
<< 31;
uint32_t Imm11_7 = extractBits(Lo, 1, 4) << 8 | extractBits(Lo, 11, 1)
<< 7;
uint32_t Imm31_25 =
extractBits(Value, 5, 6) << 25 | extractBits(Value, 12, 1) << 31;
uint32_t Imm11_7 =
extractBits(Value, 1, 4) << 8 | extractBits(Value, 11, 1) << 7;
uint32_t RawInstr = *(little32_t *)FixupPtr;
*(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7;
break;
Expand Down
16 changes: 8 additions & 8 deletions llvm/test/ExecutionEngine/JITLink/RISCV/ELF_branch.s
Expand Up @@ -4,18 +4,16 @@
# 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: -abs external_func=0xfe \
# RUN: -slab-allocate 100Kb -slab-address 0xfff00ff4 -slab-page-size 4096 \
# RUN: -abs external_func_positive_offset=0xfff00ffc -abs external_func_negative_offset=0xfff00000\
# RUN: -check %s %t/elf_riscv64_branch.o
# RUN: llvm-jitlink -noexec \
# RUN: -slab-allocate 100Kb -slab-address 0xfff00000 -slab-page-size 4096 \
# RUN: -abs external_func=0xfe \
# RUN: -slab-allocate 100Kb -slab-address 0xfff00ff4 -slab-page-size 4096 \
# RUN: -abs external_func_positive_offset=0xfff00ffc -abs external_func_negative_offset=0xfff00000 \
# RUN: -check %s %t/elf_riscv32_branch.o
#

.text
.file "testcase.c"

# Empty main entry point.
.globl main
.p2align 1
Expand All @@ -27,11 +25,13 @@ main:

# Test R_RISCV_BRANCH

# jitlink-check: decode_operand(test_branch, 2)[11:0] = (external_func - test_branch)[11:0]
# jitlink-check: decode_operand(test_branch, 2)[12:0] = (external_func_positive_offset - test_branch)[12:0]
# jitlink-check: decode_operand(test_branch+4, 2)[12:0] = (external_func_negative_offset - test_branch - 4)[12:0]
.globl test_branch
.p2align 1
.type test_branch,@function
test_branch:
bge a0, a1, external_func
bge a0, a1, external_func_positive_offset
bge a0, a1, external_func_negative_offset

.size test_branch, .-test_branch

0 comments on commit 9920943

Please sign in to comment.