CodeGenLib/x86/
function.rs

1use super::asm::REGISTER;
2use crate::arch::AsmCall::AsmCall as asm;
3use crate::arch::ext::AMD64::*;
4use super::mem::AdressManager;
5use super::var::{Variabel, VarDataType};
6
7/// The Function class is a handler for the code generation of one function
8#[derive(Clone)]   
9pub struct Function {
10    pub name: String,
11    pub gen: Vec<Vec<u8>>,
12    pos: usize,
13
14    pub esymbols: Vec<ExternSymbol>,
15    pub vars: Vec<Variabel>,
16
17    adrmng: AdressManager,
18}
19
20impl Function {
21    pub fn new(name: &str, adrmng: &mut AdressManager) -> Function {
22        let mut gen = vec![];
23        gen.push( asm::endbr64() );
24        gen.push( asm::push(REGISTER::RBP) );
25        gen.push( asm::mov_reg(REGISTER::RBP, REGISTER::RSP) );
26
27        Function {
28            gen: gen.clone(),
29            name: String::from(name),
30            pos: gen.len() - 1,
31            esymbols: vec![],
32            vars: vec![],
33            adrmng: adrmng.to_owned(),
34        }
35    }
36
37    /// Adds a return
38    pub fn asm_ret(&mut self) -> &mut Self {
39        self.gen.push( asm::nop() );
40        self.gen.push( asm::pop(REGISTER::RBP) );
41        self.gen.push( asm::ret() );
42
43        self
44    }
45
46    /// Adds a assembly mov command
47    pub fn asm_mov(&mut self, reg: REGISTER, value: u64) -> &mut Self {
48        if  reg == REGISTER::RAX || reg == REGISTER::RBX || reg == REGISTER::RCX || reg == REGISTER::RDX || 
49            reg == REGISTER::RBP || reg == REGISTER::RDI || reg == REGISTER::RIP || reg == REGISTER::RSI || 
50            reg == REGISTER::RSP {
51            self.gen.push( asm::mov_64(reg, value) );
52        } else if reg == REGISTER::EAX || reg == REGISTER::EBX || reg == REGISTER::ECX || reg == REGISTER::EDX {   // 32bit Register
53            self.gen.push( asm::mov_32(reg, value as u32) );
54        } else if reg == REGISTER::AX || reg == REGISTER::BX || reg == REGISTER::DX {
55            self.gen.push( asm::mov_16(reg, value as u16) );
56        } else {
57            self.gen.push( asm::mov_8(reg, value as u8) );
58        }
59
60        self
61    }
62
63    /// Adds a assembly mov from register to register command
64    pub fn asm_mov_reg(&mut self, from: REGISTER, to: REGISTER) -> &mut Self {
65        self.gen.push( asm::mov_reg(from, to) );
66
67        self
68    }
69
70    /// Adds a assembly adc command
71    pub fn asm_adc(&mut self, reg: REGISTER, value: u64) -> &mut Self {
72        if  reg == REGISTER::RAX || reg == REGISTER::RBX || reg == REGISTER::RCX || reg == REGISTER::RDX || 
73            reg == REGISTER::RBP || reg == REGISTER::RDI || reg == REGISTER::RIP || reg == REGISTER::RSI || 
74            reg == REGISTER::RSP {
75            self.gen.push( asm::adc_64(reg, value) );
76        } else if reg == REGISTER::EAX || reg == REGISTER::EBX || reg == REGISTER::ECX || reg == REGISTER::EDX {   // 32bit Register
77            self.gen.push( asm::adc_32(reg, value as u32) );
78        } else if reg == REGISTER::AX || reg == REGISTER::BX || reg == REGISTER::DX {
79            self.gen.push( asm::adc_16(reg, value as u16) );
80        } else {
81            self.gen.push( asm::adc_8(reg, value as u8) );
82        }
83
84        self
85    }
86
87    /// Adds a assembly adc command which adds the registers together
88    pub fn asm_adc_reg(&mut self, dest: REGISTER, src: REGISTER) -> &mut Self {
89        self.gen.push( asm::adc_reg(dest, src) );
90
91        self
92    }
93
94    /// Returns an intenger
95    pub fn ret_int(&mut self, value: u64) -> &mut Self {
96        if value > 0xffffffff {
97            self.asm_mov(REGISTER::RAX, value);
98        } else {
99            self.asm_mov(REGISTER::EAX, value);
100        }
101        self.asm_ret();
102
103        self
104    }
105
106    /// Adds an call to the adress
107    pub fn asm_call(&mut self, adr: u32) -> &mut Self {
108        self.gen.push( asm::call(adr) );
109
110        self
111    }
112
113    /// Calls a function with the name of `dest`
114    pub fn call(&mut self, dest: &str) -> &mut Self {
115        self.esymbols.push(
116            ExternSymbol {
117                start: self.name.clone(),
118                dest: dest.into(),
119                at: self.pos + 1,
120            }
121        );
122
123        self.asm_call(0);
124
125        self
126    }
127
128    /// Adds a variable to the function
129    pub fn create_var(&mut self, name: & str, typ: VarDataType) -> Variabel {
130        let var = Variabel::new(typ, &name.to_string(), &self.adrmng);
131        self.vars.push(var);
132
133       self.get_last_var()
134    }
135
136    fn get_last_var(&mut self) -> Variabel {
137        let list = self.vars.clone();
138        self.vars.get_mut(list.len() -1)
139            .expect("error while getting last function (CodeGenLib/x86/function.rs/121").to_owned()
140    }
141
142    /// Returns the generated code of the function
143    pub fn get_gen(&mut self) -> Vec<u8> {
144        let mut out: Vec<u8> = vec![];
145        for v in self.gen.iter() {
146            for b in v {
147                out.push(*b);
148            }
149        }
150
151        out
152    }
153}
154
155/// A struct for storing extern functions
156#[derive(Clone)]
157pub struct ExternFunction {
158    pub name: String,
159}
160
161/// A struct for storing extern symbols
162#[derive(Clone)]
163pub struct ExternSymbol {
164    pub start: String,
165    pub dest: String,
166    pub at: usize,
167}