diff --git a/examples/simple.rs b/examples/simple.rs index a9b2592f..ecc3522e 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,5 +1,5 @@ use std::error::Error; -use Ygen::prelude::*; +use Ygen::{prelude::*, PassManager::Passes::PreComputeValue}; pub fn main() -> Result<(), Box> { let mut module = Module(); @@ -14,11 +14,18 @@ pub fn main() -> Result<(), Box> { builder.positionAtEnd(entry); let val = builder.BuildAdd(ty.arg(0), ty.arg(1)); + let add2 = builder.BuildAdd(Type::i32(5), Type::i32(5)); + let ret = builder.BuildAdd(val, add2); - builder.BuildRet( val ); + builder.BuildRet( ret ); module.verify().print(); + let mut passes = PassManager::new(); + passes.add( PreComputeValue() ); + + module.runPassMngr(passes); + println!("{}", module.dumpColored() ); diff --git a/src/IR/func.rs b/src/IR/func.rs index 86aef70f..6510708a 100644 --- a/src/IR/func.rs +++ b/src/IR/func.rs @@ -4,6 +4,7 @@ use super::Block; use super::TypeMetadata; use super::Var; use super::VerifyError; +use crate::prelude::PassManager; use crate::Support::Colorize; /// Stores the function type @@ -143,6 +144,13 @@ impl Function { Ok(()) } + + /// Runs the pass manager over all blocks + pub fn runPassMngr(&mut self, mngr: &PassManager) { + for block in &mut self.blocks { + mngr.run(block); + } + } } /// Creates a new function type diff --git a/src/IR/ir.rs b/src/IR/ir.rs index 2f0aa9f7..44497049 100644 --- a/src/IR/ir.rs +++ b/src/IR/ir.rs @@ -1,4 +1,4 @@ -use std::fmt::Debug; +use std::{any::Any, fmt::Debug, hash::Hash}; use super::{FunctionType, IRBuilder, Type, TypeMetadata, Var, VerifyError}; macro_rules! IrTypeWith3 { @@ -30,10 +30,10 @@ macro_rules! IrTypeWith3 { } }; } -/*macro_rules! IrTypeWith2 { +macro_rules! IrTypeWith2 { ($name:tt, $param1:tt, $param2:tt) => { /// An Ir node - #[derive(Debug, Clone)] + #[derive(Debug, Clone, Hash)] pub struct $name<$param1, $param2> { /// first inner value pub inner1: $param1, @@ -55,11 +55,11 @@ macro_rules! IrTypeWith3 { } } }; -}*/ +} macro_rules! IrTypeWith1 { ($name:tt, $param1:tt) => { /// An Ir node - #[derive(Debug, Clone)] + #[derive(Debug, Clone, Hash)] pub(crate) struct $name<$param1> { /// inner value pub(crate) inner1: $param1, @@ -81,6 +81,7 @@ macro_rules! IrTypeWith1 { } IrTypeWith1!(Return, T); +IrTypeWith2!(ConstAssign, T, U); IrTypeWith3!(Add, T, U, Z); use crate::Support::Colorize; @@ -90,6 +91,10 @@ impl Ir for Return { Box::new(self.clone()) } + fn name(&self) -> String { + "RetType".into() + } + fn dump(&self) -> String { let metadata: TypeMetadata = self.inner1.into(); format!("ret {} {}", metadata, self.inner1.val()) @@ -109,6 +114,10 @@ impl Ir for Return { Ok(()) } + + fn as_any(&self) -> &dyn Any { + self + } } impl Ir for Return { @@ -116,6 +125,10 @@ impl Ir for Return { Box::new(self.clone()) } + fn name(&self) -> String { + "RetVar".into() + } + fn dump(&self) -> String { format!("ret {} {}", self.inner1.ty, self.inner1.name) } @@ -133,6 +146,10 @@ impl Ir for Return { Ok(()) } + + fn as_any(&self) -> &dyn Any { + self + } } impl Ir for Add { @@ -140,6 +157,10 @@ impl Ir for Add { Box::new(self.clone()) } + fn name(&self) -> String { + "AddTypeType".into() + } + fn dump(&self) -> String { format!("{} = add {} {}, {}", self.inner3.name, self.inner3.ty, self.inner1.val(), self.inner2.val()) } @@ -155,8 +176,26 @@ impl Ir for Add { } fn verify(&self, _: FunctionType) -> Result<(), VerifyError> { + let op0Ty: TypeMetadata = self.inner1.into(); + let op1Ty: TypeMetadata = self.inner2.into(); + let op2Ty: TypeMetadata = self.inner3.ty.into(); + + if !(op0Ty == op1Ty && op1Ty == op2Ty) { + if op0Ty != op1Ty { + Err(VerifyError::Op0Op1TyNoMatch(op0Ty, op1Ty))? + } else if op1Ty != op2Ty { + Err(VerifyError::Op0Op1TyNoMatch(op1Ty, op2Ty))? + } if op0Ty != op2Ty { + Err(VerifyError::Op0Op1TyNoMatch(op0Ty, op2Ty))? + } else { todo!("unknown error variant (debug: ty0 {} ty1 {} ty2 {})", op0Ty, op1Ty, op2Ty) } + } + Ok(()) } + + fn as_any(&self) -> &dyn Any { + self + } } impl Ir for Add { @@ -164,6 +203,10 @@ impl Ir for Add { Box::new(self.clone()) } + fn name(&self) -> String { + "AddVarVar".into() + } + fn dump(&self) -> String { format!("{} = add {} {}, {}", self.inner3.name, self.inner3.ty, self.inner1.name, self.inner2.name) } @@ -195,6 +238,48 @@ impl Ir for Add { Ok(()) } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl Ir for ConstAssign { + fn dump(&self) -> String { + let meta: TypeMetadata = self.inner2.into(); + format!("{} = {} {}", self.inner1.name, meta, self.inner2.val()) + } + + fn dumpColored(&self) -> String { + let meta: TypeMetadata = self.inner2.into(); + format!("{} = {} {}", + self.inner1.name.magenta(), + meta.to_string().cyan(), + self.inner2.val().to_string().blue() + ) + } + + fn name(&self) -> String { + "AssignVarType".into() + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn verify(&self, _: FunctionType) -> Result<(), VerifyError> { + let op0Ty = self.inner1.ty; + let op1Ty = self.inner2.into(); + if op0Ty != op1Ty { + Err(VerifyError::Op0Op1TyNoMatch(op0Ty, op1Ty))? + } + + Ok(()) + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } } /// Trait for the return instruction @@ -258,12 +343,18 @@ impl BuildAdd for IRBuilder<'_> { } /// The ir trait -pub(crate) trait Ir: Debug { +pub(crate) trait Ir: Debug + Any { /// Returns the ir node as his textual representation fn dump(&self) -> String; /// Returns the ir node as his textual representation with colors fn dumpColored(&self) -> String; + /// Returns the name of the ir expr + fn name(&self) -> String; + + /// Turns the ir node to an any + fn as_any(&self) -> &dyn Any; + fn verify(&self, FuncTy: FunctionType) -> Result<(), VerifyError>; /// Clones the node into a box of `Box` @@ -275,3 +366,15 @@ impl Clone for Box { self.clone_box() } } + +/// Used for sus workaround to replace current ir node +pub trait Replace { + /// Replaces current ir node + fn replace(&mut self, other: T); +} + +impl Replace> for Box { + fn replace(&mut self, other: Box) { + *self = other + } +} \ No newline at end of file diff --git a/src/IR/module.rs b/src/IR/module.rs index 7e9ed97c..b54e1e12 100644 --- a/src/IR/module.rs +++ b/src/IR/module.rs @@ -1,3 +1,5 @@ +use crate::PassManager; + use super::{func::FunctionType, Function, VerifyError}; use std::collections::HashMap; @@ -61,7 +63,7 @@ impl Module { string } - /// Verifys if every function is correct: + /// Checks if every function is correct: /// * Checks if the return type is the actual specified return type of the function /// * Checks all ir nodes pub fn verify(&self) -> Result<(), VerifyError> { @@ -71,6 +73,13 @@ impl Module { Ok(()) } + + /// Runs the pass manager over all functions + pub fn runPassMngr(&mut self, mngr: PassManager::PassManager) { + for (_, func) in &mut self.funcs { + func.runPassMngr(&mngr) + } + } } /// Creates a new module diff --git a/src/IR/typ.rs b/src/IR/typ.rs index 446155c4..8e6c13a0 100644 --- a/src/IR/typ.rs +++ b/src/IR/typ.rs @@ -3,7 +3,7 @@ use std::fmt::Display; /// Stores a type and a value of that type /// /// If you want an empty Type consider using `TypeMetadata` -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[allow(non_camel_case_types)] pub enum Type { /// Just an u16 with a value @@ -25,7 +25,7 @@ pub enum Type { } /// Stores type metadata (just the type without data) -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[allow(non_camel_case_types)] pub enum TypeMetadata { /// u16 diff --git a/src/IR/var.rs b/src/IR/var.rs index c0092989..88990f6e 100644 --- a/src/IR/var.rs +++ b/src/IR/var.rs @@ -1,7 +1,7 @@ use super::{Block, TypeMetadata}; /// A variable -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Var { pub(crate) name: String, pub(crate) ty: TypeMetadata, diff --git a/src/PassManager/Passes/MathEval.rs b/src/PassManager/Passes/MathEval.rs new file mode 100644 index 00000000..10e1b68d --- /dev/null +++ b/src/PassManager/Passes/MathEval.rs @@ -0,0 +1,33 @@ +use crate::{prelude::*, PassManager::Pass}; + +/// ## Pass InlineConstValue
+/// Inlines constant values +pub struct PreComputeValue {} + +/// Creates a new PreComputeValue pass which is heap allocated +pub fn PreComputeValue() -> Box { + Box::from( PreComputeValue {} ) +} + +impl Pass for PreComputeValue { + fn run(&self, block: &mut crate::prelude::Block) { + for node in block.nodes.iter_mut() { + if &node.name() == "AddTypeType" { + let any = node.as_any(); + let add_node = any.downcast_ref::>().unwrap().clone(); + let res = add_node.inner1.val() + add_node.inner2.val(); + node.replace(ConstAssign::new(add_node.inner3.clone(), { + match add_node.inner3.ty { + TypeMetadata::u16 => Type::u16(res as u16), + TypeMetadata::u32 => Type::u32(res as u32), + TypeMetadata::u64 => Type::u64(res as u64), + TypeMetadata::i16 => Type::i16(res as i16), + TypeMetadata::i32 => Type::i32(res as i32), + TypeMetadata::i64 => Type::i64(res as i64), + TypeMetadata::Void => Type::Void, + } + })) + } + } + } +} \ No newline at end of file diff --git a/src/PassManager/Passes/MathInline.rs b/src/PassManager/Passes/MathInline.rs new file mode 100644 index 00000000..2e1fad75 --- /dev/null +++ b/src/PassManager/Passes/MathInline.rs @@ -0,0 +1,42 @@ +use crate::{prelude::*, PassManager::Pass}; +use std::collections::HashMap; + +/// ## Pass Pre compute value
+/// Precomputes math expressions
+/// For example:
+/// * The expression 5 * 7 gets evalutated to 35 +pub struct InlineConstValue {} + +/// Creates a new InlineConstValue pass which is heap allocated +pub fn InlineConstValue() -> Box { + Box::from( InlineConstValue {} ) +} + +impl Pass for InlineConstValue { + fn run(&self, block: &mut crate::prelude::Block) { + let mut vars: HashMap = HashMap::new(); // no use of + + for node in block.nodes.iter_mut() { + if &node.name() == "AddTypeType" { + let any = node.as_any(); + let add_node = any.downcast_ref::>().unwrap().clone(); + let var = add_node.inner3; + vars.insert(var.name.clone(), var.clone()); + } + + if &node.name() == "AddVarVar" { + let any = node.as_any(); + let add_node = any.downcast_ref::>().unwrap().clone(); + let op0 = add_node.inner1; + let op1 = add_node.inner2; + let res = add_node.inner3; + + if vars.contains_key(&op0.name) && vars.contains_key(&op1.name) { // not the most performant order but it's ok + node.replace(ConstAssign::new(res, )) + } else if vars.contains_key(&op0.name) || vars.contains_key(&op1.name) { + + } + } + } + } +} \ No newline at end of file diff --git a/src/PassManager/Passes/mod.rs b/src/PassManager/Passes/mod.rs new file mode 100644 index 00000000..de161f2f --- /dev/null +++ b/src/PassManager/Passes/mod.rs @@ -0,0 +1,5 @@ +//mod MathInline; +mod MathEval; + +pub use MathEval::PreComputeValue; +//pub use MathInline::InlineConstValue; \ No newline at end of file diff --git a/src/PassManager/mngr.rs b/src/PassManager/mngr.rs index 259d9819..6a3e3a3c 100644 --- a/src/PassManager/mngr.rs +++ b/src/PassManager/mngr.rs @@ -3,11 +3,11 @@ use crate::IR::Block; use super::Pass; /// The manager of all passes (PassManager) -pub struct PassManager { - passes: VecDeque, +pub struct PassManager { + passes: VecDeque>, } -impl PassManager where T: Pass + Clone { +impl PassManager { /// Creates an new pass manager pub fn new() -> Self { Self { @@ -16,13 +16,13 @@ impl PassManager where T: Pass + Clone { } /// Adds a new pass to the back of the pass queue - pub fn add(&mut self, pass: T) { - self.passes.push_back( pass.clone() ); + pub fn add(&mut self, pass: Box) { + self.passes.push_back( pass ); } /// Adds a new pass to the front of the pass queue - pub fn add_front(&mut self, pass: T) { - self.passes.push_front( pass.clone() ); + pub fn addFront(&mut self, pass: Box) { + self.passes.push_front( pass ); } /// Executes the entire pass queue diff --git a/src/PassManager/mod.rs b/src/PassManager/mod.rs index 52f2b634..43bc094f 100644 --- a/src/PassManager/mod.rs +++ b/src/PassManager/mod.rs @@ -1,5 +1,7 @@ mod mngr; mod template; +/// all passes +pub mod Passes; pub use mngr::PassManager; pub use template::Pass; \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index aeace7ee..2b7ed790 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ pub mod prelude { pub use crate::IR::*; pub use crate::Target::Triple; pub use crate::Support::PrintErrorAndExit; + pub use crate::PassManager::PassManager; pub use crate::IR::ir::*; }