add support for getting a function pointer from a function symbol

This commit is contained in:
Folkert 2023-04-23 15:17:49 +02:00
parent 5a297248e2
commit c22f33ec8a
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
3 changed files with 60 additions and 29 deletions

View file

@ -522,6 +522,16 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
todo!("calling functions literal for AArch64"); todo!("calling functions literal for AArch64");
} }
#[inline(always)]
fn function_pointer(
_buf: &mut Vec<'_, u8>,
_relocs: &mut Vec<'_, Relocation>,
_fn_name: String,
_dst: AArch64GeneralReg,
) {
todo!("calling functions literal for AArch64");
}
#[inline(always)] #[inline(always)]
fn imul_reg64_reg64_reg64( fn imul_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>, buf: &mut Vec<'_, u8>,

View file

@ -216,6 +216,13 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
fn call(buf: &mut Vec<'_, u8>, relocs: &mut Vec<'_, Relocation>, fn_name: String); fn call(buf: &mut Vec<'_, u8>, relocs: &mut Vec<'_, Relocation>, fn_name: String);
fn function_pointer(
buf: &mut Vec<'_, u8>,
relocs: &mut Vec<'_, Relocation>,
fn_name: String,
dst: GeneralReg,
);
/// Jumps by an offset of offset bytes unconditionally. /// Jumps by an offset of offset bytes unconditionally.
/// It should always generate the same number of bytes to enable replacement if offset changes. /// It should always generate the same number of bytes to enable replacement if offset changes.
/// It returns the base offset to calculate the jump from (generally the instruction after the jump). /// It returns the base offset to calculate the jump from (generally the instruction after the jump).
@ -738,6 +745,12 @@ impl<
(out.into_bump_slice(), offset) (out.into_bump_slice(), offset)
} }
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String) {
let reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
ASM::function_pointer(&mut self.buf, &mut self.relocs, fn_name, reg)
}
fn build_fn_call( fn build_fn_call(
&mut self, &mut self,
dst: &Symbol, dst: &Symbol,
@ -1589,8 +1602,7 @@ impl<
.storage_manager .storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout)); .claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![ let lowlevel_args = [
in self.env.arena;
capacity, capacity,
// alignment // alignment
Symbol::DEV_TMP, Symbol::DEV_TMP,
@ -1727,13 +1739,12 @@ impl<
.storage_manager .storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout)); .claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![ let lowlevel_args = [
in self.env.arena;
list, list,
// element // element
Symbol::DEV_TMP, Symbol::DEV_TMP,
// element_width // element_width
Symbol::DEV_TMP2 Symbol::DEV_TMP2,
]; ];
let lowlevel_arg_layouts = [list_layout, Layout::U64, Layout::U64]; let lowlevel_arg_layouts = [list_layout, Layout::U64, Layout::U64];
@ -2004,8 +2015,7 @@ impl<
.storage_manager .storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout)); .claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![ let lowlevel_args = [
in self.env.arena;
list, list,
// alignment // alignment
Symbol::DEV_TMP, Symbol::DEV_TMP,
@ -2195,27 +2205,16 @@ impl<
} }
} }
fn expr_box(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>) { fn build_ptr_write(
let element_width_symbol = Symbol::DEV_TMP; &mut self,
self.load_layout_stack_size(element_layout, element_width_symbol); sym: Symbol,
ptr: Symbol,
// Load allocation alignment (u32) value: Symbol,
let element_alignment_symbol = Symbol::DEV_TMP2; element_layout: InLayout<'a>,
self.load_layout_alignment(Layout::U32, element_alignment_symbol); ) {
self.allocate_with_refcount(
Symbol::DEV_TMP3,
element_width_symbol,
element_alignment_symbol,
);
self.free_symbol(&element_width_symbol);
self.free_symbol(&element_alignment_symbol);
// Fill pointer with the value
let ptr_reg = self let ptr_reg = self
.storage_manager .storage_manager
.load_to_general_reg(&mut self.buf, &Symbol::DEV_TMP3); .load_to_general_reg(&mut self.buf, &ptr);
let element_width = self.layout_interner.stack_size(element_layout) as u64; let element_width = self.layout_interner.stack_size(element_layout) as u64;
let element_offset = 0; let element_offset = 0;
@ -2237,6 +2236,26 @@ impl<
// box is just a pointer on the stack // box is just a pointer on the stack
let base_offset = self.storage_manager.claim_stack_area(&sym, 8); let base_offset = self.storage_manager.claim_stack_area(&sym, 8);
ASM::mov_base32_reg64(&mut self.buf, base_offset, ptr_reg); ASM::mov_base32_reg64(&mut self.buf, base_offset, ptr_reg);
}
fn expr_box(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>) {
let element_width_symbol = Symbol::DEV_TMP;
self.load_layout_stack_size(element_layout, element_width_symbol);
// Load allocation alignment (u32)
let element_alignment_symbol = Symbol::DEV_TMP2;
self.load_layout_alignment(Layout::U32, element_alignment_symbol);
self.allocate_with_refcount(
Symbol::DEV_TMP3,
element_width_symbol,
element_alignment_symbol,
);
self.free_symbol(&element_width_symbol);
self.free_symbol(&element_alignment_symbol);
self.build_ptr_write(sym, Symbol::DEV_TMP3, value, element_layout);
self.free_symbol(&Symbol::DEV_TMP3); self.free_symbol(&Symbol::DEV_TMP3);
} }

View file

@ -1184,6 +1184,8 @@ trait Backend<'a> {
ret_layout: &InLayout<'a>, ret_layout: &InLayout<'a>,
); );
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String);
/// Move a returned value into `dst` /// Move a returned value into `dst`
fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>); fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>);