Skip to content

Commit

Permalink
[INSTR COMBINE] making select into cast
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Nov 2, 2024
1 parent 6dc99c7 commit 62f12a2
Show file tree
Hide file tree
Showing 18 changed files with 340 additions and 38 deletions.
8 changes: 7 additions & 1 deletion src/IR/nodes/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fmt::Display;
use crate::Support::ColorClass;
use crate::IR::{Function, Type, TypeMetadata, Var, VerifyError};

use super::{Assign, Cmp, EvalOptVisitor, Ir};
use super::{Assign, Cmp, EvalOptVisitor, Ir, IsNode};

/// The "compare mode" (e.g: ls is equal to rs)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -113,6 +113,12 @@ impl EvalOptVisitor for Cmp {
}
}

impl IsNode for Cmp {
fn is_cmp(&self) -> bool {
true
}
}

/// The trait `BuildCmp` is used to build the cmp node
pub trait BuildCmp {
/// builds the compare node
Expand Down
8 changes: 7 additions & 1 deletion src/IR/nodes/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::path::PathBuf;

use crate::{Support::ColorClass, IR::Function};

use super::{EvalOptVisitor, Ir};
use super::{EvalOptVisitor, Ir, IsNode};

/// A node which startes a debugging line programm
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -69,6 +69,12 @@ impl EvalOptVisitor for DebugNode {
}
}

impl IsNode for DebugNode {
fn is_debug(&self) -> bool {
true
}
}

