feat: JIT (WIP)
This commit is contained in:
@@ -1,129 +1,146 @@
|
||||
#![allow(unused_variables)]
|
||||
use inkwell::values::{BasicValueEnum, FunctionValue};
|
||||
|
||||
use crate::ir::*;
|
||||
use crate::ty::common as c;
|
||||
use crate::ty::internal::Value;
|
||||
|
||||
use super::JITContext;
|
||||
|
||||
pub trait JITCompile {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>);
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc>;
|
||||
}
|
||||
|
||||
impl JITCompile for Attrs {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for List {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for HasAttr {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for BinOp {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for UnOp {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
todo!()
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!();
|
||||
let rhs = self.rhs.compile(ctx, func);
|
||||
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.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.build_load(ctx.helpers.value_type, res, "load_res").unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Select {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for If {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for LoadFunc {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Call {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Let {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for With {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Assert {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for ConcatStrings {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Const {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
todo!()
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
use c::Const::*;
|
||||
match self.val {
|
||||
Bool(x) => ctx.helpers.new_bool(x),
|
||||
Int(x) => ctx.helpers.new_int(x),
|
||||
Float(x) => ctx.helpers.new_float(x),
|
||||
Null => ctx.helpers.new_null(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for String {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Var {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Arg {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for LetVar {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Thunk {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JITCompile for Path {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>) {
|
||||
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> BasicValueEnum<'gc> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ 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, FunctionValue};
|
||||
use inkwell::values::{BasicValueEnum, FloatValue, FunctionValue, IntValue};
|
||||
|
||||
use crate::env::VmEnv;
|
||||
use crate::eval::Engine;
|
||||
@@ -176,20 +176,28 @@ impl<'ctx> Helpers<'ctx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_int(&self, int: i64) -> IntValue<'ctx> {
|
||||
self.int_type.const_int(int as _, false)
|
||||
}
|
||||
|
||||
pub fn new_int(&self, int: i64) -> BasicValueEnum<'ctx> {
|
||||
self.value_type
|
||||
.const_named_struct(&[
|
||||
self.int_type.const_int(ValueTag::Int as _, false).into(),
|
||||
self.int_type.const_int(int as _, false).into(),
|
||||
self.const_int(int).into()
|
||||
])
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn const_float(&self, float: f64) -> FloatValue<'ctx> {
|
||||
self.float_type.const_float(float)
|
||||
}
|
||||
|
||||
pub fn new_float(&self, float: f64) -> BasicValueEnum<'ctx> {
|
||||
self.value_type
|
||||
.const_named_struct(&[
|
||||
self.int_type.const_int(ValueTag::Float as _, false).into(),
|
||||
self.float_type.const_float(float).into(),
|
||||
self.const_float(float).into()
|
||||
])
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ use inkwell::builder::Builder;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::execution_engine::ExecutionEngine;
|
||||
use inkwell::module::Module;
|
||||
use inkwell::values::{AnyValue, AsValueRef, BasicMetadataValueEnum, BasicValueEnum, IntValue, StructValue};
|
||||
|
||||
use crate::env::VmEnv;
|
||||
use crate::ir::{Ir, UnOpKind};
|
||||
use crate::ty::internal::Value;
|
||||
|
||||
mod compile;
|
||||
@@ -135,4 +137,30 @@ impl<'ctx> JITContext<'ctx> {
|
||||
helpers,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile(&self, ir: Ir) -> JITFunc {
|
||||
|
||||
}
|
||||
|
||||
pub fn get_tag(&self, val: BasicValueEnum<'ctx>) -> IntValue<'ctx> {
|
||||
let alloca = self
|
||||
.builder
|
||||
.build_alloca(self.helpers.value_type, "get_tag_alloca").unwrap();
|
||||
self.builder.build_store(alloca, val).unwrap();
|
||||
self.builder
|
||||
.build_load(
|
||||
self.context.bool_type(),
|
||||
self.builder
|
||||
.build_struct_gep(self.helpers.value_type, alloca, 1, "get_tag_gep").unwrap(),
|
||||
"get_tag",
|
||||
).unwrap()
|
||||
.into_int_value()
|
||||
}
|
||||
|
||||
pub fn call(&self, args: &[BasicMetadataValueEnum<'ctx>]) -> StructValue<'ctx> {
|
||||
self.builder.build_call(self.helpers.call, args, "call")
|
||||
.unwrap()
|
||||
.as_any_value_enum()
|
||||
.into_struct_value()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use derive_more::{IsVariant, TryUnwrap, Unwrap};
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use ecow::EcoString;
|
||||
use hashbrown::HashMap;
|
||||
use inkwell::values::{StructValue, FunctionValue};
|
||||
use itertools::Itertools;
|
||||
use rnix::ast::HasEntry;
|
||||
use rnix::ast::{self, Expr};
|
||||
@@ -91,9 +91,9 @@ macro_rules! ir {
|
||||
}
|
||||
|
||||
impl JITCompile for Ir {
|
||||
fn compile(self, ctx: &JITContext) {
|
||||
fn compile<'ctx>(self, ctx: &JITContext<'ctx>, func: FunctionValue<'ctx>) -> StructValue<'ctx>{
|
||||
match self {
|
||||
$(Ir::$ty(ir) => ir.compile(ctx),)*
|
||||
$(Ir::$ty(ir) => ir.compile(ctx, func),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ struct Env<'a, 'env> {
|
||||
env: EnvNode<'a>,
|
||||
prev: Option<&'env Env<'a, 'env>>,
|
||||
arg_level: usize,
|
||||
let_level: usize
|
||||
let_level: usize,
|
||||
}
|
||||
|
||||
enum EnvNode<'a> {
|
||||
@@ -208,7 +208,7 @@ impl<'a, 'env> Env<'a, 'env> {
|
||||
env: EnvNode::Builtins(base),
|
||||
prev: None,
|
||||
arg_level: 0,
|
||||
let_level: 0
|
||||
let_level: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ impl<'a, 'env> Env<'a, 'env> {
|
||||
env: EnvNode::Let(map),
|
||||
prev: Some(self),
|
||||
arg_level: self.arg_level,
|
||||
let_level: self.let_level + 1
|
||||
let_level: self.let_level + 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ impl<'a, 'env> Env<'a, 'env> {
|
||||
env: EnvNode::SingleArg(ident),
|
||||
prev: Some(self),
|
||||
arg_level: self.arg_level + 1,
|
||||
let_level: self.let_level
|
||||
let_level: self.let_level,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ impl<'a, 'env> Env<'a, 'env> {
|
||||
env: EnvNode::MultiArg(map, alias),
|
||||
prev: Some(self),
|
||||
arg_level: self.arg_level + 1,
|
||||
let_level: 0
|
||||
let_level: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ impl<'a, 'env> Env<'a, 'env> {
|
||||
env: EnvNode::With,
|
||||
prev: Some(self),
|
||||
arg_level: self.arg_level,
|
||||
let_level: self.let_level
|
||||
let_level: self.let_level,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +283,9 @@ impl<'a, 'env> Env<'a, 'env> {
|
||||
}
|
||||
SingleArg(arg) => {
|
||||
if arg == ident {
|
||||
return Ok(LookupResult::SingleArg { level: arg_level - 1 });
|
||||
return Ok(LookupResult::SingleArg {
|
||||
level: arg_level - 1,
|
||||
});
|
||||
} else {
|
||||
arg_level -= 1;
|
||||
}
|
||||
@@ -295,7 +297,9 @@ impl<'a, 'env> Env<'a, 'env> {
|
||||
default: default.clone(),
|
||||
});
|
||||
} else if alias.as_ref() == Some(ident) {
|
||||
return Ok(LookupResult::SingleArg { level: arg_level - 1 });
|
||||
return Ok(LookupResult::SingleArg {
|
||||
level: arg_level - 1,
|
||||
});
|
||||
} else {
|
||||
arg_level -= 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user