Skip to content

Commit

Permalink
[CODE GEN] implementing whitelist
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Aug 30, 2024
1 parent 4c04958 commit 6d8e5e6
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 25 deletions.
6 changes: 3 additions & 3 deletions src/CodeGen/instr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::Obj::Link;
use super::reg::Reg;

/// a low level instruction which is portable over platforms
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MachineInstr {
pub(crate) operands: Vec<MachineOperand>,
pub(crate) out: Option<MachineOperand>,
Expand Down Expand Up @@ -58,7 +58,7 @@ impl Display for MachineInstr {
}

/// a low level operand which is portable over platforms
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MachineOperand {
/// a number
Imm(i64),
Expand All @@ -77,7 +77,7 @@ impl Display for MachineOperand {

/// The mnemonic to use
#[allow(missing_docs)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum MachineMnemonic {
Move,

Expand Down
2 changes: 1 addition & 1 deletion src/CodeGen/reg.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::Target::{x64Reg, Arch};

/// A shared enum for registers
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Reg {
/// a register of the x64 platform
x64(x64Reg),
Expand Down
7 changes: 5 additions & 2 deletions src/Optimizations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ pub mod Passes;

pub use mngr::PassManager;
pub use template::Pass;

use crate::Target::Optimize;
/// used for optimizing
pub trait Optimize<T> {
/// optimizes self
fn optimize(&mut self) -> Self;
}

/// Automaticlly optimizes the input till it doesn't change
pub fn auto_max_optimize<T, U>(target: &mut T) where T: Optimize<U> + PartialEq + Clone {
Expand Down
6 changes: 4 additions & 2 deletions src/Target/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod triple;
mod target_descr;
mod x64;
pub mod x64;
mod registry;
pub use x64::*;
mod whitelist;
pub use x64::{x64Reg, initializeX64Target, Token};
pub use whitelist::*;
pub use triple::Triple;
pub use target_descr::TargetBackendDescr;
pub use registry::TargetRegistry;
Expand Down
4 changes: 2 additions & 2 deletions src/Target/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl TargetRegistry {
if let Some(org) = self.targets.get_mut(&triple.arch) {
org.block = Some(block.clone());
let instrs = org.build_instrs(&funct, &triple);
let instrs = org.lower(instrs);
let instrs = org.lower(instrs)?;

let mut asm = vec![];

Expand All @@ -90,7 +90,7 @@ impl TargetRegistry {
org.block = Some(block.clone());

let instrs = org.build_instrs(&funct, &triple);
let instrs = org.lower(instrs);
let instrs = org.lower(instrs)?;

let mut res = vec![];
let mut links = vec![];
Expand Down
13 changes: 10 additions & 3 deletions src/Target/target_descr.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::error::Error;

use crate::prelude::{ir::*, Block, Var};
use crate::CodeGen::MCInstr;
use crate::CodeGen::{compilation::CompilationHelper, MachineInstr};
use crate::IR::{Const, Function, Type, TypeMetadata};

use super::Triple;
use super::{Triple, WhiteList};
use super::{CallConv, Compiler, Lexer};

/// The TargetBackendDescr is used to store all the functions/information to compile ir nodes into assembly
Expand All @@ -20,6 +22,8 @@ pub struct TargetBackendDescr {
pub(crate) call: CallConv,

pub(crate) sink: Vec<MachineInstr>,

pub(crate) whitelist: WhiteList,
}

macro_rules! compile_func {
Expand Down Expand Up @@ -52,6 +56,7 @@ impl TargetBackendDescr {
block: None,
call: CallConv::SystemV,
helper: None,
whitelist: WhiteList::new(),
sink: vec![],
}
}
Expand Down Expand Up @@ -94,10 +99,12 @@ impl TargetBackendDescr {
}

/// Used for lowering machine instructions into dyn MCInstr
pub fn lower(&self, instrs: Vec<MachineInstr>) -> Vec<Box<dyn MCInstr>> {
pub fn lower(&self, instrs: Vec<MachineInstr>) -> Result<Vec<Box<dyn MCInstr>>, Box<dyn Error>> {
if let Some(helper) = &self.helper {
self.whitelist.check_for_forbidden_mnemonics(&instrs)?;

if let Some(lower) = helper.lower {
lower(instrs)
Ok(lower(instrs))
} else {
todo!("the target architecture {:?} doesn't support instruction lowering", helper.arch)
}
Expand Down
81 changes: 81 additions & 0 deletions src/Target/whitelist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use std::{collections::HashMap, error::Error, fmt::Display};

use crate::CodeGen::{MachineInstr, MachineMnemonic};

/// Stores allowed instructions
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WhiteList {
instrs: HashMap<MachineMnemonic, AllowmentOption>,
}

impl WhiteList {
/// Creates a new instruction whitelist
pub fn new() -> Self {
Self {
instrs: HashMap::new()
}
}

/// Allowes a specifc mnemonic
pub fn allow(&mut self, mnemonic: MachineMnemonic) {
if let Some(option) = self.instrs.get_mut(&mnemonic) {
*option = AllowmentOption::Allowed;
} else {
self.instrs.insert(mnemonic, AllowmentOption::Allowed);
}
}

/// Forbids a specfic mnemonic
pub fn forbid(&mut self, mnemonic: MachineMnemonic) {
if let Some(option) = self.instrs.get_mut(&mnemonic) {
*option = AllowmentOption::NotAllowed;
} else {
self.instrs.insert(mnemonic, AllowmentOption::NotAllowed);
}
}

/// Checks if the mnemonic is allowed
pub fn is_allowed(&self, mnemonic: MachineMnemonic) -> AllowmentOption {
if let Some(option) = self.instrs.get(&mnemonic) {
*option
} else {
AllowmentOption::Unknown
}
}

/// Checks for forbidden mnemonics
pub fn check_for_forbidden_mnemonics(&self, vec: &Vec<MachineInstr>) -> Result<(), WhiteListError> {
for instr in vec {
if self.is_allowed(instr.mnemonic.clone()) == AllowmentOption::NotAllowed {
Err(WhiteListError::NotAllowed(instr.mnemonic.clone()))?
}
}

Ok(())
}
}

/// how strong allowed the object is
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AllowmentOption {
Allowed,
NotAllowed,
Unknown,
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum WhiteListError {
NotAllowed(MachineMnemonic)
}

impl Display for WhiteListError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match self {
WhiteListError::NotAllowed(mne) => format!("the instruction {} is not allowed but was suppyled", mne),
})
}
}

impl Error for WhiteListError {}
2 changes: 1 addition & 1 deletion src/Target/x64/asm/instr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fmt::Display, ops::{Add, Sub}, str::FromStr};

use crate::{CodeGen::MCInstr, Obj::Link, Support::{ColorClass, ColorProfile}, Target::{isa::{buildOpcode, MandatoryPrefix, RexPrefix}, x64Reg}};
use crate::{CodeGen::MCInstr, Obj::Link, Support::{ColorClass, ColorProfile}, Target::{x64::isa::{buildOpcode, MandatoryPrefix, RexPrefix}, x64Reg}};

use super::isa::ModRm;

Expand Down
2 changes: 1 addition & 1 deletion src/Target/x64/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ mod optimizer;

pub use lexer::*;
pub use parser::*;
pub use optimizer::*;
//pub(crate) use optimizer::*;
8 changes: 1 addition & 7 deletions src/Target/x64/asm/optimizer.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
use crate::Target::x64Reg;
use crate::{Optimizations::Optimize, Target::x64Reg};

use super::instr::{X64MCInstr, Mnemonic, Operand};

/// used for optimizing
pub trait Optimize<T> {
/// optimizes self
fn optimize(&mut self) -> Self;
}

impl Optimize<X64MCInstr> for Vec<X64MCInstr> {
fn optimize(&mut self) -> Vec<X64MCInstr> {
let mut out: Vec<X64MCInstr> = vec![];
Expand Down
25 changes: 23 additions & 2 deletions src/Target/x64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::collections::VecDeque;
mod compilation;
//use compilation::*;

use super::{CallConv, Lexer, TargetBackendDescr};
use super::{CallConv, Lexer, TargetBackendDescr, WhiteList};
mod reg;
use compilation::construct_compilation_helper;
pub use reg::*;
Expand All @@ -16,7 +16,7 @@ mod lower;

pub use asm::*;

use crate::Target::Compiler;
use crate::{CodeGen::MachineMnemonic, Target::Compiler};

/// Initializes the x86-64 target
pub fn initializeX64Target(call_conv: CallConv) -> TargetBackendDescr {
Expand All @@ -27,10 +27,31 @@ pub fn initializeX64Target(call_conv: CallConv) -> TargetBackendDescr {
target.lexer = Some(x64Lexer {}.boxed());
target.compile = Some(x64Parser { tokens: VecDeque::new(), out: None }.boxed());

target.whitelist = construct_whitelist();

target.helper = Some(construct_compilation_helper(call_conv));

target.call = call_conv;


target
}

fn construct_whitelist() -> WhiteList {
let mut whitelist = WhiteList::new();

whitelist.allow(MachineMnemonic::Move);
whitelist.allow(MachineMnemonic::Add);
whitelist.allow(MachineMnemonic::And);
whitelist.allow(MachineMnemonic::Div);
whitelist.allow(MachineMnemonic::Mul);
whitelist.allow(MachineMnemonic::Or);
whitelist.allow(MachineMnemonic::Sub);
whitelist.allow(MachineMnemonic::Xor);
whitelist.allow(MachineMnemonic::Return);

//whitelist.allow(MachineMnemonic::Zext); todo!()
//whitelist.allow(MachineMnemonic::Downcast); todo!()

whitelist
}
2 changes: 1 addition & 1 deletion tests/x64_instruction_encoding.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ygen::{Optimizations::auto_max_optimize, Target::{instr::*, x64Reg}};
use ygen::{Optimizations::auto_max_optimize, Target::{x64::instr::*, x64Reg}};

#[test]
pub fn test_mov() {
Expand Down

0 comments on commit 6d8e5e6

Please sign in to comment.