cranelift-jit: Implement RISC-V Call relocation (#5835)
This commit is contained in:
@@ -810,3 +810,52 @@ block0:
|
|||||||
; addi a1, zero, 1
|
; addi a1, zero, 1
|
||||||
; ret
|
; ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function %call_colocated(i16) -> i16 {
|
||||||
|
sig0 = () system_v
|
||||||
|
fn0 = colocated u0:0 sig0
|
||||||
|
|
||||||
|
block0(v0: i16):
|
||||||
|
call fn0()
|
||||||
|
return v0
|
||||||
|
}
|
||||||
|
|
||||||
|
; VCode:
|
||||||
|
; add sp,-16
|
||||||
|
; sd ra,8(sp)
|
||||||
|
; sd fp,0(sp)
|
||||||
|
; mv fp,sp
|
||||||
|
; sd s3,-8(sp)
|
||||||
|
; add sp,-16
|
||||||
|
; block0:
|
||||||
|
; mv s3,a0
|
||||||
|
; call userextname0
|
||||||
|
; mv a0,s3
|
||||||
|
; add sp,+16
|
||||||
|
; ld s3,-8(sp)
|
||||||
|
; ld ra,8(sp)
|
||||||
|
; ld fp,0(sp)
|
||||||
|
; add sp,+16
|
||||||
|
; ret
|
||||||
|
;
|
||||||
|
; Disassembled:
|
||||||
|
; block0: ; offset 0x0
|
||||||
|
; addi sp, sp, -0x10
|
||||||
|
; sd ra, 8(sp)
|
||||||
|
; sd s0, 0(sp)
|
||||||
|
; ori s0, sp, 0
|
||||||
|
; sd s3, -8(sp)
|
||||||
|
; addi sp, sp, -0x10
|
||||||
|
; block1: ; offset 0x18
|
||||||
|
; ori s3, a0, 0
|
||||||
|
; auipc ra, 0 ; reloc_external RiscvCall u0:0 0
|
||||||
|
; jalr ra
|
||||||
|
; ori a0, s3, 0
|
||||||
|
; addi sp, sp, 0x10
|
||||||
|
; ld s3, -8(sp)
|
||||||
|
; ld ra, 8(sp)
|
||||||
|
; ld s0, 0(sp)
|
||||||
|
; addi sp, sp, 0x10
|
||||||
|
; ret
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ target aarch64
|
|||||||
target aarch64 sign_return_address
|
target aarch64 sign_return_address
|
||||||
target aarch64 has_pauth sign_return_address
|
target aarch64 has_pauth sign_return_address
|
||||||
target s390x
|
target s390x
|
||||||
|
target riscv64
|
||||||
|
|
||||||
|
|
||||||
function %callee_i64(i64) -> i64 {
|
function %callee_i64(i64) -> i64 {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ test run
|
|||||||
target x86_64
|
target x86_64
|
||||||
; AArch64 Does not have these libcalls
|
; AArch64 Does not have these libcalls
|
||||||
target s390x
|
target s390x
|
||||||
|
target riscv64
|
||||||
|
|
||||||
|
|
||||||
function %libcall_ceilf32(f32) -> f32 {
|
function %libcall_ceilf32(f32) -> f32 {
|
||||||
|
|||||||
@@ -3,6 +3,14 @@ use cranelift_module::ModuleExtName;
|
|||||||
use cranelift_module::ModuleReloc;
|
use cranelift_module::ModuleReloc;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
/// Reads a 32bit instruction at `iptr`, and writes it again after
|
||||||
|
/// being altered by `modifier`
|
||||||
|
unsafe fn modify_inst32(iptr: *mut u32, modifier: impl FnOnce(u32) -> u32) {
|
||||||
|
let inst = iptr.read_unaligned();
|
||||||
|
let new_inst = modifier(inst);
|
||||||
|
iptr.write_unaligned(new_inst);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct CompiledBlob {
|
pub(crate) struct CompiledBlob {
|
||||||
pub(crate) ptr: *mut u8,
|
pub(crate) ptr: *mut u8,
|
||||||
@@ -97,9 +105,34 @@ impl CompiledBlob {
|
|||||||
// immediate offset argument.
|
// immediate offset argument.
|
||||||
let chop = 32 - 26;
|
let chop = 32 - 26;
|
||||||
let imm26 = (diff as u32) << chop >> chop;
|
let imm26 = (diff as u32) << chop >> chop;
|
||||||
let ins = unsafe { iptr.read_unaligned() } | imm26;
|
unsafe { modify_inst32(iptr, |inst| inst | imm26) };
|
||||||
|
}
|
||||||
|
Reloc::RiscvCall => {
|
||||||
|
// A R_RISCV_CALL relocation expects auipc+jalr instruction pair.
|
||||||
|
// It is the equivalent of two relocations:
|
||||||
|
// 1. R_RISCV_PCREL_HI20 on the `auipc`
|
||||||
|
// 2. R_RISCV_PCREL_LO12_I on the `jalr`
|
||||||
|
|
||||||
|
let base = get_address(name);
|
||||||
|
let what = unsafe { base.offset(isize::try_from(addend).unwrap()) };
|
||||||
|
let pcrel = i32::try_from((what as isize) - (at as isize)).unwrap() as u32;
|
||||||
|
|
||||||
|
// See https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses
|
||||||
|
// for a better explanation of the following code.
|
||||||
|
//
|
||||||
|
// Unlike the regular symbol relocations, here both "sub-relocations" point
|
||||||
|
// to the same address.
|
||||||
|
let hi20 = pcrel.wrapping_add(0x800) & 0xFFFFF000;
|
||||||
|
let lo12 = (pcrel - hi20) & 0xFFF;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
iptr.write_unaligned(ins);
|
// Do a R_RISCV_PCREL_HI20 on the `auipc`
|
||||||
|
let auipc_addr = at as *mut u32;
|
||||||
|
modify_inst32(auipc_addr, |auipc| (auipc & 0xFFF) | hi20);
|
||||||
|
|
||||||
|
// Do a R_RISCV_PCREL_LO12_I on the `jalr`
|
||||||
|
let jalr_addr = at.offset(4) as *mut u32;
|
||||||
|
modify_inst32(jalr_addr, |jalr| (jalr & 0xFFFFF) | (lo12 << 20));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
|
|||||||
Reference in New Issue
Block a user