Skip to content

Commit

Permalink
[CODE GEN] adding more stuff (i forgot what)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Aug 29, 2024
1 parent ea3484f commit 72db96f
Show file tree
Hide file tree
Showing 20 changed files with 300 additions and 214 deletions.
43 changes: 39 additions & 4 deletions src/CodeGen/calling_convention.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,64 @@
use crate::Target::{x64Reg, Arch, CallConv};
use crate::{Target::{x64Reg, Arch, CallConv}, IR::TypeMetadata};

use super::Reg;

/// A more machine specifc calling convention
/// (Just a wrapper around the normal calling convention but with some pretty handy functions)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MachineCallingConvention {
pub(crate) call_conv: CallConv,
}

impl MachineCallingConvention {
pub fn return_reg(&self, arch: Arch) -> Reg {
/// returns the return register for the specific architecture and ty
pub fn return_reg(&self, arch: Arch, ty: TypeMetadata) -> Reg {
match self.call_conv {
CallConv::WindowsFastCall => {
match arch {
Arch::X86_64 => Reg::x64(x64Reg::Rax),
Arch::X86_64 => Reg::x64(x64Reg::Rax.sub_ty(ty)),
_ => todo!()
}
},
CallConv::SystemV => {
match arch {
Arch::X86_64 => Reg::x64(x64Reg::Rax),
Arch::X86_64 => Reg::x64(x64Reg::Rax.sub_ty(ty)),
_ => todo!()
}
},
CallConv::AppleAarch64 => todo!(),
CallConv::WasmBasicCAbi => todo!(),
}
}

/// returns the args for the specifc architecture
pub fn args(&self, arch: Arch) -> Vec<Reg> {
match self.call_conv {
CallConv::WindowsFastCall => {
match arch {
Arch::X86_64 => vec![
Reg::x64(x64Reg::Rcx), Reg::x64(x64Reg::Rdx),
Reg::x64(x64Reg::R8), Reg::x64(x64Reg::R9)
],
_ => todo!()
}
},
CallConv::SystemV => {
match arch {
Arch::X86_64 => vec![
Reg::x64(x64Reg::Rsi), Reg::x64(x64Reg::Rdi),
Reg::x64(x64Reg::Rcx), Reg::x64(x64Reg::Rdx),
Reg::x64(x64Reg::R8), Reg::x64(x64Reg::R9)
],
_ => todo!()
}
},
CallConv::AppleAarch64 => todo!(),
CallConv::WasmBasicCAbi => todo!(),
}
}

/// returns how many arguments are stored in registers
pub fn num_reg_args(&self, arch: Arch) -> usize {
self.args(arch).len()
}
}
21 changes: 21 additions & 0 deletions src/CodeGen/compilation/assign.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::prelude::ConstAssign;
use crate::IR::{Block, Const, Type, Var};
use super::CompilationHelper;
use crate::CodeGen::MachineInstr;

impl CompilationHelper {
#[allow(missing_docs)]
pub fn compile_assign_var_type(&mut self, node: &ConstAssign<Var, Type>, mc_sink: &mut Vec<MachineInstr>, block: &Block) {
todo!()
}

#[allow(missing_docs)]
pub fn compile_assign_var_var(&mut self, node: &ConstAssign<Var, Var>, mc_sink: &mut Vec<MachineInstr>, block: &Block) {
todo!()
}

#[allow(missing_docs)]
pub fn compile_assign_var_const(&mut self, node: &ConstAssign<Var, Const>, mc_sink: &mut Vec<MachineInstr>, block: &Block) {
todo!()
}
}
11 changes: 11 additions & 0 deletions src/CodeGen/compilation/call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use crate::prelude::Call;
use crate::IR::{Block, Function, Var};
use super::CompilationHelper;
use crate::CodeGen::MachineInstr;

impl CompilationHelper {
#[allow(missing_docs)]
pub fn compile_call(&mut self, node: &Call<Function, Vec<Var>, Var>, mc_sink: &mut Vec<MachineInstr>, block: &Block) {
todo!()
}
}
10 changes: 10 additions & 0 deletions src/CodeGen/compilation/cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::prelude::Cast;
use crate::IR::{Block, TypeMetadata, Var};
use super::CompilationHelper;
use crate::CodeGen::MachineInstr;

impl CompilationHelper {
pub fn compile_cast(&mut self, node: &Cast<Var, TypeMetadata, Var>, mc_sink: &mut Vec<MachineInstr>, block: &Block) {
todo!()
}
}
2 changes: 1 addition & 1 deletion src/CodeGen/compilation/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ macro_rules! MathVarType {
($func:ident, $node:ident, $mnemonic:expr) => {
impl CompilationHelper {
#[allow(missing_docs)]
pub(crate) fn $func(&mut self, node: &$node<Var, Type, Var>, mc_sink: &mut Vec<MachineInstr>, block: &Block) {
pub fn $func(&mut self, node: &$node<Var, Type, Var>, mc_sink: &mut Vec<MachineInstr>, block: &Block) {
let src1 = *self.vars.get(&node.inner1).expect("expected valid variable");

let boxed: Box<dyn Ir> = Box::new(node.clone());
Expand Down
29 changes: 27 additions & 2 deletions src/CodeGen/compilation/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use std::collections::HashMap;

use crate::{Target::Arch, IR::Var};
use crate::{Target::Arch, IR::{Function, Var}};

use super::{calling_convention::MachineCallingConvention, reg::Reg, reg_vec::RegVec, MCInstr, MachineInstr};

mod math;
mod cast;
mod call;
mod ret;
mod assign;

pub(crate) struct CompilationHelper {
/// helps with compilation
pub struct CompilationHelper {
pub(crate) regs: RegVec,
pub(crate) arch: Arch,
pub(crate) lower: Option<fn(Vec<MachineInstr>) -> Vec<Box<dyn MCInstr>>>,
Expand Down Expand Up @@ -49,6 +53,27 @@ impl CompilationHelper {

location
}

/// passes the arguments into the right register
pub(crate) fn build_argument_preprocessing(&mut self, func: &Function) {
let func = &func.ty;

for (num, ty) in &func.args {

let location = {
if let Some(reg) = self.call.args(self.arch).get(*num) {
VarLocation::Reg(*reg)
} else {
todo!("The new system currently doesn't support memory")
}
};

self.vars.insert(
Var { name: format!("%{}", num), ty: *ty },
location
);
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
9 changes: 7 additions & 2 deletions src/CodeGen/compilation/ret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ use crate::{prelude::Return, CodeGen::{MachineInstr, MachineMnemonic, MachineOpe
use super::CompilationHelper;

impl CompilationHelper {
#[allow(missing_docs)]
pub fn compile_ret_ty(&mut self, node: &Return<Type>, mc_sink: &mut Vec<MachineInstr>, _: &Block) {
let mut instr = MachineInstr::new(MachineMnemonic::Move);
instr.add_operand(MachineOperand::Reg(self.call.return_reg(self.arch)) );

instr.add_operand(MachineOperand::Reg(self.call.return_reg(self.arch, node.inner1.into())) );
instr.add_operand(MachineOperand::Imm(node.inner1.val() as i64));

mc_sink.push( MachineInstr::new(MachineMnemonic::Return) );
}

#[allow(missing_docs)]
pub fn compile_ret_var(&mut self, node: &Return<Var>, mc_sink: &mut Vec<MachineInstr>, _: &Block) {
let src = *self.vars.get(&node.inner1).expect("expected valid variable");

let mut instr = MachineInstr::new(MachineMnemonic::Move);
instr.add_operand(MachineOperand::Reg(self.call.return_reg(self.arch)) );

instr.add_operand(MachineOperand::Reg(self.call.return_reg(self.arch, node.inner1.ty)) );

match src {
super::VarLocation::Reg(reg) => instr.add_operand(MachineOperand::Reg(reg)),
Expand Down
4 changes: 3 additions & 1 deletion src/CodeGen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ pub(crate) mod calling_convention;
pub use reg_vec::*;
pub use reg::*;
pub use settings::*;
pub use instr::*;
pub use instr::*;
pub use calling_convention::*;
pub use compilation::*;
7 changes: 7 additions & 0 deletions src/CodeGen/reg_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ impl RegVec {
entry.pop()
} else { None }
}

/// reversees the registers of the arch
pub fn reverse(&mut self, arch: Arch) {
if let Some(entry) = self.regs.get_mut(&arch) {
entry.reverse();
}
}
}
2 changes: 1 addition & 1 deletion src/IR/nodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ macro_rules! IrTypeWith1 {
($name:tt, $param1:tt) => {
/// An Ir node
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct $name<$param1> {
pub struct $name<$param1> {
/// inner value
pub(crate) inner1: $param1,
}
Expand Down
2 changes: 0 additions & 2 deletions src/Target/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
mod triple;
mod target_descr;
mod x64;
mod reg;
mod registry;
pub use x64::*;
pub use reg::Reg;
pub use triple::Triple;
pub use target_descr::TargetBackendDescr;
pub use registry::TargetRegistry;
Expand Down
49 changes: 0 additions & 49 deletions src/Target/reg.rs

This file was deleted.

19 changes: 14 additions & 5 deletions src/Target/target_descr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use crate::CodeGen::{compilation::CompilationHelper, MachineInstr};
use crate::IR::{Const, Function, Type, TypeMetadata};

use super::Triple;
use super::{CallConv, Compiler, instr::Instr, Lexer};

pub(crate) type CompileFunc<T> = fn(&T, &mut TargetBackendDescr) -> Vec<Instr>;
use super::{CallConv, Compiler, Lexer};

/// The TargetBackendDescr is used to store all the functions/information to compile ir nodes into assembly
#[allow(unused)]
Expand Down Expand Up @@ -67,20 +65,31 @@ impl TargetBackendDescr {
self.compile.clone().unwrap()
}

/// builds all ir nodes of the current block into a vector of MachineInstr
pub fn build_instrs(&mut self, func: &Function, triple: &Triple) -> Vec<MachineInstr> {
let helper = if let Some(helper) = &mut self.helper { helper }
else { panic!("no current compilation helper"); };

if helper.arch != triple.arch {
panic!("the architecture of the triple {:?} isn't the same as the one of the compilation helper {:?}", triple.arch, helper.arch)
}

let block = if let Some(block) = &self.block {
block.clone()
} else {
todo!("no current block");
panic!("no current block");
};

helper.build_argument_preprocessing(func);

for node in block.nodes {
node.compile(&mut self);
node.compile(self);
}

self.sink.clone()
}

/// Used for lowering machine instructions into dyn MCInstr
pub fn lower(&self, instrs: Vec<MachineInstr>) -> Vec<Box<dyn MCInstr>> {
if let Some(helper) = &self.helper {
if let Some(lower) = helper.lower {
Expand Down
Loading

0 comments on commit 72db96f

Please sign in to comment.