use super::asm::REGISTER;
use crate::arch::AsmCall::AsmCall as asm;
use crate::arch::ext::AMD64::*;
use super::mem::AdressManager;
use super::var::{Variabel, VarDataType};
#[derive(Clone)]
pub struct Function {
pub name: String,
pub gen: Vec<Vec<u8>>,
pos: usize,
pub esymbols: Vec<ExternSymbol>,
pub vars: Vec<Variabel>,
adrmng: AdressManager,
}
impl Function {
pub fn new(name: &str, adrmng: &mut AdressManager) -> Function {
let mut gen = vec![];
gen.push( asm::endbr64() );
gen.push( asm::push(REGISTER::RBP) );
gen.push( asm::mov_reg(REGISTER::RBP, REGISTER::RSP) );
Function {
gen: gen.clone(),
name: String::from(name),
pos: gen.len() - 1,
esymbols: vec![],
vars: vec![],
adrmng: adrmng.to_owned(),
}
}
pub fn asm_ret(&mut self) -> &mut Self {
self.gen.push( asm::nop() );
self.gen.push( asm::pop(REGISTER::RBP) );
self.gen.push( asm::ret() );
self
}
pub fn asm_mov(&mut self, reg: REGISTER, value: u64) -> &mut Self {
if reg == REGISTER::RAX || reg == REGISTER::RBX || reg == REGISTER::RCX || reg == REGISTER::RDX ||
reg == REGISTER::RBP || reg == REGISTER::RDI || reg == REGISTER::RIP || reg == REGISTER::RSI ||
reg == REGISTER::RSP {
self.gen.push( asm::mov_64(reg, value) );
} else if reg == REGISTER::EAX || reg == REGISTER::EBX || reg == REGISTER::ECX || reg == REGISTER::EDX { self.gen.push( asm::mov_32(reg, value as u32) );
} else if reg == REGISTER::AX || reg == REGISTER::BX || reg == REGISTER::DX {
self.gen.push( asm::mov_16(reg, value as u16) );
} else {
self.gen.push( asm::mov_8(reg, value as u8) );
}
self
}
pub fn asm_mov_reg(&mut self, from: REGISTER, to: REGISTER) -> &mut Self {
self.gen.push( asm::mov_reg(from, to) );
self
}
pub fn asm_adc(&mut self, reg: REGISTER, value: u64) -> &mut Self {
if reg == REGISTER::RAX || reg == REGISTER::RBX || reg == REGISTER::RCX || reg == REGISTER::RDX ||
reg == REGISTER::RBP || reg == REGISTER::RDI || reg == REGISTER::RIP || reg == REGISTER::RSI ||
reg == REGISTER::RSP {
self.gen.push( asm::adc_64(reg, value) );
} else if reg == REGISTER::EAX || reg == REGISTER::EBX || reg == REGISTER::ECX || reg == REGISTER::EDX { self.gen.push( asm::adc_32(reg, value as u32) );
} else if reg == REGISTER::AX || reg == REGISTER::BX || reg == REGISTER::DX {
self.gen.push( asm::adc_16(reg, value as u16) );
} else {
self.gen.push( asm::adc_8(reg, value as u8) );
}
self
}
pub fn asm_adc_reg(&mut self, dest: REGISTER, src: REGISTER) -> &mut Self {
self.gen.push( asm::adc_reg(dest, src) );
self
}
pub fn ret_int(&mut self, value: u64) -> &mut Self {
if value > 0xffffffff {
self.asm_mov(REGISTER::RAX, value);
} else {
self.asm_mov(REGISTER::EAX, value);
}
self.asm_ret();
self
}
pub fn asm_call(&mut self, adr: u32) -> &mut Self {
self.gen.push( asm::call(adr) );
self
}
pub fn call(&mut self, dest: &str) -> &mut Self {
self.esymbols.push(
ExternSymbol {
start: self.name.clone(),
dest: dest.into(),
at: self.pos + 1,
}
);
self.asm_call(0);
self
}
pub fn create_var(&mut self, name: & str, typ: VarDataType) -> Variabel {
let var = Variabel::new(typ, &name.to_string(), &self.adrmng);
self.vars.push(var);
self.get_last_var()
}
fn get_last_var(&mut self) -> Variabel {
let list = self.vars.clone();
self.vars.get_mut(list.len() -1)
.expect("error while getting last function (CodeGenLib/x86/function.rs/121").to_owned()
}
pub fn get_gen(&mut self) -> Vec<u8> {
let mut out: Vec<u8> = vec![];
for v in self.gen.iter() {
for b in v {
out.push(*b);
}
}
out
}
}
#[derive(Clone)]
pub struct ExternFunction {
pub name: String,
}
#[derive(Clone)]
pub struct ExternSymbol {
pub start: String,
pub dest: String,
pub at: usize,
}