feat(jit): support multiple arg function call

note: performance regression?
This commit is contained in:
2025-05-20 18:22:06 +08:00
parent 96fb6033a4
commit b4249ccd11
2 changed files with 40 additions and 12 deletions

View File

@@ -11,7 +11,7 @@ use crate::jit::JITValueData;
use crate::ty::internal::{Thunk, Value}; use crate::ty::internal::{Thunk, Value};
use crate::vm::{LetEnv, VM}; use crate::vm::{LetEnv, VM};
use super::{JITFunc, JITValue, ValueTag}; use super::{JITValue, ValueTag};
pub struct Helpers<'ctx> { pub struct Helpers<'ctx> {
pub int_type: IntType<'ctx>, pub int_type: IntType<'ctx>,
@@ -93,7 +93,7 @@ impl<'ctx> Helpers<'ctx> {
let call = module.add_function( let call = module.add_function(
"call", "call",
value_type.fn_type( value_type.fn_type(
&[value_type.into(), value_type.into(), ptr_type.into()], &[value_type.into(), ptr_type.into(), ptr_int_type.into(), ptr_type.into()],
false, false,
), ),
None, None,
@@ -224,7 +224,13 @@ extern "C" fn helper_neg(rhs: JITValue, _env: *const LetEnv) -> JITValue {
int: -unsafe { rhs.data.int }, int: -unsafe { rhs.data.int },
}, },
}, },
_ => todo!(), Float => JITValue {
tag: Float,
data: JITValueData {
float: -unsafe { rhs.data.float },
},
},
_ => unreachable!(),
} }
} }
@@ -238,7 +244,7 @@ extern "C" fn helper_not(rhs: JITValue, _env: *const LetEnv) -> JITValue {
bool: !unsafe { rhs.data.bool }, bool: !unsafe { rhs.data.bool },
}, },
}, },
_ => todo!(), _ => unreachable!(),
} }
} }
@@ -317,14 +323,16 @@ extern "C" fn helper_or(lhs: JITValue, rhs: JITValue) -> JITValue {
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "C" fn helper_call<'jit, 'vm>( extern "C" fn helper_call<'jit, 'vm>(
func: JITValue, func: JITValue,
arg: JITValue, args: *mut JITValue,
arity: usize,
vm: *const VM<'jit>, vm: *const VM<'jit>,
) -> JITValue { ) -> JITValue {
use ValueTag::*; use ValueTag::*;
let args = unsafe { Vec::from_raw_parts(args, arity, arity) }.into_iter().map(Value::from).collect();
match func.tag { match func.tag {
Function => { Function => {
let func: Value = func.into(); let func: Value = func.into();
func.call(unsafe { vm.as_ref() }.unwrap(), vec![arg.into()]) func.call(unsafe { vm.as_ref() }.unwrap(), args)
.unwrap() .unwrap()
.into() .into()
} }

View File

@@ -40,12 +40,14 @@ pub enum ValueTag {
} }
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)]
pub struct JITValue { pub struct JITValue {
tag: ValueTag, tag: ValueTag,
data: JITValueData, data: JITValueData,
} }
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)]
pub union JITValueData { pub union JITValueData {
int: i64, int: i64,
float: f64, float: f64,
@@ -365,11 +367,21 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
.unwrap(), .unwrap(),
)?, )?,
OpCode::Call { arity } => { OpCode::Call { arity } => {
// TODO: let args = self.builder.build_array_malloc(
assert_eq!(arity, 1); self.helpers.value_type,
let mut args = Vec::with_capacity(arity); self.helpers.int_type.const_int(arity as u64, false),
for _ in 0..arity { "malloc_args",
args.insert(0, stack.pop()); )?;
for i in 0..arity {
let ptr = unsafe {
self.builder.build_in_bounds_gep(
self.helpers.value_type,
args,
&[self.helpers.int_type.const_int(i as u64, false)],
"gep_arg",
)?
};
self.builder.build_store(ptr, stack.pop())?;
} }
let func = self let func = self
.builder .builder
@@ -385,7 +397,15 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
.builder .builder
.build_direct_call( .build_direct_call(
self.helpers.call, self.helpers.call,
&[func.into(), args[0].into(), self.new_ptr(vm).into()], &[
func.into(),
args.into(),
self.helpers
.ptr_int_type
.const_int(arity as u64, false)
.into(),
self.new_ptr(vm).into(),
],
"call", "call",
)? )?
.try_as_basic_value() .try_as_basic_value()