Skip to content

Commit

Permalink
[X64] adding support to the return intstruction into the asm generati…
Browse files Browse the repository at this point in the history
…on backend
  • Loading branch information
Cr0a3 committed Jul 13, 2024
1 parent 1381f4e commit adebb6b
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 84 deletions.
7 changes: 5 additions & 2 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::error::Error;
use Ygen::{prelude::*, PassManager::Passes::PreComputeValue, Target::{initializeX64Target, CallConv}};
use Ygen::{prelude::*, Target::{initializeX64Target, CallConv}};

pub fn main() -> Result<(), Box<dyn Error>> {

Expand All @@ -17,11 +17,14 @@ pub fn main() -> Result<(), Box<dyn Error>> {
let entry = func.addBlock("entry");
builder.positionAtEnd(entry);

let val = builder.BuildAdd(ty.arg(0), ty.arg(1));
//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( ret );

builder.BuildRet( Type::i32(5) );

let block = builder.getLastBlock().clone().unwrap().clone();
let func = func.clone().to_owned().clone();

Expand Down
24 changes: 24 additions & 0 deletions src/IR/ir.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{any::Any, fmt::Debug, hash::Hash};
use super::{FunctionType, IRBuilder, Type, TypeMetadata, Var, VerifyError};
use crate::Target::TARGETS;

macro_rules! IrTypeWith3 {
($name:tt, $param1:tt, $param2:tt, $param3:tt) => {
Expand Down Expand Up @@ -118,6 +119,10 @@ impl Ir for Return<Type> {
fn as_any(&self) -> &dyn Any {
self
}

fn compile(&self) -> Vec<String> {
TARGETS.get().unwrap().lock().unwrap().getCompileFuncRetType()(self)
}
}

impl Ir for Return<Var> {
Expand Down Expand Up @@ -150,6 +155,10 @@ impl Ir for Return<Var> {
fn as_any(&self) -> &dyn Any {
self
}

fn compile(&self) -> Vec<String> {
TARGETS.get().unwrap().lock().unwrap().getCompileFuncRetVar()(self)
}
}

impl Ir for Add<Type, Type, Var> {
Expand Down Expand Up @@ -196,6 +205,10 @@ impl Ir for Add<Type, Type, Var> {
fn as_any(&self) -> &dyn Any {
self
}

fn compile(&self) -> Vec<String> {
TARGETS.get().unwrap().lock().unwrap().getCompileFuncAddTypeType()(self)
}
}

impl Ir for Add<Var, Var, Var> {
Expand Down Expand Up @@ -242,6 +255,10 @@ impl Ir for Add<Var, Var, Var> {
fn as_any(&self) -> &dyn Any {
self
}

fn compile(&self) -> Vec<String> {
TARGETS.get().unwrap().lock().unwrap().getCompileFuncAddVarVar()(self)
}
}

impl Ir for ConstAssign<Var, Type> {
Expand Down Expand Up @@ -280,6 +297,10 @@ impl Ir for ConstAssign<Var, Type> {
fn clone_box(&self) -> Box<dyn Ir> {
Box::new(self.clone())
}

fn compile(&self) -> Vec<String> {
TARGETS.get().unwrap().lock().unwrap().getCompileFuncConstAssign()(self)
}
}

/// Trait for the return instruction
Expand Down Expand Up @@ -359,6 +380,9 @@ pub(crate) trait Ir: Debug + Any {

/// Clones the node into a box of `Box<dyn Ir>`
fn clone_box(&self) -> Box<dyn Ir>;

/// Compiles the node based on the initialized TARGETS.get().unwrap().lock().unwrap()
fn compile(&self) -> Vec<String>;
}

impl Clone for Box<dyn Ir> {
Expand Down
13 changes: 7 additions & 6 deletions src/Target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ mod triple;
mod registry;
mod x64;
pub use x64::initializeX64Target;
pub(crate) use registry::TARGETS;
pub use triple::Triple;
pub use registry::TargetRegistry;

/// Target architecture
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Arch {
/// Unknown Architecture
Unknown,
Expand Down Expand Up @@ -111,7 +112,7 @@ pub enum Arch {
}

/// Target calling convention
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CallConv {
/// Windows standart
WindowsFastCall,
Expand All @@ -120,7 +121,7 @@ pub enum CallConv {
}

/// Vendor
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Vendor {
/// Unknown Vendor
Unknown,
Expand Down Expand Up @@ -157,7 +158,7 @@ pub enum Vendor {
}

/// Target OS
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OS {
/// Unknown OS
Unknown,
Expand Down Expand Up @@ -232,7 +233,7 @@ pub enum OS {
}

/// Target environment
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Environment {
/// Unknown environment
Unknown,
Expand Down Expand Up @@ -275,7 +276,7 @@ pub enum Environment {
}

/// Target object format
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ObjFormat {
/// Unknown
Unknown,
Expand Down
70 changes: 67 additions & 3 deletions src/Target/registry.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
use std::sync::Mutex;
use std::{collections::HashMap, sync::Mutex};

use once_cell::sync::OnceCell;

use super::Arch;
use crate::prelude::{Return, Type, Var};

use super::{Arch, CallConv};

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct BackendInfos {
pub(crate) varsStorage: HashMap<Var, VarStorage>,
}

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


/// The Target Registry: stores if a target was already initialized
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum VarStorage {
Register(String),
Memory(String),
}
pub(crate) type CompileFunc<T> = fn(&T/*, &mut BackendInfos*/) -> Vec<String>;

/// The Target Registry: stores if a target was already initialized
#[derive(Debug, Clone)]
pub struct TargetRegistry {
pub(crate) inited_targets: Vec<Arch>,
funcForRetType: HashMap<Arch, CompileFunc<Return<Type>>>,
funcForRetVar: HashMap<Arch, CompileFunc<Return<Var>>>,
pub(crate) backend: BackendInfos,
pub(crate) call: CallConv,
}

pub(crate) static TARGETS: OnceCell<Mutex<TargetRegistry>> = OnceCell::new();
Expand All @@ -17,9 +42,48 @@ impl TargetRegistry {
pub fn new() -> Self {
Self {
inited_targets: vec![],
funcForRetType: HashMap::new(),
funcForRetVar: HashMap::new(),
call: CallConv::SystemV,
backend: BackendInfos { varsStorage: HashMap::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);
}
}

/// 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!()}
}



/// 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);
}
}

/// 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!()}
}


/// Sets an architecture as initialized
pub fn set_inited(&mut self, arch: Arch) {
if !self.inited_targets.contains(&arch) {
Expand Down
24 changes: 24 additions & 0 deletions src/Target/x64/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,28 @@ impl CallConv {
CallConv::WindowsFastCall => vec!["rdx".into(), "rcx".into(), "r8".into(), "r9".into()],
}
}

/// Returns the return register
pub fn ret16(&self) -> String {
match self {
CallConv::WindowsFastCall => "ax".into(),
CallConv::SystemV => "ax".into(),
}
}

/// Returns the return register
pub fn ret32(&self) -> String {
match self {
CallConv::WindowsFastCall => "eax".into(),
CallConv::SystemV => "eax".into(),
}
}

/// Returns the return register
pub fn ret64(&self) -> String {
match self {
CallConv::WindowsFastCall => "rax".into(),
CallConv::SystemV => "rax".into(),
}
}
}
Loading

0 comments on commit adebb6b

Please sign in to comment.