use std::marker::PhantomData; use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue}; pub mod builder; pub mod compile; mod debug; mod util; // pub struct InstructionValue(BlockValue, usize); #[derive(Debug)] pub struct Context { builder: Builder, } impl Context { pub fn new() -> Context { Context { builder: Builder::new(), } } pub fn module<'ctx>(&'ctx self, name: &str) -> Module<'ctx> { let value = self.builder.add_module(ModuleData { name: name.to_owned(), }); Module { phantom: PhantomData, builder: self.builder.clone(), value, } } } #[derive(Debug, Clone, Hash)] pub struct ModuleData { name: String, } pub struct Module<'ctx> { phantom: PhantomData<&'ctx ()>, builder: Builder, value: ModuleValue, } impl<'ctx> Module<'ctx> { pub fn function(&mut self, name: &str, ret: Type, params: Vec) -> Function<'ctx> { unsafe { Function { phantom: PhantomData, builder: self.builder.clone(), value: self.builder.add_function( &self.value, FunctionData { name: name.to_owned(), ret, params, }, ), } } } pub fn value(&self) -> ModuleValue { self.value } } #[derive(Debug, Clone, Hash)] pub struct FunctionData { name: String, ret: Type, params: Vec, } pub struct Function<'ctx> { phantom: PhantomData<&'ctx ()>, builder: Builder, value: FunctionValue, } impl<'ctx> Function<'ctx> { pub fn block(&self, name: &str) -> Block<'ctx> { unsafe { Block { phantom: PhantomData, builder: self.builder.clone(), value: self.builder.add_block( &self.value, BlockData { name: name.to_owned(), terminator: None, }, ), } } } pub fn value(&self) -> FunctionValue { self.value } } #[derive(Debug, Clone, Hash)] pub struct BlockData { name: String, terminator: Option, } pub struct Block<'builder> { phantom: PhantomData<&'builder ()>, builder: Builder, value: BlockValue, } impl<'builder> Block<'builder> { pub fn build(&mut self, instruction: InstructionKind) -> Result { unsafe { self.builder .add_instruction(&self.value, InstructionData { kind: instruction }) } } pub fn terminate(&mut self, instruction: TerminatorKind) -> Result<(), ()> { unsafe { self.builder.terminate(&self.value, instruction) } } pub fn value(&self) -> BlockValue { self.value } } #[derive(Clone, Hash)] pub struct InstructionData { kind: InstructionKind, } #[derive(Clone, Copy, Hash)] pub enum CmpPredicate { LT, LE, GT, GE, EQ, NE, } #[derive(Clone, Hash)] pub enum InstructionKind { Param(usize), Constant(ConstValue), Add(InstructionValue, InstructionValue), Sub(InstructionValue, InstructionValue), Phi(Vec), /// Integer Comparison ICmp(CmpPredicate, InstructionValue, InstructionValue), FunctionCall(FunctionValue, Vec), } #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum Type { I8, I16, I32, I64, I128, U8, U16, U32, U64, U128, Bool, Void, } #[derive(Debug, Clone, Hash)] pub enum ConstValue { I8(i8), I16(i16), I32(i32), I64(i64), I128(i128), U8(u8), U16(u16), U32(u32), U64(u64), U128(u128), Bool(bool), } #[derive(Clone, Hash)] pub enum TerminatorKind { Ret(InstructionValue), Branch(BlockValue), CondBr(InstructionValue, BlockValue, BlockValue), }