feat: migrate to cranelift (WIP)
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
use std::alloc::Layout;
|
||||
use std::ffi::CStr;
|
||||
use std::ptr::NonNull;
|
||||
use std::{slice, str};
|
||||
use std::alloc::alloc;
|
||||
use core::ptr::NonNull;
|
||||
use core::{slice, str};
|
||||
|
||||
use inkwell::AddressSpace;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::execution_engine::ExecutionEngine;
|
||||
use inkwell::module::Module;
|
||||
use inkwell::types::{FloatType, FunctionType, IntType, PointerType, StructType};
|
||||
use inkwell::values::{BasicValueEnum, FloatValue, FunctionValue, IntValue, StructValue};
|
||||
use cranelift::codegen::ir::ArgumentExtension;
|
||||
use cranelift::codegen::ir::ArgumentPurpose;
|
||||
use cranelift::prelude::*;
|
||||
use cranelift_module::FuncId;
|
||||
use cranelift_module::Linkage;
|
||||
use cranelift_module::Module;
|
||||
|
||||
use crate::env::Env;
|
||||
use crate::eval::Engine;
|
||||
@@ -16,153 +16,71 @@ use crate::ty::internal::Value;
|
||||
|
||||
use super::{JITContext, JITValue, JITValueData, ValueTag};
|
||||
|
||||
pub struct Helpers<'ctx> {
|
||||
pub int_type: IntType<'ctx>,
|
||||
pub float_type: FloatType<'ctx>,
|
||||
pub bool_type: IntType<'ctx>,
|
||||
pub ptr_int_type: IntType<'ctx>,
|
||||
pub ptr_type: PointerType<'ctx>,
|
||||
pub value_type: StructType<'ctx>,
|
||||
pub func_type: FunctionType<'ctx>,
|
||||
pub struct Helpers {
|
||||
pub int_type: Type,
|
||||
pub float_type: Type,
|
||||
pub bool_type: Type,
|
||||
pub ptr_int_type: Type,
|
||||
pub ptr_type: Type,
|
||||
pub value_type: Type,
|
||||
pub func_sig: Signature,
|
||||
|
||||
pub new_thunk: FunctionValue<'ctx>,
|
||||
|
||||
pub debug: FunctionValue<'ctx>,
|
||||
pub capture_env: FunctionValue<'ctx>,
|
||||
pub neg: FunctionValue<'ctx>,
|
||||
pub not: FunctionValue<'ctx>,
|
||||
pub add: FunctionValue<'ctx>,
|
||||
pub sub: FunctionValue<'ctx>,
|
||||
pub eq: FunctionValue<'ctx>,
|
||||
pub or: FunctionValue<'ctx>,
|
||||
pub call: FunctionValue<'ctx>,
|
||||
pub lookup_arg: FunctionValue<'ctx>,
|
||||
pub lookup: FunctionValue<'ctx>,
|
||||
pub force: FunctionValue<'ctx>,
|
||||
pub call: FuncId,
|
||||
pub lookup_arg: FuncId,
|
||||
pub lookup: FuncId,
|
||||
pub force: FuncId,
|
||||
|
||||
pub alloc_array: FunctionValue<'ctx>,
|
||||
pub alloc_array: FuncId,
|
||||
}
|
||||
|
||||
impl<'ctx> Helpers<'ctx> {
|
||||
impl Helpers {
|
||||
pub fn new(
|
||||
ctx: &'ctx Context,
|
||||
module: &Module<'ctx>,
|
||||
execution_engine: &ExecutionEngine<'ctx>,
|
||||
ctx: &codegen::Context,
|
||||
module: &mut dyn Module,
|
||||
) -> Self {
|
||||
let int_type = ctx.i64_type();
|
||||
let float_type = ctx.f64_type();
|
||||
let bool_type = ctx.bool_type();
|
||||
let ptr_int_type = ctx.ptr_sized_int_type(execution_engine.get_target_data(), None);
|
||||
let ptr_type = ctx.ptr_type(AddressSpace::default());
|
||||
let value_type =
|
||||
ctx.struct_type(&[int_type.into(), int_type.into(), int_type.into()], false);
|
||||
let func_type = value_type.fn_type(&[ptr_type.into(), ptr_type.into()], false);
|
||||
let int_type = types::I64;
|
||||
let float_type = types::F64;
|
||||
let bool_type = types::I8;
|
||||
// let ptr_type = ctx.ptr_type(AddressSpace::default());
|
||||
let ptr_type = module.target_config().pointer_type();
|
||||
let ptr_int_type = ptr_type;
|
||||
let value_type = types::I128;
|
||||
// let func_sig = ctx.void_type().fn_type(&[ptr_type.into(), ptr_type.into(), ptr_type.into()], false);
|
||||
let mut func_sig = Signature::new(isa::CallConv::SystemV);
|
||||
func_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
func_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
func_sig.returns.push(AbiParam { value_type, purpose: ArgumentPurpose::StructReturn, extension: ArgumentExtension::None });
|
||||
|
||||
let new_thunk = module.add_function(
|
||||
"new_thunk",
|
||||
value_type.fn_type(&[ptr_type.into(), ptr_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let capture_env = module.add_function(
|
||||
"capture_env",
|
||||
ctx
|
||||
.void_type()
|
||||
.fn_type(&[value_type.into(), ptr_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let neg = module.add_function(
|
||||
"neg",
|
||||
value_type.fn_type(&[value_type.into(), ptr_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let not = module.add_function(
|
||||
"not",
|
||||
value_type.fn_type(&[value_type.into(), ptr_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let add = module.add_function(
|
||||
"add",
|
||||
value_type.fn_type(&[value_type.into(), value_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let sub = module.add_function(
|
||||
"sub",
|
||||
value_type.fn_type(&[value_type.into(), value_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let eq = module.add_function(
|
||||
"eq",
|
||||
value_type.fn_type(&[value_type.into(), value_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let or = module.add_function(
|
||||
"or",
|
||||
value_type.fn_type(&[value_type.into(), value_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let call = module.add_function(
|
||||
"call",
|
||||
value_type.fn_type(
|
||||
&[
|
||||
value_type.into(),
|
||||
ptr_type.into(),
|
||||
ptr_int_type.into(),
|
||||
ptr_type.into(),
|
||||
ptr_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
None,
|
||||
);
|
||||
let debug = module.add_function(
|
||||
"debug",
|
||||
ctx
|
||||
.void_type()
|
||||
.fn_type(&[ptr_type.into(), int_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let lookup_arg = module.add_function(
|
||||
"lookup_arg",
|
||||
// value_type.fn_type(&[ptr_type.into(), int_type.into()], false),
|
||||
ctx.void_type().fn_type(&[ptr_type.into(), int_type.into(), ptr_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let lookup = module.add_function(
|
||||
"lookup",
|
||||
value_type.fn_type(
|
||||
&[ptr_int_type.into(), ptr_type.into(), ptr_int_type.into()],
|
||||
false,
|
||||
),
|
||||
None,
|
||||
);
|
||||
let force = module.add_function(
|
||||
"force",
|
||||
value_type.fn_type(
|
||||
&[value_type.into(), ptr_type.into(), ptr_type.into()],
|
||||
false,
|
||||
),
|
||||
None,
|
||||
);
|
||||
let alloc_array = module.add_function(
|
||||
"alloc_array",
|
||||
value_type.fn_type(&[ptr_int_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let mut call_sig = Signature::new(isa::CallConv::SystemV);
|
||||
call_sig.params.push(AbiParam { value_type, purpose: ArgumentPurpose::StructArgument(24), extension: ArgumentExtension::None });
|
||||
call_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
call_sig.params.push(AbiParam { value_type: ptr_int_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
call_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
call_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
let call = module.declare_function("helper_call", Linkage::Import, &call_sig).unwrap();
|
||||
|
||||
execution_engine.add_global_mapping(&new_thunk, helper_new_thunk as _);
|
||||
execution_engine.add_global_mapping(&debug, helper_debug as _);
|
||||
execution_engine.add_global_mapping(&capture_env, helper_capture_env as _);
|
||||
execution_engine.add_global_mapping(&neg, helper_neg as _);
|
||||
execution_engine.add_global_mapping(¬, helper_not as _);
|
||||
execution_engine.add_global_mapping(&add, helper_add as _);
|
||||
execution_engine.add_global_mapping(&sub, helper_sub as _);
|
||||
execution_engine.add_global_mapping(&eq, helper_eq as _);
|
||||
execution_engine.add_global_mapping(&or, helper_or as _);
|
||||
execution_engine.add_global_mapping(&call, helper_call as _);
|
||||
execution_engine.add_global_mapping(&lookup_arg, helper_lookup_arg as _);
|
||||
execution_engine.add_global_mapping(&lookup, helper_lookup as _);
|
||||
execution_engine.add_global_mapping(&force, helper_force as _);
|
||||
execution_engine.add_global_mapping(&alloc_array, helper_alloc_array as _);
|
||||
let mut lookup_arg_sig = Signature::new(isa::CallConv::SystemV);
|
||||
lookup_arg_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
lookup_arg_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
let lookup_arg = module.declare_function("helper_lookup_arg", Linkage::Import, &call_sig).unwrap();
|
||||
|
||||
let mut lookup_sig = Signature::new(isa::CallConv::SystemV);
|
||||
lookup_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
lookup_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
lookup_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
lookup_sig.params.push(AbiParam { value_type: ptr_int_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
let lookup = module.declare_function("helper_lookup", Linkage::Import, &call_sig).unwrap();
|
||||
|
||||
let mut force_sig = Signature::new(isa::CallConv::SystemV);
|
||||
force_sig.params.push(AbiParam { value_type, purpose: ArgumentPurpose::StructArgument(24), extension: ArgumentExtension::None });
|
||||
force_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
force_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
let force = module.declare_function("helper_force", Linkage::Import, &call_sig).unwrap();
|
||||
|
||||
let mut alloc_array_sig = Signature::new(isa::CallConv::SystemV);
|
||||
alloc_array_sig.params.push(AbiParam { value_type: ptr_int_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
|
||||
let alloc_array = module.declare_function("helper_alloc_array", Linkage::Import, &call_sig).unwrap();
|
||||
|
||||
Helpers {
|
||||
int_type,
|
||||
@@ -171,18 +89,8 @@ impl<'ctx> Helpers<'ctx> {
|
||||
ptr_int_type,
|
||||
ptr_type,
|
||||
value_type,
|
||||
func_type,
|
||||
func_sig,
|
||||
|
||||
new_thunk,
|
||||
|
||||
debug,
|
||||
capture_env,
|
||||
neg,
|
||||
not,
|
||||
add,
|
||||
sub,
|
||||
eq,
|
||||
or,
|
||||
call,
|
||||
lookup_arg,
|
||||
lookup,
|
||||
@@ -192,7 +100,7 @@ impl<'ctx> Helpers<'ctx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_value(&self, tag: ValueTag, data: BasicValueEnum<'ctx>) -> StructValue<'ctx> {
|
||||
pub fn new_value(&self, tag: ValueTag, data: BasicValueEnum) -> StructValue {
|
||||
self.value_type.const_named_struct(&[
|
||||
self.const_int(tag as i64).into(),
|
||||
data,
|
||||
@@ -200,143 +108,39 @@ impl<'ctx> Helpers<'ctx> {
|
||||
])
|
||||
}
|
||||
|
||||
pub fn const_ptr_int(&self, int: usize) -> IntValue<'ctx> {
|
||||
pub fn const_ptr_int(&self, int: usize) -> IntValue {
|
||||
self.ptr_int_type.const_int(int as _, false)
|
||||
}
|
||||
|
||||
pub fn const_int(&self, int: i64) -> IntValue<'ctx> {
|
||||
pub fn const_int(&self, int: i64) -> IntValue {
|
||||
self.int_type.const_int(int as _, false)
|
||||
}
|
||||
|
||||
pub fn new_int(&self, int: i64) -> StructValue<'ctx> {
|
||||
pub fn new_int(&self, int: i64) -> StructValue {
|
||||
self.new_value(ValueTag::Int, self.const_int(int).into())
|
||||
}
|
||||
|
||||
pub fn const_float(&self, float: f64) -> FloatValue<'ctx> {
|
||||
pub fn const_float(&self, float: f64) -> FloatValue {
|
||||
self.float_type.const_float(float)
|
||||
}
|
||||
|
||||
pub fn new_float(&self, float: f64) -> StructValue<'ctx> {
|
||||
pub fn new_float(&self, float: f64) -> StructValue {
|
||||
self.new_value(ValueTag::Float, self.const_float(float).into())
|
||||
}
|
||||
|
||||
pub fn const_bool(&self, bool: bool) -> IntValue<'ctx> {
|
||||
pub fn const_bool(&self, bool: bool) -> IntValue {
|
||||
self.bool_type.const_int(bool as _, false)
|
||||
}
|
||||
|
||||
pub fn new_bool(&self, bool: bool) -> StructValue<'ctx> {
|
||||
pub fn new_bool(&self, bool: bool) -> StructValue {
|
||||
self.new_value(ValueTag::Bool, self.const_bool(bool).into())
|
||||
}
|
||||
|
||||
pub fn new_null(&self) -> StructValue<'ctx> {
|
||||
pub fn new_null(&self) -> StructValue {
|
||||
self.new_value(ValueTag::Null, self.int_type.const_zero().into())
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_capture_env(thunk: JITValue, env: *const Env) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
extern "C" fn helper_neg(rhs: JITValue, _env: *const Env) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match rhs.tag {
|
||||
Int => JITValue {
|
||||
tag: Int,
|
||||
data: JITValueData {
|
||||
int: -unsafe { rhs.data.int },
|
||||
},
|
||||
},
|
||||
Float => JITValue {
|
||||
tag: Float,
|
||||
data: JITValueData {
|
||||
float: -unsafe { rhs.data.float },
|
||||
},
|
||||
},
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_not(rhs: JITValue, _env: *const Env) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match rhs.tag {
|
||||
Bool => JITValue {
|
||||
tag: Bool,
|
||||
data: JITValueData {
|
||||
bool: !unsafe { rhs.data.bool },
|
||||
},
|
||||
},
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_add(lhs: JITValue, rhs: JITValue) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match (lhs.tag, rhs.tag) {
|
||||
(Int, Int) => JITValue {
|
||||
tag: Int,
|
||||
data: JITValueData {
|
||||
int: unsafe { lhs.data.int + rhs.data.int },
|
||||
},
|
||||
},
|
||||
_ => todo!(
|
||||
"Addition not implemented for {:?} and {:?}",
|
||||
lhs.tag,
|
||||
rhs.tag
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_sub(lhs: JITValue, rhs: JITValue) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match (lhs.tag, rhs.tag) {
|
||||
(Int, Int) => JITValue {
|
||||
tag: Int,
|
||||
data: JITValueData {
|
||||
int: unsafe { lhs.data.int - rhs.data.int },
|
||||
},
|
||||
},
|
||||
_ => todo!(
|
||||
"Substruction not implemented for {:?} and {:?}",
|
||||
lhs.tag,
|
||||
rhs.tag
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_eq(lhs: JITValue, rhs: JITValue) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match (lhs.tag, rhs.tag) {
|
||||
(Int, Int) => JITValue {
|
||||
tag: Bool,
|
||||
data: JITValueData {
|
||||
bool: unsafe { lhs.data.int == rhs.data.int },
|
||||
},
|
||||
},
|
||||
_ => todo!(
|
||||
"Equation not implemented for {:?} and {:?}",
|
||||
lhs.tag,
|
||||
rhs.tag
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_or(lhs: JITValue, rhs: JITValue) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match (lhs.tag, rhs.tag) {
|
||||
(Bool, Bool) => JITValue {
|
||||
tag: Bool,
|
||||
data: JITValueData {
|
||||
bool: unsafe { lhs.data.bool || rhs.data.bool },
|
||||
},
|
||||
},
|
||||
_ => todo!(
|
||||
"Substraction not implemented for {:?} and {:?}",
|
||||
lhs.tag,
|
||||
rhs.tag
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_call(
|
||||
func: JITValue,
|
||||
args: *mut JITValue,
|
||||
@@ -354,19 +158,12 @@ extern "C" fn helper_call(
|
||||
unsafe { env.as_mut() },
|
||||
)
|
||||
.unwrap();
|
||||
todo!()
|
||||
func.into()
|
||||
}
|
||||
|
||||
extern "C" fn helper_debug(env: NonNull<Env>, level: u64) {
|
||||
dbg!(env, level);
|
||||
dbg!(unsafe { env.as_ref() }.lookup_arg(level as usize));
|
||||
}
|
||||
|
||||
extern "C" fn helper_lookup_arg(env_ptr: NonNull<Env>, level: u64, ret: NonNull<JITValue>) {
|
||||
dbg!(env_ptr, level);
|
||||
let env_ref = unsafe { env_ptr.as_ref() };
|
||||
let val: JITValue = env_ref.lookup_arg(level as usize).into();
|
||||
unsafe { ret.write(val) }
|
||||
extern "C" fn helper_lookup_arg(env: NonNull<Env>, level: u64) -> JITValue {
|
||||
let env_ref = unsafe { env.as_ref() };
|
||||
env_ref.lookup_arg(level as usize).into()
|
||||
}
|
||||
|
||||
extern "C" fn helper_lookup(env: NonNull<Env>, ptr: *const u8, len: usize) -> JITValue {
|
||||
@@ -391,10 +188,6 @@ extern "C" fn helper_force(
|
||||
todo!()
|
||||
}
|
||||
|
||||
extern "C" fn helper_new_thunk(opcodes: *const ()) -> JITValue {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe extern "C" fn helper_alloc_array(len: usize) -> *mut u8 {
|
||||
unsafe { std::alloc::alloc(Layout::array::<JITValue>(len).unwrap()) }
|
||||
unsafe { alloc(Layout::array::<JITValue>(len).unwrap()) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user