feat: JIT (WIP)
This commit is contained in:
@@ -88,10 +88,7 @@ impl JITCompile for BinOp {
|
|||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(
|
.build_store(
|
||||||
res,
|
res,
|
||||||
ctx.helpers.value_type.const_named_struct(&[
|
ctx.helpers.new_value(Int, val.into())
|
||||||
ctx.helpers.const_int(Int as i64).into(),
|
|
||||||
val.into(),
|
|
||||||
]),
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.builder.position_at_end(int_float);
|
ctx.builder.position_at_end(int_float);
|
||||||
@@ -112,10 +109,7 @@ impl JITCompile for BinOp {
|
|||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(
|
.build_store(
|
||||||
res,
|
res,
|
||||||
ctx.helpers.value_type.const_named_struct(&[
|
ctx.helpers.new_value(Float, val.into())
|
||||||
ctx.helpers.const_int(Float as i64).into(),
|
|
||||||
val.into(),
|
|
||||||
]),
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.builder.position_at_end(float_int);
|
ctx.builder.position_at_end(float_int);
|
||||||
@@ -136,10 +130,7 @@ impl JITCompile for BinOp {
|
|||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(
|
.build_store(
|
||||||
res,
|
res,
|
||||||
ctx.helpers.value_type.const_named_struct(&[
|
ctx.helpers.new_value(Float, val.into())
|
||||||
ctx.helpers.const_int(Float as i64).into(),
|
|
||||||
val.into(),
|
|
||||||
]),
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.builder.position_at_end(int_int);
|
ctx.builder.position_at_end(int_int);
|
||||||
@@ -150,10 +141,7 @@ impl JITCompile for BinOp {
|
|||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(
|
.build_store(
|
||||||
res,
|
res,
|
||||||
ctx.helpers.value_type.const_named_struct(&[
|
ctx.helpers.new_value(Float, val.into())
|
||||||
ctx.helpers.const_int(Float as i64).into(),
|
|
||||||
val.into(),
|
|
||||||
]),
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.builder.position_at_end(fallback);
|
ctx.builder.position_at_end(fallback);
|
||||||
@@ -179,10 +167,7 @@ impl JITCompile for BinOp {
|
|||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(
|
.build_store(
|
||||||
res,
|
res,
|
||||||
ctx.helpers.value_type.const_named_struct(&[
|
ctx.helpers.new_value(Bool, val.into())
|
||||||
ctx.helpers.const_int(Bool as i64).into(),
|
|
||||||
val.into(),
|
|
||||||
]),
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ctx.builder.position_at_end(fallback);
|
ctx.builder.position_at_end(fallback);
|
||||||
@@ -233,8 +218,8 @@ impl JITCompile for If {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl JITCompile for LoadFunc {
|
impl JITCompile for LoadFunc {
|
||||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
fn compile<'gc>(&self, ctx: &JITContext<'gc>, _: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||||
todo!()
|
ctx.helpers.new_value(ValueTag::Function, ctx.helpers.const_int(self.idx as i64).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,8 +290,8 @@ impl JITCompile for LetVar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl JITCompile for Thunk {
|
impl JITCompile for Thunk {
|
||||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
fn compile<'gc>(&self, ctx: &JITContext<'gc>, _: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||||
todo!()
|
ctx.helpers.new_value(ValueTag::Thunk, ctx.helpers.const_int(self.idx as i64).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ impl<'ctx> Helpers<'ctx> {
|
|||||||
let bool_type = context.bool_type();
|
let bool_type = context.bool_type();
|
||||||
let ptr_int_type = context.ptr_sized_int_type(execution_engine.get_target_data(), None);
|
let ptr_int_type = context.ptr_sized_int_type(execution_engine.get_target_data(), None);
|
||||||
let ptr_type = context.ptr_type(AddressSpace::default());
|
let ptr_type = context.ptr_type(AddressSpace::default());
|
||||||
let value_type = context.struct_type(&[int_type.into(), int_type.into()], false);
|
let value_type = context.struct_type(&[int_type.into(), int_type.into(), int_type.into()], false);
|
||||||
let func_type = value_type.fn_type(&[ptr_type.into()], false);
|
let func_type = value_type.fn_type(&[ptr_type.into()], false);
|
||||||
|
|
||||||
let new_thunk = module.add_function(
|
let new_thunk = module.add_function(
|
||||||
@@ -182,17 +182,20 @@ impl<'ctx> Helpers<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_value(&self, tag: ValueTag, data: BasicValueEnum<'ctx>) -> StructValue<'ctx> {
|
||||||
|
self.value_type.const_named_struct(&[
|
||||||
|
self.const_int(tag as i64).into(),
|
||||||
|
data,
|
||||||
|
self.int_type.const_zero().into()
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
pub fn const_int(&self, int: i64) -> IntValue<'ctx> {
|
pub fn const_int(&self, int: i64) -> IntValue<'ctx> {
|
||||||
self.int_type.const_int(int as _, false)
|
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<'ctx> {
|
||||||
self.value_type
|
self.new_value(ValueTag::Int, self.const_int(int).into())
|
||||||
.const_named_struct(&[
|
|
||||||
self.int_type.const_int(ValueTag::Int as _, false).into(),
|
|
||||||
self.const_int(int).into(),
|
|
||||||
])
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_float(&self, float: f64) -> FloatValue<'ctx> {
|
pub fn const_float(&self, float: f64) -> FloatValue<'ctx> {
|
||||||
@@ -200,39 +203,19 @@ impl<'ctx> Helpers<'ctx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_float(&self, float: f64) -> StructValue<'ctx> {
|
pub fn new_float(&self, float: f64) -> StructValue<'ctx> {
|
||||||
self.value_type
|
self.new_value(ValueTag::Float, self.const_float(float).into())
|
||||||
.const_named_struct(&[
|
}
|
||||||
self.int_type.const_int(ValueTag::Float as _, false).into(),
|
|
||||||
self.const_float(float).into(),
|
pub fn const_bool(&self, bool: bool) -> IntValue<'ctx> {
|
||||||
])
|
self.bool_type.const_int(bool as _, false)
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_bool(&self, bool: bool) -> StructValue<'ctx> {
|
pub fn new_bool(&self, bool: bool) -> StructValue<'ctx> {
|
||||||
self.value_type
|
self.new_value(ValueTag::Bool, self.const_bool(bool).into())
|
||||||
.const_named_struct(&[
|
|
||||||
self.int_type.const_int(ValueTag::Bool as _, false).into(),
|
|
||||||
self.bool_type.const_int(bool as _, false).into(),
|
|
||||||
])
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_null(&self) -> StructValue<'ctx> {
|
pub fn new_null(&self) -> StructValue<'ctx> {
|
||||||
self.value_type
|
self.new_value(ValueTag::Null, self.int_type.const_zero().into())
|
||||||
.const_named_struct(&[
|
|
||||||
self.int_type.const_int(ValueTag::Null as _, false).into(),
|
|
||||||
self.int_type.const_zero().into(),
|
|
||||||
])
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn const_string(&self, string: *const u8) -> StructValue<'ctx> {
|
|
||||||
self.value_type
|
|
||||||
.const_named_struct(&[
|
|
||||||
self.int_type.const_int(ValueTag::String as _, false).into(),
|
|
||||||
self.ptr_int_type.const_int(string as _, false).into(),
|
|
||||||
])
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use inkwell::OptimizationLevel;
|
use inkwell::OptimizationLevel;
|
||||||
use inkwell::builder::Builder;
|
use inkwell::builder::Builder;
|
||||||
@@ -18,9 +19,6 @@ mod helpers;
|
|||||||
pub use compile::JITCompile;
|
pub use compile::JITCompile;
|
||||||
use helpers::Helpers;
|
use helpers::Helpers;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test;
|
|
||||||
|
|
||||||
#[repr(u64)]
|
#[repr(u64)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ValueTag {
|
pub enum ValueTag {
|
||||||
@@ -50,6 +48,14 @@ pub union JITValueData {
|
|||||||
float: f64,
|
float: f64,
|
||||||
bool: bool,
|
bool: bool,
|
||||||
ptr: *const (),
|
ptr: *const (),
|
||||||
|
slice: Slice
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Slice {
|
||||||
|
ptr: *const (),
|
||||||
|
len: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<JITValue> for Value {
|
impl From<JITValue> for Value {
|
||||||
@@ -72,18 +78,19 @@ impl From<Value> for JITValue {
|
|||||||
tag: ValueTag::Int,
|
tag: ValueTag::Int,
|
||||||
data: JITValueData { int },
|
data: JITValueData { int },
|
||||||
},
|
},
|
||||||
/* Value::Func(func) => JITValue {
|
Value::List(list) => JITValue { tag: ValueTag::List, data: JITValueData { slice: Slice { ptr: list.as_ptr() as *const (), len: list.len() } } },
|
||||||
|
Value::Func(idx) => JITValue {
|
||||||
tag: ValueTag::Function,
|
tag: ValueTag::Function,
|
||||||
data: JITValueData {
|
data: JITValueData {
|
||||||
ptr: Rc::into_raw(func) as *const _,
|
int: idx as i64
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Value::Thunk(thunk) => JITValue {
|
Value::Thunk(idx) => JITValue {
|
||||||
tag: ValueTag::Thunk,
|
tag: ValueTag::Thunk,
|
||||||
data: JITValueData {
|
data: JITValueData {
|
||||||
ptr: Rc::into_raw(thunk.thunk) as *const _,
|
int: idx as i64
|
||||||
},
|
},
|
||||||
}, */
|
},
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +143,7 @@ impl<'ctx> JITContext<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(&self, ir: Ir) -> JITFunc {
|
pub fn compile(&self, ir: Ir) -> JITFunc<'ctx> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
extern crate test;
|
|
||||||
|
|
||||||
use hashbrown::{HashMap, HashSet};
|
|
||||||
|
|
||||||
use inkwell::context::Context;
|
|
||||||
|
|
||||||
use ecow::EcoString;
|
|
||||||
|
|
||||||
use super::JITContext;
|
|
||||||
use crate::ir::downgrade;
|
|
||||||
use crate::ty::common::Const;
|
|
||||||
use crate::ty::public::*;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn test_expr(expr: &str, expected: Value) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! map {
|
|
||||||
($($k:expr => $v:expr),*) => {
|
|
||||||
{
|
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut m = HashMap::new();
|
|
||||||
$(
|
|
||||||
m.insert($k, $v);
|
|
||||||
)*
|
|
||||||
m
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! thunk {
|
|
||||||
() => {
|
|
||||||
Value::Thunk
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! int {
|
|
||||||
($e:expr) => {
|
|
||||||
Value::Const(Const::Int($e))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! float {
|
|
||||||
($e:expr) => {
|
|
||||||
Value::Const(Const::Float($e as f64))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! boolean {
|
|
||||||
($e:expr) => {
|
|
||||||
Value::Const(Const::Bool($e))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! string {
|
|
||||||
($e:expr) => {
|
|
||||||
Value::Const(Const::String(EcoString::from($e)))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! symbol {
|
|
||||||
($e:expr) => {
|
|
||||||
Symbol::from($e.to_string())
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! list {
|
|
||||||
($($x:tt)*) => (
|
|
||||||
Value::List(List::new(vec![$($x)*]))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! attrs {
|
|
||||||
($($x:tt)*) => (
|
|
||||||
Value::AttrSet(AttrSet::new(map!{$($x)*}))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_jit_const() {
|
|
||||||
// test_expr("let f = _: 1; in (f 1) + (f 1)", int!(2));
|
|
||||||
test_expr("let f = _: 1; in (f 1) == (f 1)", boolean!(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_arith() {
|
|
||||||
test_expr("let f = _: -(-1); in (f 1) + (f 1)", int!(2));
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user