Skip to content

Commit

Permalink
[X64] added differnt register usage for different variable types (fix…
Browse files Browse the repository at this point in the history
…ed bug from previus commit)
  • Loading branch information
Cr0a3 committed Jul 14, 2024
1 parent 0b00ea0 commit 221f850
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 100 deletions.
16 changes: 8 additions & 8 deletions src/IR/ir.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{any::Any, fmt::Debug, hash::Hash};
use super::{FunctionType, IRBuilder, Type, TypeMetadata, Var, VerifyError};
use crate::Target::TargetRegistry;
use crate::Target::TargetBackendDescr;

macro_rules! IrTypeWith3 {
($name:tt, $param1:tt, $param2:tt, $param3:tt) => {
Expand Down Expand Up @@ -120,7 +120,7 @@ impl Ir for Return<Type> {
self
}

fn compile(&self, registry: &mut TargetRegistry) -> Vec<String> {
fn compile(&self, registry: &mut TargetBackendDescr) -> Vec<String> {
registry.getCompileFuncRetType()(self, registry)
}
}
Expand Down Expand Up @@ -156,8 +156,8 @@ impl Ir for Return<Var> {
self
}

fn compile(&self, registry: &mut TargetRegistry) -> Vec<String> {
registry.getCompileFuncRetVar()(self, registry)
fn compile(&self, registry: &mut TargetBackendDescr) -> Vec<String> {
registry.getCompileFuncForRetVar()(self, registry)
}
}

Expand Down Expand Up @@ -206,7 +206,7 @@ impl Ir for Add<Type, Type, Var> {
self
}

fn compile(&self, registry: &mut TargetRegistry) -> Vec<String> {
fn compile(&self, registry: &mut TargetBackendDescr) -> Vec<String> {
registry.getCompileFuncForAddTypeType()(self, registry)
}
}
Expand Down Expand Up @@ -256,7 +256,7 @@ impl Ir for Add<Var, Var, Var> {
self
}

fn compile(&self, registry: &mut TargetRegistry) -> Vec<String> {
fn compile(&self, registry: &mut TargetBackendDescr) -> Vec<String> {
registry.getCompileFuncForAddVarVar()(self, registry)
}
}
Expand Down Expand Up @@ -298,7 +298,7 @@ impl Ir for ConstAssign<Var, Type> {
Box::new(self.clone())
}

fn compile(&self, registry: &mut TargetRegistry) -> Vec<String> {
fn compile(&self, registry: &mut TargetBackendDescr) -> Vec<String> {
registry.getCompileFuncForConstAssign()(self, registry)
}
}
Expand Down Expand Up @@ -382,7 +382,7 @@ pub(crate) trait Ir: Debug + Any {
fn clone_box(&self) -> Box<dyn Ir>;

/// Compiles the node based on the initialized TARGETS.lock().unwrap().lock().unwrap()
fn compile(&self, registry: &mut TargetRegistry) -> Vec<String>;
fn compile(&self, registry: &mut TargetBackendDescr) -> Vec<String>;
}

impl Clone for Box<dyn Ir> {
Expand Down
1 change: 1 addition & 0 deletions src/Target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod registry;
mod x64;
pub use x64::initializeX64Target;
pub use triple::Triple;
pub use registry::TargetBackendDescr;
pub use registry::TargetRegistry;

/// Target architecture
Expand Down
179 changes: 108 additions & 71 deletions src/Target/registry.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,71 @@
use std::{collections::{HashMap, VecDeque}, fmt::Display};

use crate::prelude::{ir::*, Type, Var};
use crate::prelude::{ir::*, Type, TypeMetadata, Var};

use super::{Arch, CallConv};

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct BackendInfos {
pub(crate) varsStorage: HashMap<Var, VarStorage>,
pub(crate) currStackOffsetForLocalVars: isize,
pub(crate) openUsableRegisters: VecDeque<String>,
pub(crate) openUsableRegisters64: VecDeque<String>,
pub(crate) openUsableRegisters32: VecDeque<String>,
pub(crate) openUsableRegisters16: VecDeque<String>,
pub(crate) openUsableRegisters8: VecDeque<String>,
}

impl BackendInfos {
pub(crate) fn new() -> Self {
Self {
varsStorage: HashMap::new(),
currStackOffsetForLocalVars: 0,
openUsableRegisters: VecDeque::new(),
openUsableRegisters64: VecDeque::new(),
openUsableRegisters32: VecDeque::new(),
openUsableRegisters16: VecDeque::new(),
openUsableRegisters8: VecDeque::new(),
}
}

pub(crate) fn insertVar(&mut self, var: Var, store: VarStorage) {
self.varsStorage.insert(var, store);
}

pub(crate) fn getOpenReg(&mut self) -> Option<String> {
self.openUsableRegisters.pop_front()
pub(crate) fn getOpenReg64(&mut self) -> Option<String> {
self.openUsableRegisters32.pop_front(); // update all other members
self.openUsableRegisters16.pop_front();
self.openUsableRegisters8.pop_front();
self.openUsableRegisters64.pop_front()
}

pub(crate) fn getOpenReg32(&mut self) -> Option<String> {
self.openUsableRegisters64.pop_front(); // update all other members
self.openUsableRegisters16.pop_front();
self.openUsableRegisters8.pop_front();
self.openUsableRegisters32.pop_front()
}

pub(crate) fn getOpenReg16(&mut self) -> Option<String> {
self.openUsableRegisters64.pop_front(); // update all other members
self.openUsableRegisters32.pop_front();
self.openUsableRegisters8.pop_front();
self.openUsableRegisters16.pop_front()
}

#[allow(dead_code)]
pub(crate) fn getOpenReg8(&mut self) -> Option<String> {
self.openUsableRegisters64.pop_front(); // update all other members
self.openUsableRegisters32.pop_front();
self.openUsableRegisters16.pop_front();
self.openUsableRegisters8.pop_front()
}

pub(crate) fn getOpenRegBasedOnTy(&mut self, ty: TypeMetadata) -> Option<String> {
match ty {
TypeMetadata::u16 | TypeMetadata::i16 => self.getOpenReg16(),
TypeMetadata::u32 | TypeMetadata::i32 => self.getOpenReg32(),
TypeMetadata::u64 | TypeMetadata::i64 => self.getOpenReg64(),
TypeMetadata::Void => todo!("cannot use void as a register variable type. consider removing it"),
}
}
}

Expand All @@ -45,120 +85,117 @@ impl Display for VarStorage {
}
}

pub(crate) type CompileFunc<T> = fn(&T, &mut TargetRegistry) -> Vec<String>;
pub(crate) type CompileFunc<T> = fn(&T, &mut TargetBackendDescr) -> Vec<String>;

/// The Target Registry: stores if a target was already initialized
/// The TargetBackendDescr is used to store all the functions/information to compile ir nodes into assembly
#[derive(Debug, Clone)]
pub struct TargetRegistry {
pub(crate) inited_targets: Vec<Arch>,
funcForRetType: HashMap<Arch, CompileFunc<Return<Type>>>,
funcForRetVar: HashMap<Arch, CompileFunc<Return<Var>>>,
funcForConstAssign: HashMap<Arch, CompileFunc<ConstAssign<Var, Type>>>,
funcForAddVarVar: HashMap<Arch, CompileFunc<Add<Var, Var, Var>>>,
funcForAddTypeType: HashMap<Arch, CompileFunc<Add<Type, Type, Var>>>,
pub struct TargetBackendDescr {
funcForRetType: Option<CompileFunc<Return<Type>>>,
funcForRetVar: Option<CompileFunc<Return<Var>>>,
funcForConstAssign: Option<CompileFunc<ConstAssign<Var, Type>>>,
funcForAddVarVar: Option<CompileFunc<Add<Var, Var, Var>>>,
funcForAddTypeType: Option<CompileFunc<Add<Type, Type, Var>>>,
pub(crate) backend: BackendInfos,
pub(crate) call: CallConv,
}

impl TargetRegistry {
impl TargetBackendDescr {
/// Creates a new instance
pub fn new() -> Self {
Self {
inited_targets: vec![],
funcForRetType: HashMap::new(),
funcForRetVar: HashMap::new(),
funcForConstAssign: HashMap::new(),
funcForAddVarVar: HashMap::new(),
funcForAddTypeType: HashMap::new(),
funcForRetType: None,
funcForRetVar: None,
funcForConstAssign: None,
funcForAddVarVar: None,
funcForAddTypeType: None,

call: CallConv::SystemV,
backend: BackendInfos::new(),
}
}

/// sets the callback for compiling the return ir node into asm
pub(crate) fn setCompileFuncForRetType(&mut self, arch: Arch, callback: CompileFunc<Return<Type>>) {
if !self.funcForRetType.contains_key(&arch) {
self.funcForRetType.insert(arch, callback);
}
pub(crate) fn setCompileFuncForRetType(&mut self, callback: CompileFunc<Return<Type>>) {
self.funcForRetType = Some(callback);
}

/// gets the callback for compiling the return ir node into asm
pub(crate) fn getCompileFuncRetType(&self) -> CompileFunc<Return<Type>> {
if let Some(last_arch) = self.inited_targets.last() {
if let Some(func) = self.funcForRetType.get(last_arch) {
*func
} else { todo!() }
} else { todo!()}
if let Some(func) = self.funcForRetType {
func
} else { todo!("an corresponding assembly handler needs to be registered in order to compile an ReturnType ir node")}
}

/// sets the callback for compiling the return ir node into asm
pub(crate) fn setCompileFuncForRetVar(&mut self, arch: Arch, callback: CompileFunc<Return<Var>>) {
if !self.funcForRetVar.contains_key(&arch) {
self.funcForRetVar.insert(arch, callback);
}
pub(crate) fn setCompileFuncForRetVar(&mut self, callback: CompileFunc<Return<Var>>) {
self.funcForRetVar = Some(callback)
}

/// gets the callback for compiling the return ir node into asm
pub(crate) fn getCompileFuncRetVar(&self) -> CompileFunc<Return<Var>> {
if let Some(last_arch) = self.inited_targets.last() {
if let Some(func) = self.funcForRetVar.get(last_arch) {
*func
} else { todo!() }
} else { todo!()}
pub(crate) fn getCompileFuncForRetVar(&self) -> CompileFunc<Return<Var>> {
if let Some(func) = self.funcForRetVar {
func
} else { todo!("an corresponding assembly handler needs to be registered in order to compile an ReturnVar ir node")}
}

/// sets the callback for compiling the const assign node into asm
pub(crate) fn setCompileFuncForConstAssign(&mut self, arch: Arch, callback: CompileFunc<ConstAssign<Var, Type>>) {
if !self.funcForConstAssign.contains_key(&arch) {
self.funcForConstAssign.insert(arch, callback);
}
pub(crate) fn setCompileFuncForConstAssign(&mut self, callback: CompileFunc<ConstAssign<Var, Type>>) {
self.funcForConstAssign = Some(callback);
}

/// gets the callback for compiling the const assign into asm
pub(crate) fn getCompileFuncForConstAssign(&self) -> CompileFunc<ConstAssign<Var, Type>> {
if let Some(last_arch) = self.inited_targets.last() {
if let Some(func) = self.funcForConstAssign.get(last_arch) {
*func
} else { todo!() }
} else { todo!()}
if let Some(func) = self.funcForConstAssign {
func
} else { todo!("an corresponding assembly handler needs to be registered in order to compile an ConstAssign ir node")}
}

/// sets the callback for compiling the add var var ir node into asm
pub(crate) fn setCompileFuncForAddVarVar(&mut self, arch: Arch, callback: CompileFunc<Add<Var, Var, Var>>) {
if !self.funcForAddVarVar.contains_key(&arch) {
self.funcForAddVarVar.insert(arch, callback);
}
pub(crate) fn setCompileFuncForAddVarVar(&mut self, callback: CompileFunc<Add<Var, Var, Var>>) {
self.funcForAddVarVar = Some(callback);
}

/// gets the callback for compiling the add var var node into into asm
pub(crate) fn getCompileFuncForAddVarVar(&self) -> CompileFunc<Add<Var, Var, Var>> {
if let Some(last_arch) = self.inited_targets.last() {
if let Some(func) = self.funcForAddVarVar.get(last_arch) {
*func
} else { todo!() }
} else { todo!()}
if let Some(func) = self.funcForAddVarVar {
func
} else { todo!("an corresponding assembly handler needs to be registered in order to compile an AddVarVar ir node")}
}

/// sets the callback for compiling the add var var ir node into asm
pub(crate) fn setCompileFuncForAddTypeType(&mut self, arch: Arch, callback: CompileFunc<Add<Type, Type, Var>>) {
if !self.funcForAddTypeType.contains_key(&arch) {
self.funcForAddTypeType.insert(arch, callback);
}
pub(crate) fn setCompileFuncForAddTypeType(&mut self, callback: CompileFunc<Add<Type, Type, Var>>) {
self.funcForAddTypeType = Some(callback);
}

/// gets the callback for compiling the add var var node into into asm
pub(crate) fn getCompileFuncForAddTypeType(&self) -> CompileFunc<Add<Type, Type, Var>> {
if let Some(last_arch) = self.inited_targets.last() {
if let Some(func) = self.funcForAddTypeType.get(last_arch) {
*func
} else { todo!() }
} else { todo!()}
if let Some(func) = self.funcForAddTypeType {
func
} else { todo!("an corresponding assembly handler needs to be registered in order to compile an AddTypeType ir node")}
}
}

/// The target registry: is just a big HashMap of `Arch` and `TargetBackendDescr`
#[derive(Debug, Clone)]
pub struct TargetRegistry {
map: HashMap<Arch, TargetBackendDescr>
}

/// Sets an architecture as initialized
pub fn set_inited(&mut self, arch: Arch) {
if !self.inited_targets.contains(&arch) {
self.inited_targets.push(arch);
impl TargetRegistry {
/// Creates an new target registry
pub fn new() -> Self {
Self {
map: HashMap::new(),
}
}

#[allow(dead_code)]
pub(crate) fn setInited(&mut self, arch: Arch, descr: TargetBackendDescr) {
self.map.insert(arch, descr);
}

#[allow(dead_code)]
pub(crate) fn getDescr(&mut self, arch: Arch) -> Option<&TargetBackendDescr> {
self.map.get(&arch)
}
}
Loading

0 comments on commit 221f850

Please sign in to comment.