Files
nixjit/src/eval/jit/mod.rs

139 lines
3.1 KiB
Rust

use std::marker::PhantomData;
use std::ops::Deref;
use inkwell::OptimizationLevel;
use inkwell::builder::Builder;
use inkwell::context::Context;
use inkwell::execution_engine::ExecutionEngine;
use inkwell::module::Module;
use crate::env::VmEnv;
use crate::ty::internal::Value;
mod compile;
mod helpers;
pub use compile::JITCompile;
use helpers::Helpers;
#[cfg(test)]
mod test;
#[repr(u64)]
#[derive(Debug, Clone, Copy)]
pub enum ValueTag {
Null,
Int,
Float,
String,
Bool,
AttrSet,
List,
Function,
Thunk,
Path,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct JITValue {
tag: ValueTag,
data: JITValueData,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union JITValueData {
int: i64,
float: f64,
bool: bool,
ptr: *const (),
}
impl From<JITValue> for Value {
fn from(value: JITValue) -> Self {
use ValueTag::*;
match value.tag {
Int => Value::Int(unsafe { value.data.int }),
Null => Value::Null,
/* Function => Value::Func(unsafe { Rc::from_raw(value.data.ptr as *const _) }),
Thunk => Value::Thunk(self::Thunk {
thunk: unsafe { Rc::from_raw(value.data.ptr as *const _) },
}), */
_ => todo!("not implemented for {:?}", value.tag),
}
}
}
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: Rc::into_raw(func) as *const _,
},
},
Value::Thunk(thunk) => JITValue {
tag: ValueTag::Thunk,
data: JITValueData {
ptr: Rc::into_raw(thunk.thunk) as *const _,
},
}, */
_ => todo!(),
}
}
}
pub struct JITFunc<'ctx>(F, PhantomData<&'ctx mut ()>);
type F = unsafe extern "C" fn(*const VmEnv) -> JITValue;
impl From<F> for JITFunc<'_> {
fn from(value: F) -> Self {
Self(value, PhantomData)
}
}
impl Deref for JITFunc<'_> {
type Target = F;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct JITContext<'ctx> {
context: &'ctx Context,
module: Module<'ctx>,
builder: Builder<'ctx>,
execution_engine: ExecutionEngine<'ctx>,
helpers: Helpers<'ctx>,
}
impl<'ctx> JITContext<'ctx> {
pub fn new(context: &'ctx Context) -> Self {
// force linker to link JIT engine
unsafe {
inkwell::llvm_sys::execution_engine::LLVMLinkInMCJIT();
}
let module = context.create_module("nixjit");
let execution_engine = module
.create_jit_execution_engine(OptimizationLevel::Aggressive)
.unwrap();
let helpers = Helpers::new(context, &module, &execution_engine);
JITContext {
execution_engine,
builder: context.create_builder(),
context,
module,
helpers,
}
}
}