feat(gc): WIP

This commit is contained in:
2025-06-02 12:00:38 +08:00
parent 20b2b6f1ef
commit d3442e87e7
7 changed files with 72 additions and 77 deletions

View File

@@ -56,7 +56,7 @@ impl<'ctx> Helpers<'ctx> {
let new_thunk = module.add_function(
"new_thunk",
value_type.fn_type(&[ptr_type.into(), ptr_type.into()], false),
value_type.fn_type(&[ptr_type.into(), ptr_type.into(), ptr_type.into()], false),
None,
);
let debug = module.add_function(
@@ -110,6 +110,7 @@ impl<'ctx> Helpers<'ctx> {
value_type.into(),
ptr_type.into(),
ptr_type.into(),
ptr_type.into(),
],
false,
),
@@ -350,6 +351,7 @@ extern "C" fn helper_call<'gc>(
func: JITValue,
arg: JITValue,
vm: *const VM<'gc>,
env: *mut VmEnv<'gc>,
mc: *const Mutation<'gc>,
) -> JITValue {
let vm = unsafe { vm.as_ref() }.unwrap();
@@ -358,7 +360,8 @@ extern "C" fn helper_call<'gc>(
match func.tag {
ValueTag::Function => {
let func = Value::from(func).unwrap_func();
func.call_compile(arg, vm, mc).unwrap().into()
let env = unsafe { &mut *env };
env.alloc_gc(func.call_compile(arg, vm, mc).unwrap(), mc).into()
}
_ => todo!(),
}
@@ -403,15 +406,17 @@ extern "C" fn helper_force<'gc>(
.unwrap()
.compile_seq(opcodes.iter().copied().rev(), vm)
.unwrap();
let val = unsafe { func.call(env.as_ref() as *const _, mc as *const _) };
let val = unsafe { func(env.as_ref() as *const _, mc as *const _) };
thunk.insert_value(val.into(), mc);
val
}
extern "C" fn helper_new_thunk(opcodes: *const OpCodes, mc: *const Mutation) -> JITValue {
Value::Thunk(Thunk::new(
extern "C" fn helper_new_thunk<'gc>(opcodes: *const OpCodes, env: *mut VmEnv<'gc>, mc: *const Mutation<'gc>) -> JITValue {
let mc = unsafe { &*mc };
let env = unsafe { &mut *env };
env.alloc_gc(Value::Thunk(Thunk::new(
unsafe { opcodes.as_ref() }.unwrap(),
unsafe { mc.as_ref() }.unwrap(),
))
mc
)), mc)
.into()
}

View File

@@ -1,10 +1,11 @@
use std::marker::PhantomData;
use std::ops::Deref;
use gc_arena::{Collect, Gc, Mutation};
use inkwell::OptimizationLevel;
use inkwell::builder::Builder;
use inkwell::context::Context;
use inkwell::execution_engine::{ExecutionEngine, JitFunction};
use inkwell::execution_engine::ExecutionEngine;
use inkwell::module::Module;
use inkwell::values::{BasicValueEnum, FunctionValue, PointerValue};
@@ -72,37 +73,13 @@ impl<'gc> From<JITValue> for Value<'gc> {
}
impl From<&Value<'_>> for JITValue {
fn from(value: &Value<'_>) -> Self {
match *value {
Value::Int(int) => JITValue {
tag: ValueTag::Int,
data: JITValueData { int },
},
Value::Func(func) => JITValue {
tag: ValueTag::Function,
data: JITValueData {
ptr: Gc::as_ptr(func) as *const _,
},
},
Value::Thunk(ref thunk) => JITValue {
tag: ValueTag::Thunk,
data: JITValueData {
ptr: Gc::as_ptr(thunk.thunk) as *const _,
},
},
_ => todo!(),
}
}
}
impl From<Value<'_>> for JITValue {
fn from(value: Value) -> Self {
fn from(value: &Value) -> Self {
match value {
Value::Int(int) => JITValue {
&Value::Int(int) => JITValue {
tag: ValueTag::Int,
data: JITValueData { int },
},
Value::Func(func) => JITValue {
&Value::Func(func) => JITValue {
tag: ValueTag::Function,
data: JITValueData {
ptr: Gc::as_ptr(func) as *const _,
@@ -119,33 +96,25 @@ impl From<Value<'_>> for JITValue {
}
}
pub struct JITFunc<'gc>(
JitFunction<'gc, unsafe extern "C" fn(*const VmEnv<'gc>, *const Mutation<'gc>) -> JITValue>,
);
pub struct JITFunc<'gc>(F<'gc>, PhantomData<fn(&'gc F<'gc>) -> &'gc F<'gc>>);
type F<'gc> = unsafe extern "C" fn(*const VmEnv<'gc>, *const Mutation<'gc>) -> JITValue;
unsafe impl<'gc> Collect<'gc> for JITFunc<'gc> {
fn trace<T: gc_arena::collect::Trace<'gc>>(&self, _: &mut T) {}
const NEEDS_TRACE: bool = false;
}
impl<'gc>
From<
JitFunction<'gc, unsafe extern "C" fn(*const VmEnv<'gc>, *const Mutation<'gc>) -> JITValue>,
> for JITFunc<'gc>
impl<'gc> From<F<'gc>> for JITFunc<'gc>
{
fn from(
value: JitFunction<
'gc,
unsafe extern "C" fn(*const VmEnv<'gc>, *const Mutation<'gc>) -> JITValue,
>,
value: F<'gc>
) -> Self {
Self(value)
Self(value, PhantomData)
}
}
impl<'gc> Deref for JITFunc<'gc> {
type Target =
JitFunction<'gc, unsafe extern "C" fn(*const VmEnv<'gc>, *const Mutation<'gc>) -> JITValue>;
type Target = F<'gc>;
fn deref(&self) -> &Self::Target {
&self.0
}
@@ -223,7 +192,7 @@ impl<'gc> JITContext<'gc> {
unsafe {
let name = func_.get_name().to_str().unwrap();
let func = self.execution_engine.get_function(name).unwrap();
Ok(func.into())
Ok(JITFunc(func.as_raw(), PhantomData))
}
} else {
todo!()
@@ -325,6 +294,7 @@ impl<'gc> JITContext<'gc> {
self.helpers.new_thunk,
&[
self.new_ptr(vm.get_thunk(idx) as *const _).into(),
env.into(),
mc.into(),
],
"call_capture_env",
@@ -477,7 +447,6 @@ impl<'gc> JITContext<'gc> {
.left()
.unwrap(),
)?,
OpCode::LookUp { sym } => stack.push(
self.builder
.build_direct_call(
@@ -503,7 +472,7 @@ impl<'gc> JITContext<'gc> {
.builder
.build_direct_call(
self.helpers.call,
&[func.into(), arg.into(), self.new_ptr(vm).into(), mc.into()],
&[func.into(), arg.into(), self.new_ptr(vm).into(), env.into(), mc.into()],
"call",
)?
.try_as_basic_value()