reid-llvm/reid-llvm-lib/src/lib.rs

229 lines
4.9 KiB
Rust

//! Reid LLVM Lib is an ergonomic Rust'y API which is used to produce a
//! Low-Level IR (LLIR) using [`Context`] and [`Builder`]. This Builder can then
//! be used at the end to compile said LLIR into LLVM IR.
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<Type>) -> 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<Type>,
}
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,
deleted: false,
},
),
}
}
}
pub fn value(&self) -> FunctionValue {
self.value
}
}
#[derive(Debug, Clone, Hash)]
pub struct BlockData {
name: String,
terminator: Option<TerminatorKind>,
deleted: bool,
}
pub struct Block<'builder> {
phantom: PhantomData<&'builder ()>,
builder: Builder,
value: BlockValue,
}
impl<'builder> Block<'builder> {
pub fn build(&mut self, instruction: Instr) -> Result<InstructionValue, ()> {
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) }
}
/// Delete block if it is unused. Return true if deleted, false if not.
pub fn delete_if_unused(&mut self) -> Result<bool, ()> {
unsafe {
if !self.builder.is_block_used(self.value()) {
self.builder.delete_block(&self.value)?;
Ok(true)
} else {
Ok(false)
}
}
}
pub fn value(&self) -> BlockValue {
self.value
}
}
#[derive(Clone, Hash)]
pub struct InstructionData {
kind: Instr,
}
#[derive(Clone, Copy, Hash)]
pub enum CmpPredicate {
LT,
LE,
GT,
GE,
EQ,
NE,
}
#[derive(Clone, Hash)]
pub enum Instr {
Param(usize),
Constant(ConstValue),
Add(InstructionValue, InstructionValue),
Sub(InstructionValue, InstructionValue),
Mult(InstructionValue, InstructionValue),
And(InstructionValue, InstructionValue),
Phi(Vec<InstructionValue>),
Alloca(String, Type),
Load(InstructionValue, Type),
Store(InstructionValue, InstructionValue),
Extract(InstructionValue, u32),
/// Integer Comparison
ICmp(CmpPredicate, InstructionValue, InstructionValue),
FunctionCall(FunctionValue, Vec<InstructionValue>),
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum Type {
I8,
I16,
I32,
I64,
I128,
U8,
U16,
U32,
U64,
U128,
Bool,
Void,
Ptr(Box<Type>),
Array(Box<Type>, u32),
}
#[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),
ConstArray(Vec<ConstValue>),
}
#[derive(Clone, Hash)]
pub enum TerminatorKind {
Ret(InstructionValue),
RetVoid,
Br(BlockValue),
CondBr(InstructionValue, BlockValue, BlockValue),
}