feat: less clone, avoid evaluating not depended thunk
This commit is contained in:
@@ -4,38 +4,204 @@ use crate::ir::*;
|
||||
use crate::ty::common as c;
|
||||
use crate::ty::internal::Value;
|
||||
|
||||
use super::JITContext;
|
||||
use super::{JITContext, ValueTag};
|
||||
|
||||
pub trait JITCompile {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc>;
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc>;
|
||||
}
|
||||
|
||||
impl JITCompile for Attrs {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for List {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for HasAttr {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for BinOp {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
use ValueTag::*;
|
||||
use BinOpKind::*;
|
||||
let lhs = self.lhs.compile(ctx, func);
|
||||
let rhs = self.rhs.compile(ctx, func);
|
||||
let lhs_tag = ctx.get_tag(lhs);
|
||||
let rhs_tag = ctx.get_tag(rhs);
|
||||
let tag = ctx
|
||||
.builder
|
||||
.build_int_add(
|
||||
lhs_tag.const_shl(ctx.helpers.const_int(8)),
|
||||
rhs_tag,
|
||||
"calc_tag",
|
||||
)
|
||||
.unwrap();
|
||||
let ret = ctx.context.append_basic_block(func, "fallback");
|
||||
let res = ctx
|
||||
.builder
|
||||
.build_alloca(ctx.helpers.value_type, "res_alloca")
|
||||
.unwrap();
|
||||
match self.kind {
|
||||
Add => {
|
||||
let int_int = ctx.context.append_basic_block(func, "int_int");
|
||||
let int_float = ctx.context.append_basic_block(func, "int_float");
|
||||
let float_int = ctx.context.append_basic_block(func, "float_int");
|
||||
let float_float = ctx.context.append_basic_block(func, "float_float");
|
||||
let fallback = ctx.context.append_basic_block(func, "fallback");
|
||||
ctx.builder
|
||||
.build_switch(
|
||||
tag,
|
||||
fallback,
|
||||
&[
|
||||
(
|
||||
ctx.helpers.const_int(((Int as i64) << 8) + Int as i64),
|
||||
int_int,
|
||||
),
|
||||
(
|
||||
ctx.helpers.const_int(((Int as i64) << 8) + Float as i64),
|
||||
int_float,
|
||||
),
|
||||
(
|
||||
ctx.helpers.const_int(((Float as i64) << 8) + Int as i64),
|
||||
float_int,
|
||||
),
|
||||
(
|
||||
ctx.helpers.const_int(((Float as i64) << 8) + Float as i64),
|
||||
float_float,
|
||||
),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(int_int);
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_int_add(ctx.get_int(lhs), ctx.get_int(rhs), "add")
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
.build_store(
|
||||
res,
|
||||
ctx.helpers.value_type.const_named_struct(&[
|
||||
ctx.helpers.const_int(Int as i64).into(),
|
||||
val.into(),
|
||||
]),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(int_float);
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_float_add(
|
||||
ctx.builder
|
||||
.build_signed_int_to_float(
|
||||
ctx.get_int(lhs),
|
||||
ctx.helpers.float_type,
|
||||
"lhs_to_float",
|
||||
)
|
||||
.unwrap(),
|
||||
ctx.get_float(rhs),
|
||||
"add",
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
.build_store(
|
||||
res,
|
||||
ctx.helpers.value_type.const_named_struct(&[
|
||||
ctx.helpers.const_int(Float as i64).into(),
|
||||
val.into(),
|
||||
]),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(float_int);
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_float_add(
|
||||
ctx.get_float(lhs),
|
||||
ctx.builder
|
||||
.build_signed_int_to_float(
|
||||
ctx.get_int(rhs),
|
||||
ctx.helpers.float_type,
|
||||
"rhs_to_float",
|
||||
)
|
||||
.unwrap(),
|
||||
"add",
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
.build_store(
|
||||
res,
|
||||
ctx.helpers.value_type.const_named_struct(&[
|
||||
ctx.helpers.const_int(Float as i64).into(),
|
||||
val.into(),
|
||||
]),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(int_int);
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_float_add(ctx.get_float(lhs), ctx.get_float(rhs), "add")
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
.build_store(
|
||||
res,
|
||||
ctx.helpers.value_type.const_named_struct(&[
|
||||
ctx.helpers.const_int(Float as i64).into(),
|
||||
val.into(),
|
||||
]),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(fallback);
|
||||
}
|
||||
Or => {
|
||||
let bool_bool = ctx.context.append_basic_block(func, "int_int");
|
||||
let fallback = ctx.context.append_basic_block(func, "fallback");
|
||||
ctx.builder
|
||||
.build_switch(
|
||||
tag,
|
||||
fallback,
|
||||
&[
|
||||
(
|
||||
ctx.helpers.const_int(((Bool as i64) << 8) + Bool as i64),
|
||||
bool_bool,
|
||||
),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(bool_bool);
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_or(ctx.get_bool(lhs), ctx.get_bool(rhs), "or")
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
.build_store(
|
||||
res,
|
||||
ctx.helpers.value_type.const_named_struct(&[
|
||||
ctx.helpers.const_int(Bool as i64).into(),
|
||||
val.into(),
|
||||
]),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(fallback);
|
||||
}
|
||||
_ => todo!()
|
||||
}
|
||||
ctx.builder.position_at_end(ret);
|
||||
ctx.builder
|
||||
.build_load(ctx.helpers.value_type, res, "load_res")
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for UnOp {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!();
|
||||
let rhs = self.rhs.compile(ctx, func);
|
||||
let tag = ctx.get_tag(rhs);
|
||||
@@ -57,55 +223,55 @@ impl JITCompile for UnOp {
|
||||
}
|
||||
|
||||
impl JITCompile for Select {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for If {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for LoadFunc {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Call {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Let {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for With {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Assert {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for ConcatStrings {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Const {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
use c::Const::*;
|
||||
match self.val {
|
||||
Bool(x) => ctx.helpers.new_bool(x),
|
||||
@@ -117,37 +283,37 @@ impl JITCompile for Const {
|
||||
}
|
||||
|
||||
impl JITCompile for String {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Var {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Arg {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for LetVar {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Thunk {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Path {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,9 @@ use inkwell::module::Module;
|
||||
use inkwell::types::{FloatType, FunctionType, IntType, PointerType, StructType};
|
||||
use inkwell::values::{BasicValueEnum, FloatValue, FunctionValue, IntValue, StructValue};
|
||||
|
||||
use crate::env::VmEnv;
|
||||
use crate::env::Env;
|
||||
use crate::eval::Engine;
|
||||
use crate::ty::internal::Value;
|
||||
|
||||
use super::{JITContext, JITValue, JITValueData, ValueTag};
|
||||
|
||||
@@ -54,7 +55,7 @@ impl<'ctx> Helpers<'ctx> {
|
||||
|
||||
let new_thunk = module.add_function(
|
||||
"new_thunk",
|
||||
value_type.fn_type(&[ptr_type.into()], false),
|
||||
value_type.fn_type(&[ptr_type.into(), ptr_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let debug = module.add_function(
|
||||
@@ -102,7 +103,7 @@ impl<'ctx> Helpers<'ctx> {
|
||||
let call = module.add_function(
|
||||
"call",
|
||||
value_type.fn_type(
|
||||
&[value_type.into(), value_type.into(), ptr_type.into()],
|
||||
&[value_type.into(), ptr_type.into(), ptr_type.into(), ptr_type.into()],
|
||||
false,
|
||||
),
|
||||
None,
|
||||
@@ -234,11 +235,11 @@ extern "C" fn helper_debug(value: JITValue) {
|
||||
dbg!(value.tag);
|
||||
}
|
||||
|
||||
extern "C" fn helper_capture_env(thunk: JITValue, env: *const VmEnv) {
|
||||
extern "C" fn helper_capture_env(thunk: JITValue, env: *const Env) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
extern "C" fn helper_neg(rhs: JITValue, _env: *const VmEnv) -> JITValue {
|
||||
extern "C" fn helper_neg(rhs: JITValue, _env: *const Env) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match rhs.tag {
|
||||
Int => JITValue {
|
||||
@@ -257,7 +258,7 @@ extern "C" fn helper_neg(rhs: JITValue, _env: *const VmEnv) -> JITValue {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_not(rhs: JITValue, _env: *const VmEnv) -> JITValue {
|
||||
extern "C" fn helper_not(rhs: JITValue, _env: *const Env) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match rhs.tag {
|
||||
Bool => JITValue {
|
||||
@@ -338,21 +339,22 @@ extern "C" fn helper_or(lhs: JITValue, rhs: JITValue) -> JITValue {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_call(func: JITValue, arg: JITValue, engine: *mut Engine) -> JITValue {
|
||||
extern "C" fn helper_call(func: JITValue, args: Box<[JITValue]>, engine: NonNull<Engine>, env: NonNull<Env>) -> JITValue {
|
||||
let func = Value::from(func);
|
||||
todo!()
|
||||
}
|
||||
|
||||
extern "C" fn helper_arg(idx: usize, env: *const VmEnv) -> JITValue {
|
||||
extern "C" fn helper_arg(idx: usize, env: *const Env) -> JITValue {
|
||||
let env = unsafe { env.as_ref() }.unwrap();
|
||||
let val: JITValue = env.lookup_arg(idx).clone().into();
|
||||
val
|
||||
}
|
||||
|
||||
extern "C" fn helper_lookup_let(level: usize, idx: usize, env: *const VmEnv) -> JITValue {
|
||||
extern "C" fn helper_lookup_let(level: usize, idx: usize, env: *const Env) -> JITValue {
|
||||
todo!()
|
||||
}
|
||||
|
||||
extern "C" fn helper_lookup(sym: usize, env: *const VmEnv) -> JITValue {
|
||||
extern "C" fn helper_lookup(sym: usize, env: *const Env) -> JITValue {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ use inkwell::context::Context;
|
||||
use inkwell::execution_engine::ExecutionEngine;
|
||||
use inkwell::module::Module;
|
||||
use inkwell::values::{
|
||||
AnyValue, AsValueRef, BasicMetadataValueEnum, BasicValueEnum, IntValue, StructValue,
|
||||
AnyValue, BasicMetadataValueEnum, FloatValue, IntValue, StructValue
|
||||
};
|
||||
|
||||
use crate::env::VmEnv;
|
||||
use crate::ir::{Ir, UnOpKind};
|
||||
use crate::env::Env;
|
||||
use crate::ir::Ir;
|
||||
use crate::ty::internal::Value;
|
||||
|
||||
mod compile;
|
||||
@@ -60,10 +60,10 @@ impl From<JITValue> for Value {
|
||||
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 _) },
|
||||
}), */
|
||||
Function => Value::Func(unsafe { value.data.int as usize}),
|
||||
Thunk => Value::Thunk(unsafe {
|
||||
value.data.int as usize
|
||||
}),
|
||||
_ => todo!("not implemented for {:?}", value.tag),
|
||||
}
|
||||
}
|
||||
@@ -94,7 +94,7 @@ impl From<Value> for JITValue {
|
||||
}
|
||||
|
||||
pub struct JITFunc<'ctx>(F, PhantomData<&'ctx mut ()>);
|
||||
type F = unsafe extern "C" fn(*const VmEnv) -> JITValue;
|
||||
type F = unsafe extern "C" fn(*const Env) -> JITValue;
|
||||
|
||||
impl From<F> for JITFunc<'_> {
|
||||
fn from(value: F) -> Self {
|
||||
@@ -144,6 +144,60 @@ impl<'ctx> JITContext<'ctx> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn get_float(&self, val: StructValue<'ctx>) -> FloatValue<'ctx> {
|
||||
let alloca = self
|
||||
.builder
|
||||
.build_alloca(self.helpers.int_type, "get_value_alloca")
|
||||
.unwrap();
|
||||
self.builder.build_store(alloca, val).unwrap();
|
||||
self.builder
|
||||
.build_load(
|
||||
self.helpers.float_type,
|
||||
self.builder
|
||||
.build_struct_gep(self.helpers.value_type, alloca, 1, "get_value_gep")
|
||||
.unwrap(),
|
||||
"get_value",
|
||||
)
|
||||
.unwrap()
|
||||
.into_float_value()
|
||||
}
|
||||
|
||||
pub fn get_int(&self, val: StructValue<'ctx>) -> IntValue<'ctx> {
|
||||
let alloca = self
|
||||
.builder
|
||||
.build_alloca(self.helpers.int_type, "get_value_alloca")
|
||||
.unwrap();
|
||||
self.builder.build_store(alloca, val).unwrap();
|
||||
self.builder
|
||||
.build_load(
|
||||
self.helpers.int_type,
|
||||
self.builder
|
||||
.build_struct_gep(self.helpers.value_type, alloca, 1, "get_value_gep")
|
||||
.unwrap(),
|
||||
"get_value",
|
||||
)
|
||||
.unwrap()
|
||||
.into_int_value()
|
||||
}
|
||||
|
||||
pub fn get_bool(&self, val: StructValue<'ctx>) -> IntValue<'ctx> {
|
||||
let alloca = self
|
||||
.builder
|
||||
.build_alloca(self.helpers.bool_type, "get_value_alloca")
|
||||
.unwrap();
|
||||
self.builder.build_store(alloca, val).unwrap();
|
||||
self.builder
|
||||
.build_load(
|
||||
self.helpers.bool_type,
|
||||
self.builder
|
||||
.build_struct_gep(self.helpers.value_type, alloca, 1, "get_value_gep")
|
||||
.unwrap(),
|
||||
"get_value",
|
||||
)
|
||||
.unwrap()
|
||||
.into_int_value()
|
||||
}
|
||||
|
||||
pub fn get_tag(&self, val: StructValue<'ctx>) -> IntValue<'ctx> {
|
||||
let alloca = self
|
||||
.builder
|
||||
@@ -152,9 +206,9 @@ impl<'ctx> JITContext<'ctx> {
|
||||
self.builder.build_store(alloca, val).unwrap();
|
||||
self.builder
|
||||
.build_load(
|
||||
self.context.bool_type(),
|
||||
self.helpers.int_type,
|
||||
self.builder
|
||||
.build_struct_gep(self.helpers.value_type, alloca, 1, "get_tag_gep")
|
||||
.build_struct_gep(self.helpers.value_type, alloca, 0, "get_tag_gep")
|
||||
.unwrap(),
|
||||
"get_tag",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user