feat: migrate to cranelift (WIP)
This commit is contained in:
@@ -1,70 +1,71 @@
|
||||
use std::{alloc::Layout, ffi::CStr};
|
||||
|
||||
use inkwell::values::{FunctionValue, StructValue};
|
||||
use cranelift::prelude::*;
|
||||
use cranelift::codegen::ir;
|
||||
|
||||
use crate::eval::jit::JITValue;
|
||||
use crate::ir::*;
|
||||
use crate::ty::common as c;
|
||||
use crate::ty::internal::Value;
|
||||
use crate::{eval::jit::JITValue, ir::*};
|
||||
|
||||
use super::{JITContext, ValueTag};
|
||||
|
||||
pub trait JITCompile {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc>;
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value;
|
||||
}
|
||||
|
||||
impl JITCompile for Attrs {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for List {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for HasAttr {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for BinOp {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
use BinOpKind::*;
|
||||
use ValueTag::*;
|
||||
let lhs = self.lhs.compile(ctx, func, values);
|
||||
let rhs = self.rhs.compile(ctx, func, values);
|
||||
let lhs = self.lhs.compile(ctx, builder, block);
|
||||
let rhs = self.rhs.compile(ctx, builder, block);
|
||||
let lhs_tag = ctx.get_tag(lhs);
|
||||
let rhs_tag = ctx.get_tag(rhs);
|
||||
let tag = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_int_add(
|
||||
lhs_tag.const_shl(ctx.helpers.const_int(8)),
|
||||
rhs_tag,
|
||||
@@ -73,7 +74,7 @@ impl JITCompile for BinOp {
|
||||
.unwrap();
|
||||
let ret = ctx.context.append_basic_block(func, "fallback");
|
||||
let res = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_alloca(ctx.helpers.value_type, "res_alloca")
|
||||
.unwrap();
|
||||
match self.kind {
|
||||
@@ -83,7 +84,7 @@ impl JITCompile for BinOp {
|
||||
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
|
||||
ctx.func_builder
|
||||
.build_switch(
|
||||
tag,
|
||||
fallback,
|
||||
@@ -107,19 +108,19 @@ impl JITCompile for BinOp {
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(int_int);
|
||||
ctx.func_builder.position_at_end(int_int);
|
||||
let val = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_int_add(ctx.get_int(lhs), ctx.get_int(rhs), "add")
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_store(res, ctx.helpers.new_value(Int, val.into()))
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(int_float);
|
||||
ctx.func_builder.position_at_end(int_float);
|
||||
let val = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_float_add(
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_signed_int_to_float(
|
||||
ctx.get_int(lhs),
|
||||
ctx.helpers.float_type,
|
||||
@@ -130,15 +131,15 @@ impl JITCompile for BinOp {
|
||||
"add",
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_store(res, ctx.helpers.new_value(Float, val.into()))
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(float_int);
|
||||
ctx.func_builder.position_at_end(float_int);
|
||||
let val = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_float_add(
|
||||
ctx.get_float(lhs),
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_signed_int_to_float(
|
||||
ctx.get_int(rhs),
|
||||
ctx.helpers.float_type,
|
||||
@@ -148,23 +149,23 @@ impl JITCompile for BinOp {
|
||||
"add",
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_store(res, ctx.helpers.new_value(Float, val.into()))
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(int_int);
|
||||
ctx.func_builder.position_at_end(int_int);
|
||||
let val = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_float_add(ctx.get_float(lhs), ctx.get_float(rhs), "add")
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_store(res, ctx.helpers.new_value(Float, val.into()))
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(fallback);
|
||||
ctx.func_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
|
||||
ctx.func_builder
|
||||
.build_switch(
|
||||
tag,
|
||||
fallback,
|
||||
@@ -174,20 +175,20 @@ impl JITCompile for BinOp {
|
||||
)],
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(bool_bool);
|
||||
ctx.func_builder.position_at_end(bool_bool);
|
||||
let val = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_or(ctx.get_bool(lhs), ctx.get_bool(rhs), "or")
|
||||
.unwrap();
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_store(res, ctx.helpers.new_value(Bool, val.into()))
|
||||
.unwrap();
|
||||
ctx.builder.position_at_end(fallback);
|
||||
ctx.func_builder.position_at_end(fallback);
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
ctx.builder.position_at_end(ret);
|
||||
ctx.builder
|
||||
ctx.func_builder.position_at_end(ret);
|
||||
ctx.func_builder
|
||||
.build_load(ctx.helpers.value_type, res, "load_res")
|
||||
.unwrap()
|
||||
.try_into()
|
||||
@@ -196,25 +197,25 @@ impl JITCompile for BinOp {
|
||||
}
|
||||
|
||||
impl JITCompile for UnOp {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!();
|
||||
let rhs = self.rhs.compile(ctx, func, values);
|
||||
let rhs = self.rhs.compile(ctx, builder, block);
|
||||
let tag = ctx.get_tag(rhs);
|
||||
let fallback = ctx.context.append_basic_block(func, "fallback");
|
||||
let ret = ctx.context.append_basic_block(func, "fallback");
|
||||
let res = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_alloca(ctx.helpers.value_type, "res_alloca")
|
||||
.unwrap();
|
||||
ctx.builder.build_switch(tag, fallback, &[]).unwrap();
|
||||
ctx.builder.position_at_end(fallback);
|
||||
ctx.builder.position_at_end(ret);
|
||||
ctx.builder
|
||||
ctx.func_builder.build_switch(tag, fallback, &[]).unwrap();
|
||||
ctx.func_builder.position_at_end(fallback);
|
||||
ctx.func_builder.position_at_end(ret);
|
||||
ctx.func_builder
|
||||
.build_load(ctx.helpers.value_type, res, "load_res")
|
||||
.unwrap()
|
||||
.try_into()
|
||||
@@ -223,34 +224,34 @@ impl JITCompile for UnOp {
|
||||
}
|
||||
|
||||
impl JITCompile for Select {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for If {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for LoadFunc {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
_: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
ctx.helpers.new_value(
|
||||
ValueTag::Function,
|
||||
ctx.helpers.const_int(self.idx as i64).into(),
|
||||
@@ -259,14 +260,18 @@ impl JITCompile for LoadFunc {
|
||||
}
|
||||
|
||||
impl JITCompile for Call {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
let ret = ctx
|
||||
.func_builder
|
||||
.build_alloca(ctx.helpers.value_type, "ret")
|
||||
.unwrap();
|
||||
let args = ctx
|
||||
.builder
|
||||
.func_builder
|
||||
.build_call(
|
||||
ctx.helpers.alloc_array,
|
||||
&[ctx.helpers.const_ptr_int(self.args.len()).into()],
|
||||
@@ -277,89 +282,93 @@ impl JITCompile for Call {
|
||||
.unwrap_left()
|
||||
.into_pointer_value();
|
||||
for (i, arg) in self.args.iter().enumerate() {
|
||||
ctx.builder
|
||||
.build_store(
|
||||
unsafe {
|
||||
args.const_in_bounds_gep(
|
||||
ctx.helpers.value_type,
|
||||
&[ctx.helpers.const_ptr_int(i)],
|
||||
)
|
||||
},
|
||||
arg.compile(ctx, func, values),
|
||||
)
|
||||
let arg_ptr = unsafe {
|
||||
ctx.func_builder
|
||||
.build_gep(
|
||||
ctx.helpers.value_type,
|
||||
args,
|
||||
&[ctx.helpers.const_ptr_int(i)],
|
||||
"args_gep",
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
ctx.func_builder
|
||||
.build_store(arg_ptr, arg.compile(ctx, builder, block))
|
||||
.unwrap();
|
||||
}
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_call(
|
||||
ctx.helpers.call,
|
||||
&[
|
||||
self.func.compile(ctx, func, values).into(),
|
||||
self.func.compile(ctx, builder, block).into(),
|
||||
args.into(),
|
||||
ctx.helpers.const_ptr_int(self.args.len()).into(),
|
||||
func.get_first_param().unwrap().into(),
|
||||
func.get_last_param().unwrap().into(),
|
||||
func.get_nth_param(0).unwrap().into(),
|
||||
func.get_nth_param(1).unwrap().into(),
|
||||
ret.into(),
|
||||
],
|
||||
"call",
|
||||
)
|
||||
.unwrap();
|
||||
ctx.func_builder
|
||||
.build_load(ctx.helpers.value_type, ret, "load_ret")
|
||||
.unwrap()
|
||||
.try_as_basic_value()
|
||||
.unwrap_left()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
.into_struct_value()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Let {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for With {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Assert {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for ConcatStrings {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Const {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
use c::Const::*;
|
||||
match self.val {
|
||||
Bool(x) => ctx.helpers.new_bool(x),
|
||||
@@ -371,28 +380,27 @@ impl JITCompile for Const {
|
||||
}
|
||||
|
||||
impl JITCompile for String {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Var {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
let env = func.get_nth_param(1).unwrap();
|
||||
let ptr = self.sym.as_ptr();
|
||||
let len = self.sym.len();
|
||||
// values.push(Value::String(self.sym.clone()));
|
||||
ctx.builder
|
||||
ctx.func_builder
|
||||
.build_direct_call(
|
||||
ctx.helpers.lookup,
|
||||
&[
|
||||
@@ -411,43 +419,54 @@ impl JITCompile for Var {
|
||||
}
|
||||
|
||||
impl JITCompile for Arg {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
let env = func.get_last_param().unwrap();
|
||||
let ret = ctx.builder.build_alloca(ctx.helpers.value_type, "alloca_ret").unwrap();
|
||||
ctx.builder
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
let env = builder.block_params(block)[];
|
||||
let env = func.get_nth_param(1).unwrap();
|
||||
let arg = ctx
|
||||
.func_builder
|
||||
.build_alloca(ctx.helpers.value_type, "alloca_arg")
|
||||
.unwrap();
|
||||
ctx.func_builder
|
||||
.build_direct_call(
|
||||
ctx.helpers.lookup_arg,
|
||||
&[env.into(), ctx.helpers.const_ptr_int(self.level).into(), ret.into()],
|
||||
&[
|
||||
env.into(),
|
||||
ctx.helpers.const_ptr_int(self.level).into(),
|
||||
arg.into(),
|
||||
],
|
||||
"lookup_arg",
|
||||
)
|
||||
.unwrap();
|
||||
ctx.builder.build_load(ctx.helpers.value_type,ret, "load_ret").unwrap().into_struct_value()
|
||||
ctx.func_builder
|
||||
.build_load(ctx.helpers.value_type, arg, "load_arg")
|
||||
.unwrap()
|
||||
.into_struct_value()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for LetVar {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Thunk {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
_: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
ctx.helpers.new_value(
|
||||
ValueTag::Thunk,
|
||||
ctx.helpers.const_int(self.idx as i64).into(),
|
||||
@@ -456,12 +475,12 @@ impl JITCompile for Thunk {
|
||||
}
|
||||
|
||||
impl JITCompile for Path {
|
||||
fn compile<'gc>(
|
||||
fn compile(
|
||||
&self,
|
||||
ctx: &JITContext<'gc>,
|
||||
func: FunctionValue<'gc>,
|
||||
values: &mut Vec<Value>,
|
||||
) -> StructValue<'gc> {
|
||||
ctx: &mut JITContext,
|
||||
builder: &mut FunctionBuilder,
|
||||
block: Block,
|
||||
) -> ir::Value {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user