8 changed files with 10 additions and 520 deletions
@ -1,58 +1,8 @@
|
||||
//pub mod types;
|
||||
|
||||
use super::llvm; |
||||
|
||||
#[derive(thiserror::Error, Debug)] |
||||
pub enum Err { |
||||
#[error(transparent)] |
||||
Llvm(#[from] llvm::Err), |
||||
} |
||||
|
||||
pub struct Rt { |
||||
build: *mut llvm::Builder, |
||||
modul: *mut llvm::Module, |
||||
contx: *mut llvm::Context, |
||||
|
||||
jit_e: *mut llvm::Jit, |
||||
} |
||||
|
||||
impl Rt { |
||||
pub fn new() -> Result<Self, Err> { |
||||
unsafe { |
||||
llvm::target_init(); |
||||
|
||||
let jit_e = jit_engine()?; |
||||
|
||||
let contx = llvm::context_new(); |
||||
let modul = llvm::module_new_with_name_in_context( |
||||
crate::c_str!("main"), |
||||
contx, |
||||
); |
||||
let build = llvm::builder_new_in_context(contx); |
||||
|
||||
Ok(Self { build, modul, contx, jit_e }) |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl Drop for Rt { |
||||
fn drop(&mut self) { |
||||
unsafe { |
||||
llvm::builder_drop(self.build); |
||||
llvm::module_drop(self.modul); |
||||
llvm::context_drop(self.contx); |
||||
pub enum Err {} |
||||
|
||||
llvm::jit_drop(self.jit_e); |
||||
} |
||||
} |
||||
} |
||||
pub struct Rt {} |
||||
|
||||
unsafe fn jit_engine() -> Result<*mut llvm::Jit, Err> { |
||||
let mut jit = std::ptr::null_mut(); |
||||
unsafe { |
||||
llvm::Err::check(llvm::jit_new(&mut jit))?; |
||||
} |
||||
Ok(jit) |
||||
} |
||||
impl Rt {} |
||||
|
||||
// EOF
|
||||
|
@ -1,128 +0,0 @@
|
||||
use super::*; |
||||
use std::{ffi::CString, io::Read}; |
||||
|
||||
pub struct IncompleteFunction<'a> { |
||||
value: *mut llvm::Value, |
||||
block: *mut llvm::BasicBlock, |
||||
contx: &'a Context, |
||||
in_context: bool, |
||||
} |
||||
|
||||
pub struct Function { |
||||
value: *mut llvm::Value, |
||||
} |
||||
|
||||
impl<'a> IncompleteFunction<'a> { |
||||
pub fn new(c: &'a Context, name: ffi::Nts, ftyp: &Type) -> Self { |
||||
const ENT: ffi::Nts = crate::c_str!("entry"); |
||||
unsafe { |
||||
let value = |
||||
llvm::module_add_function(c.modul, name, ftyp.llvm_type()); |
||||
let block = llvm::context_append_basic_block(c.contx, value, ENT); |
||||
Self { value, block, contx: c, in_context: false } |
||||
} |
||||
} |
||||
|
||||
pub fn compile( |
||||
&mut self, datum: &Datum, |
||||
) -> Result<(*mut llvm::Type, *mut llvm::Value), Err> { |
||||
if !self.in_context { |
||||
return Err(Err::Context); |
||||
} |
||||
|
||||
unsafe { |
||||
match datum { |
||||
| Datum::Null => { |
||||
let ty = BasicType::Void.llvm_type(); |
||||
let vl = llvm::value_undef(ty); |
||||
Ok((ty, vl)) |
||||
} |
||||
| Datum::Bool(val) => { |
||||
let ty = BasicType::Bool.llvm_type(); |
||||
let vl = llvm::value_const_int(ty, *val as _, Bool::False); |
||||
Ok((ty, vl)) |
||||
} |
||||
| Datum::Char(chr) => { |
||||
let ty = BasicType::Q32_0U.llvm_type(); |
||||
let vl = llvm::value_const_int(ty, *chr as _, Bool::False); |
||||
Ok((ty, vl)) |
||||
} |
||||
| Datum::Strn(_) => { |
||||
// TODO
|
||||
Err(Err::Syntax) |
||||
} |
||||
| Datum::Symb(name) => { |
||||
// TODO: must support more than global function symbols
|
||||
let name = CString::new(name.as_bytes()).unwrap().into_raw(); |
||||
let func = |
||||
llvm::module_get_named_function(self.contx.modul, name); |
||||
CString::from_raw(name); |
||||
Ok((llvm::value_type(func), func)) |
||||
} |
||||
| Datum::Numb(num) => { |
||||
let ty = BasicType::Q64_0.llvm_type(); |
||||
let vl = llvm::value_const_int(ty, *num as _, Bool::False); |
||||
Ok((ty, vl)) |
||||
} |
||||
| Datum::Cons { cdr, car } => { |
||||
// function call
|
||||
let (ftyp, func) = self.compile(car)?; |
||||
let mut args = Vec::new(); |
||||
|
||||
let mut cdr = cdr.as_ref(); |
||||
while let Datum::Cons { cdr: cdr_next, car: car_next } = cdr { |
||||
args.push(self.compile(car_next)?.1); |
||||
cdr = cdr_next.as_ref(); |
||||
} |
||||
|
||||
let call = llvm::builder_call( |
||||
self.contx.build, |
||||
ftyp, |
||||
func, |
||||
args.as_mut_ptr(), |
||||
args.len() as _, |
||||
crate::c_str!(""), |
||||
); |
||||
|
||||
Ok((llvm::value_type(call), call)) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn begin_context( |
||||
&mut self, block: impl FnOnce(&mut Self) -> Result<(), Err>, |
||||
) -> Result<(), Err> { |
||||
unsafe { |
||||
llvm::builder_position_at_end(self.contx.build, self.block); |
||||
} |
||||
self.in_context = true; |
||||
let res = block(self); |
||||
self.in_context = false; |
||||
res |
||||
} |
||||
|
||||
pub fn complete(self) -> Result<Function, Err> { |
||||
// insert ret void
|
||||
unsafe { |
||||
llvm::builder_ret_void(self.contx.build); |
||||
} |
||||
|
||||
// verify
|
||||
let err_msg = unsafe { llvm::value_verify_func(self.value) }; |
||||
|
||||
if err_msg.is_null() { |
||||
Ok(Function::new(self.value)) |
||||
} else { |
||||
Err(llvm::get_msg_and_drop(err_msg, llvm::message_drop)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl Function { |
||||
pub fn new(value: *mut llvm::Value) -> Self { |
||||
Self { value } |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -1,23 +0,0 @@
|
||||
use super::*; |
||||
|
||||
macro_rules! nat_binop { |
||||
( $id:literal , $name:ident , $op:tt ) => { |
||||
#[nat_call($id, |Q64_0, Q64_0| -> Q64_0)] |
||||
fn $name(x: i64, y: i64) -> i64 { |
||||
x $op y |
||||
} |
||||
}; |
||||
} |
||||
|
||||
#[nat_call("dbgi", |Q64_0| -> Void)] |
||||
fn dbgi(n: i64) { |
||||
eprintln!("{}", n); |
||||
} |
||||
|
||||
nat_binop!("i+", addi, +); |
||||
nat_binop!("i-", subi, -); |
||||
nat_binop!("i*", muli, *); |
||||
nat_binop!("i/", divi, /); |
||||
nat_binop!("i%", remi, %); |
||||
|
||||
// EOF
|
@ -1,117 +0,0 @@
|
||||
use super::*; |
||||
|
||||
#[repr(u8)] |
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] |
||||
pub enum BasicType { |
||||
// 0 bit type
|
||||
Void, |
||||
|
||||
// 1 bit type
|
||||
Bool, |
||||
|
||||
// signed integers
|
||||
Q8_0, |
||||
Q16_0, |
||||
Q32_0, |
||||
Q64_0, |
||||
|
||||
// unsigned integers
|
||||
Q8_0U, |
||||
Q16_0U, |
||||
Q32_0U, |
||||
Q64_0U, |
||||
|
||||
// fixed point
|
||||
Q24_8, |
||||
Q24_8U, |
||||
|
||||
// angles
|
||||
Q16, |
||||
Q16U, |
||||
} |
||||
|
||||
#[derive(Clone)] |
||||
pub struct ArrayType { |
||||
pub size: usize, |
||||
pub memb: Box<Type>, |
||||
} |
||||
|
||||
/* |
||||
#[derive(Clone)] |
||||
pub struct StrucType { |
||||
pub memb: Vec<Type>, |
||||
} |
||||
*/ |
||||
|
||||
#[derive(Clone)] |
||||
pub struct FunctType { |
||||
pub args: Vec<Type>, |
||||
pub retn: Box<Type>, |
||||
} |
||||
|
||||
#[derive(Clone)] |
||||
pub enum Type { |
||||
Basic(BasicType), |
||||
Array(ArrayType), |
||||
//Struc(StrucType),
|
||||
Funct(FunctType), |
||||
} |
||||
|
||||
pub trait LlvmType { |
||||
unsafe fn llvm_type(&self) -> *mut llvm::Type; |
||||
} |
||||
|
||||
impl BasicType { |
||||
pub fn iter() -> impl DoubleEndedIterator<Item = Self> { |
||||
(0u8..14u8).map(|it| unsafe { std::mem::transmute(it) }) |
||||
} |
||||
} |
||||
|
||||
impl LlvmType for BasicType { |
||||
unsafe fn llvm_type(&self) -> *mut llvm::Type { |
||||
match self { |
||||
| Self::Void => llvm::type_void(), |
||||
| Self::Bool => llvm::type_int1(), |
||||
| Self::Q8_0 | Self::Q8_0U => llvm::type_int8(), |
||||
| Self::Q16_0 | Self::Q16_0U | Self::Q16 | Self::Q16U => { |
||||
llvm::type_int16() |
||||
} |
||||
| Self::Q32_0 | Self::Q32_0U | Self::Q24_8 | Self::Q24_8U => { |
||||
llvm::type_int32() |
||||
} |
||||
| Self::Q64_0 | Self::Q64_0U => llvm::type_int64(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl LlvmType for ArrayType { |
||||
unsafe fn llvm_type(&self) -> *mut llvm::Type { |
||||
llvm::type_array(self.memb.llvm_type(), self.size.cast()) |
||||
} |
||||
} |
||||
|
||||
impl LlvmType for FunctType { |
||||
unsafe fn llvm_type(&self) -> *mut llvm::Type { |
||||
let mut args = |
||||
self.args.iter().map(|arg| arg.llvm_type()).collect::<Vec<_>>(); |
||||
llvm::type_function( |
||||
self.retn.llvm_type(), |
||||
args.as_mut_ptr(), |
||||
args.len().cast(), |
||||
Bool::False, |
||||
) |
||||
} |
||||
} |
||||
|
||||
impl LlvmType for Type { |
||||
unsafe fn llvm_type(&self) -> *mut llvm::Type { |
||||
match self { |
||||
Self::Basic(ty) => ty.llvm_type(), |
||||
Self::Array(ty) => ty.llvm_type(), |
||||
//Self::Struc(ty) => ty.llvm_type(),
|
||||
Self::Funct(ty) => ty.llvm_type(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
// EOF
|
Loading…
Reference in new issue