Skip to content

Commit

Permalink
rt: Also emit direct calls on arm64 in bootstrapped boots
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Jan 4, 2025
1 parent da8df9b commit 64ed397
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 20 deletions.
4 changes: 2 additions & 2 deletions dora-asm/src/arm64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2309,7 +2309,7 @@ mod inst {
}
}

mod cls {
pub mod cls {
use super::*;

pub(super) fn addsub_extreg(
Expand Down Expand Up @@ -3083,7 +3083,7 @@ mod cls {
| rt
}

pub(super) fn uncond_branch_imm(op: u32, imm26: i32) -> u32 {
pub fn uncond_branch_imm(op: u32, imm26: i32) -> u32 {
assert!(fits_bit(op));
assert!(fits_i26(imm26));

Expand Down
16 changes: 6 additions & 10 deletions dora-runtime/src/compiler/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,20 +555,16 @@ fn prepare_lazy_call_sites(
.expect("missing function");
let ra = code.instruction_start().offset(*offset as usize);

if mode.is_stage2_or_3() && cfg!(target_arch = "x86_64") {
let distance = target.to_usize() as isize - ra.to_usize() as isize;
let distance: i32 = distance.try_into().expect("overflow");

unsafe {
assert_eq!(std::ptr::read(ra.sub(5).to_ptr::<u8>()), 0xE8);
assert_eq!(std::ptr::read(ra.sub(4).to_ptr::<i32>()), 0);
std::ptr::write(ra.sub(4).to_mut_ptr(), distance);
}
if mode.is_stage2_or_3() {
crate::cpu::patch_direct_call_site(ra, target);
} else {
let const_pool_address = ra.ioffset(*const_pool_offset_from_ra as isize);

unsafe {
*const_pool_address.to_mut_ptr::<Address>() = target;
std::ptr::write_unaligned(
const_pool_address.to_mut_ptr::<Address>(),
target,
);
}
}
}
Expand Down
18 changes: 16 additions & 2 deletions dora-runtime/src/cpu/arm64.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#[cfg(not(target_os = "macos"))]
use std::arch::asm;

use dora_asm::arm64::cls::uncond_branch_imm;
use dora_asm::arm64::Cond;
use lazy_static::lazy_static;

use crate::masm::CondCode;
use crate::Address;

#[cfg(target_os = "macos")]
pub fn flush_icache(start: *const u8, len: usize) {
Expand Down Expand Up @@ -296,6 +298,18 @@ pub fn next_param_offset(param_offset: i32) -> i32 {
param_offset + 8
}

pub fn patch_direct_call_site(_ra: Address, _distance: i32) {
unimplemented!();
pub fn patch_direct_call_site(ra: Address, target: Address) {
let distance = target.to_usize() as isize - ra.to_usize() as isize + 4;
assert_eq!(distance % 4, 0);
let distance: i32 = distance.try_into().expect("overflow");
let distance = distance / 4;
let call = ra.sub(4).to_mut_ptr::<u32>();

let expected = uncond_branch_imm(1, 0);
let inst = uncond_branch_imm(1, distance);

unsafe {
assert_eq!(expected, std::ptr::read(call));
std::ptr::write(call, inst);
}
}
5 changes: 4 additions & 1 deletion dora-runtime/src/cpu/x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@ impl FReg {
}
}

pub fn patch_direct_call_site(ra: Address, distance: i32) {
pub fn patch_direct_call_site(ra: Address, target: Address) {
let distance = target.to_usize() as isize - ra.to_usize() as isize;
let distance: i32 = distance.try_into().expect("overflow");

unsafe {
assert_eq!(std::ptr::read(ra.sub(5).to_ptr::<u8>()), 0xE8);
assert_eq!(std::ptr::read(ra.sub(4).to_ptr::<i32>()), 0);
Expand Down
6 changes: 6 additions & 0 deletions pkgs/boots/assembler/arm64.dora
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,12 @@ impl AssemblerArm64 {
}
}

pub fn bl_imm(diff: Int32) {
assert(diff % 4i32 == 0i32);
let inst = encoding::uncond_branch_imm(1i32, diff / 4i32);
self.emit(inst);
}

pub fn bl_r(rn: Register) {
let inst = encoding::uncond_branch_reg(0b0001i32, 0b11111i32, 0i32, rn, 0i32);
self.emit(inst);
Expand Down
16 changes: 11 additions & 5 deletions pkgs/boots/codegen/arm64.dora
Original file line number Diff line number Diff line change
Expand Up @@ -569,16 +569,22 @@ impl CodeGenArm64 {
}

fn emitCall(fct_id: FunctionId, type_params: Array[BytecodeType], inlined_location: InlinedLocation, gc_point: GcPoint) {
let address = iface::getFunctionAddress(self.ci, fct_id, type_params);
let cp_entry = self.constPool.push(ConstPoolValue::Address(address));
self.loadConstPool(REG_TEMP, cp_entry, REG_TEMP2);
self.asm.bl_r(REG_TEMP);
let const_pool_offset_from_ra = if self.ci.compilationMode.isStage2or3() {
self.asm.bl_imm(0i32);
0i32
} else {
let address = iface::getFunctionAddress(self.ci, fct_id, type_params);
let cp_entry = self.constPool.push(ConstPoolValue::Address(address));
self.loadConstPool(REG_TEMP, cp_entry, REG_TEMP2);
self.asm.bl_r(REG_TEMP);
-(self.asm.position() + cp_entry.disp)
};

let pos = self.asm.position();
let site = LazyCompilationSiteDirect(
fct_id,
type_params,
const_pool_offset_from_ra = -(pos + cp_entry.disp),
const_pool_offset_from_ra,
);

self.lazyCompilation.insert(pos, LazyCompilationSite::Direct(site));
Expand Down

0 comments on commit 64ed397

Please sign in to comment.