impl Function {
/// Sets the source location for debugging (all of the ir nodes will respond to the location till an new location is set)
pub fn BuildDebug(&mut self, line: i64, coloumn: i64, file: PathBuf) {
Expand Down
6 changes: 6 additions & 0 deletions src/IR/nodes/getelemptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ impl EvalOptVisitor for GetElemPtr {
}
}

impl IsNode for GetElemPtr {
fn is_getelemptr(&self) -> bool {
true
}
}

impl Function {
/// Builds the `getelemptr` node.
/// It is used for example in this c code:
Expand Down
103 changes: 76 additions & 27 deletions src/IR/nodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use select::*;
pub use getelemptr::*;

macro_rules! IrTypeWith3 {
($name:tt, $param1:tt, $param2:tt, $param3:tt) => {
($name:tt, $param1:tt, $param2:tt, $param3:tt, $is_func:ident) => {
/// An Ir node
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct $name<$param1, $param2, $param3> {
Expand All @@ -60,10 +60,16 @@ macro_rules! IrTypeWith3 {
)
}
}

impl<$param1, $param2, $param3> IsNode for $name<$param1, $param2, $param3> {
fn $is_func(&self) -> bool {
true
}
}
};
}
macro_rules! IrTypeWith2 {
($name:tt, $param1:tt, $param2:tt) => {
($name:tt, $param1:tt, $param2:tt, $is_func:ident) => {
/// An Ir node
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct $name<$param1, $param2> {
Expand All @@ -86,10 +92,16 @@ macro_rules! IrTypeWith2 {
)
}
}

impl<$param1, $param2> IsNode for $name<$param1, $param2> {
fn $is_func(&self) -> bool {
true
}
}
};
}
macro_rules! IrTypeWith1 {
($name:tt, $param1:tt) => {
($name:tt, $param1:tt, $is_func:ident) => {
/// An Ir node
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct $name<$param1> {
Expand All @@ -109,35 +121,41 @@ macro_rules! IrTypeWith1 {
)
}
}

impl<$param1> IsNode for $name<$param1> {
fn $is_func(&self) -> bool {
true
}
}
};
}

IrTypeWith1!(Return, T);
IrTypeWith3!(Call, T, U, Z);
IrTypeWith1!(Return, T, is_ret);
IrTypeWith3!(Call, T, U, Z, is_call);

IrTypeWith2!(Assign, T, U);
IrTypeWith2!(Assign, T, U, is_assign);

IrTypeWith3!(Cast, T, U, Z);
IrTypeWith3!(Cast, T, U, Z, is_cast);

IrTypeWith3!(Add, T, U, Z);
IrTypeWith3!(Sub, T, U, Z);
IrTypeWith3!(Xor, T, U, Z);
IrTypeWith3!(Or, T, U, Z);
IrTypeWith3!(And, T, U, Z);
IrTypeWith3!(Mul, T, U, Z);
IrTypeWith3!(Div, T, U, Z);
IrTypeWith3!(Rem, T, U, Z);
IrTypeWith3!(Shl, T, U, Z);
IrTypeWith3!(Shr, T, U, Z);
IrTypeWith3!(Add, T, U, Z, is_add);
IrTypeWith3!(Sub, T, U, Z, is_sub);
IrTypeWith3!(Xor, T, U, Z, is_xor);
IrTypeWith3!(Or, T, U, Z, is_or);
IrTypeWith3!(And, T, U, Z, is_and);
IrTypeWith3!(Mul, T, U, Z, is_mul);
IrTypeWith3!(Div, T, U, Z, is_div);
IrTypeWith3!(Rem, T, U, Z, is_rem);
IrTypeWith3!(Shl, T, U, Z, is_shl);
IrTypeWith3!(Shr, T, U, Z, is_shr);

IrTypeWith1!(Br, T);
IrTypeWith3!(BrCond, T, U, Z);
IrTypeWith1!(Br, T, is_br);
IrTypeWith3!(BrCond, T, U, Z, is_brcond);

IrTypeWith2!(Alloca, T, U);
IrTypeWith2!(Store, T, U);
IrTypeWith3!(Load, T, U, Z);
IrTypeWith2!(Alloca, T, U, is_alloca);
IrTypeWith2!(Store, T, U, is_store);
IrTypeWith3!(Load, T, U, Z, is_load);

IrTypeWith2!(Neg, T, U);
IrTypeWith2!(Neg, T, U, is_neg);

/// The cmp node is used to compare values
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -191,8 +209,8 @@ impl Phi {
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Select<T, U>
where T: Debug + Clone + PartialEq + Eq,
U: Debug + Clone + PartialEq + Eq,
where T: Debug + Clone + PartialEq + Eq + AsAny,
U: Debug + Clone + PartialEq + Eq + AsAny,
{
pub(crate) out: Var,
pub(crate) cond: Var,
Expand All @@ -201,9 +219,40 @@ pub struct Select<T, U>
pub(crate) no: U,
}

use crate::Support::{ColorClass, ColorProfile};
/// checks if the node is another node
#[allow(missing_docs)]
pub trait IsNode {
fn is_alloca(&self) -> bool { false }
fn is_assign(&self) -> bool { false }
fn is_cast(&self) -> bool { false }
fn is_br(&self) -> bool { false }
fn is_brcond(&self) -> bool { false }
fn is_call(&self) -> bool { false }
fn is_cmp(&self) -> bool { false }
fn is_debug(&self) -> bool { false }
fn is_getelemptr(&self) -> bool { false }
fn is_load(&self) -> bool { false }
fn is_add(&self) -> bool { false }
fn is_sub(&self) -> bool { false }
fn is_xor(&self) -> bool { false }
fn is_or(&self) -> bool { false }
fn is_and(&self) -> bool { false }
fn is_mul(&self) -> bool { false }
fn is_div(&self) -> bool { false }
fn is_rem(&self) -> bool { false }
fn is_shl(&self) -> bool { false }
fn is_shr(&self) -> bool { false }
fn is_neg(&self) -> bool { false }
fn is_phi(&self) -> bool { false }
fn is_ret(&self) -> bool { false }
fn is_select(&self) -> bool { false }
fn is_store(&self) -> bool { false }
fn is_switch(&self) -> bool { false }
}

use crate::Support::{AsAny, ColorClass, ColorProfile};
/// The ir trait
pub trait Ir: Debug + Any + EvalOptVisitor {
pub trait Ir: Debug + Any + EvalOptVisitor + IsNode {
/// Returns the ir node as his textual representation
fn dump(&self) -> String;
/// Returns the ir node as his textual representation with colors
Expand Down
8 changes: 7 additions & 1 deletion src/IR/nodes/phi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::Support::ColorClass;
use crate::IR::{Block, Function, TypeMetadata, Var};

use super::{EvalOptVisitor, Ir, Phi};
use super::{EvalOptVisitor, Ir, IsNode, Phi};

impl Ir for Phi {
fn dump(&self) -> String {
Expand Down Expand Up @@ -85,6 +85,12 @@ impl EvalOptVisitor for Phi {
}
}

impl IsNode for Phi {
fn is_phi(&self) -> bool {
true
}
}

impl Function {
/// Builds the phi node which recives variables from different blocks
pub fn BuildPhi(&mut self, typ: TypeMetadata, recipients: Vec<(&Block, Var)>) -> Var {
Expand Down
89 changes: 87 additions & 2 deletions src/IR/nodes/select.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use super::{Assign, EvalOptVisitor, Ir, Select};
use crate::{prelude::{Type, TypeMetadata, Var}, Support::ColorClass, IR::Function};
use std::any::{Any, TypeId};

use super::{Assign, EvalOptVisitor, Ir, IsNode, Select};
use crate::{prelude::{Type, TypeMetadata, Var}, Support::{AsAny, ColorClass}, IR::Function};

impl Ir for Select<Type, Type> {
fn dump(&self) -> String {
Expand Down Expand Up @@ -295,6 +297,89 @@ impl EvalOptVisitor for Select<Var, Var> {
}
}

impl<T, U> IsNode for Select<T, U>
where T: std::fmt::Debug + Clone + PartialEq + Eq + AsAny,
U: std::fmt::Debug + Clone + PartialEq + Eq + AsAny,
{
fn is_select(&self) -> bool {
true
}
}
impl<T, U> Select<T, U>
where T: std::fmt::Debug + Clone + PartialEq + Eq + AsAny + 'static,
U: std::fmt::Debug + Clone + PartialEq + Eq + AsAny + 'static,
{
/// Returns the condition
pub fn getCondition(&self) -> Var {
self.cond.to_owned()
}

/// Returns the output variable
pub fn getOut(&self) -> Var {
self.out.to_owned()
}

/// Returns the type
pub fn getSelType(&self) -> TypeMetadata {
self.out.ty
}

/// Returns if the true value is a variable
pub fn isTrueVar(&self) -> bool {
self.yes.type_id() == TypeId::of::<Var>()
}

/// Returns if the false value is a variable
pub fn isFalseVar(&self) -> bool {
self.no.type_id() == TypeId::of::<Var>()
}

/// Returns if the true value is a constant
pub fn isTrueConst(&self) -> bool {
self.yes.type_id() == TypeId::of::<Type>()
}

/// Returns if the false value is a constant
pub fn isFalseConst(&self) -> bool {
self.no.type_id() == TypeId::of::<Type>()
}

/// Returns the true value as a variable
///
/// ### Panics
///
/// panics if the true value is not a variable so first check
pub fn getTrueVar(&self) -> Var {
self.yes.as_any().downcast_ref::<Var>().unwrap().clone()
}

/// Returns if the false value is a variable
///
/// ### Panics
///
/// panics if the false value is not a variable so first check
pub fn getFalseVar(&self) -> bool {
self.no.type_id() == TypeId::of::<Var>()
}

/// Returns the true value as a constant
///
/// ### Panics
///
/// panics if the true value is not a constant so first check
pub fn getTrueConst(&self) -> Type {
self.yes.as_any().downcast_ref::<Type>().unwrap().clone()
}

/// Returns the false value as a constant
///
/// ### Panics
///
/// panics if the false value is not a constant so first check
pub fn getFalseConst(&self) -> Type {
self.no.as_any().downcast_ref::<Type>().unwrap().clone()
}
}
/// This trait is used to build the select node
pub trait BuildSelect<T, U> {
/// The select node.
Expand Down
8 changes: 7 additions & 1 deletion src/IR/nodes/switch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::HashMap;

use crate::{Support::ColorClass, IR::{BlockId, Function, Type, TypeMetadata, Var}};

use super::{Br, EvalOptVisitor, Ir};
use super::{Br, EvalOptVisitor, Ir, IsNode};

/// The switch node is used to switch
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -103,6 +103,12 @@ impl EvalOptVisitor for Switch {
}
}

impl IsNode for Switch {
fn is_switch(&self) -> bool {
true
}
}

impl Function {
/// Builds an switch statement
pub fn BuildSwitch(&mut self, source: Var, default: &BlockId, cases: HashMap<Type, &BlockId>) {
Expand Down
6 changes: 6 additions & 0 deletions src/IR/typ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@ impl Display for Type {
}
}

impl crate::Support::AsAny for Type {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}

impl Display for TypeMetadata {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match &self {
Expand Down
6 changes: 6 additions & 0 deletions src/IR/var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ impl Var {
}
}

impl crate::Support::AsAny for Var {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}

/// Creates a new variable
pub fn Var(block: &mut Block, ty: TypeMetadata) -> Var {
Var::new(block, ty)
Expand Down
Loading

0 comments on commit 62f12a2

Please sign in to comment.