diff --git a/src/codegen/codegen.rs b/src/codegen/codegen.rs index 4a94e01..dfa469d 100644 --- a/src/codegen/codegen.rs +++ b/src/codegen/codegen.rs @@ -1,3 +1,4 @@ +use super::{Register, RegisterAllocator}; use crate::{ parser::{ BinOp, Expr, ExprBinary, ExprLit, ExprUnary, IntLitRepr, Stmt, StmtVarDecl, Type, UnOp, @@ -7,23 +8,9 @@ use crate::{ use indoc::{formatdoc, writedoc}; use std::{fmt::Write, fs::File}; -struct Register<'a> { - name: &'a str, - in_use: bool, -} - -impl<'a> Register<'a> { - pub fn new(name: &'a str) -> Self { - Self { - name, - in_use: false, - } - } -} - pub struct CodeGen<'a> { symtable: SymbolTable, - registers: [Register<'a>; 6], + registers: RegisterAllocator<'a>, data_section: String, text_section: String, bss_section: String, @@ -33,14 +20,14 @@ impl<'a> CodeGen<'a> { pub fn new(symtable: SymbolTable) -> Self { Self { symtable, - registers: [ - Register::new("r8"), - Register::new("r9"), - Register::new("rdi"), - Register::new("rsi"), - Register::new("rdx"), - Register::new("rcx"), - ], + registers: RegisterAllocator::new(vec![ + Register::new("r8b", "r8"), + Register::new("r9b", "r9"), + Register::new("dil", "rdi"), + Register::new("sil", "rsi"), + Register::new("dl", "rdx"), + Register::new("cl", "rcx"), + ]), bss_section: "section .bss\n".to_string(), data_section: "section .data\n".to_string(), text_section: formatdoc!( @@ -54,22 +41,6 @@ impl<'a> CodeGen<'a> { } } - fn alloc(&mut self) -> usize { - for (i, r) in self.registers.iter_mut().enumerate() { - if !r.in_use { - r.in_use = true; - - return i; - } - } - - panic!("All registers were in use"); - } - - fn free(&mut self, r: usize) { - self.registers[r].in_use = false; - } - fn declare(&mut self, var: &StmtVarDecl) { let size = self.size(&var.type_); @@ -83,7 +54,7 @@ impl<'a> CodeGen<'a> { .unwrap(); } - fn expr(&mut self, expr: &Expr) -> usize { + fn expr(&mut self, expr: &Expr) -> &Register { match expr { Expr::Binary(bin_expr) => self.bin_expr(bin_expr), Expr::Lit(lit) => match lit { @@ -94,7 +65,7 @@ impl<'a> CodeGen<'a> { } } - fn bin_expr(&mut self, expr: &ExprBinary) -> usize { + fn bin_expr(&mut self, expr: &ExprBinary) -> &Register { match &expr.op { BinOp::Assign => { let left = expr.left.as_ref(); @@ -106,7 +77,7 @@ impl<'a> CodeGen<'a> { self.mov(name, right); - 69 + todo!(); } else { panic!("Cant assign to non ident"); } @@ -154,27 +125,27 @@ impl<'a> CodeGen<'a> { } } - fn mov(&mut self, label: &str, r: usize) { + fn mov(&mut self, label: &str, r: &Register) { writedoc!( self.text_section, " \tmov [{}], {} ", &label, - &self.registers[r].name + r.dword(), ) .unwrap(); } - fn load(&mut self, int_lit: &IntLitRepr) -> usize { - let r = self.alloc(); + fn load(&mut self, int_lit: &IntLitRepr) -> &Register { + let r = self.registers.alloc().unwrap(); writedoc!( self.text_section, " \tmov {}, {} ", - &self.registers[r].name, + r.dword(), int_lit.to_string(), ) .unwrap(); @@ -182,7 +153,7 @@ impl<'a> CodeGen<'a> { r } - fn unary_expr(&mut self, unary_expr: &ExprUnary) -> usize { + fn unary_expr(&mut self, unary_expr: &ExprUnary) -> &Register { match unary_expr.op { UnOp::Negative => { let r = self.expr(unary_expr.expr.as_ref()); @@ -194,67 +165,67 @@ impl<'a> CodeGen<'a> { } } - fn negate(&mut self, r: usize) { + fn negate(&mut self, r: &Register) { writedoc!( self.text_section, " \tneg {} ", - &self.registers[r].name, + r.dword(), ) .unwrap(); } - fn add(&mut self, r1: usize, r2: usize) -> usize { + fn add(&mut self, r1: &Register, r2: &Register) -> &Register { writedoc!( self.text_section, " \tadd {}, {} ", - &self.registers[r1].name, - &self.registers[r2].name, + r1.dword(), + r2.dword(), ) .unwrap(); - self.free(r2); + self.registers.free(r2); r1 } - fn sub(&mut self, r1: usize, r2: usize) -> usize { + fn sub(&mut self, r1: &Register, r2: &Register) -> &Register { writedoc!( self.text_section, " \tsub {}, {} ", - &self.registers[r1].name, - &self.registers[r2].name, + r1.dword(), + r2.dword(), ) .unwrap(); - self.free(r2); + self.registers.free(r2); r1 } - fn mul(&mut self, r1: usize, r2: usize) -> usize { + fn mul(&mut self, r1: &Register, r2: &Register) -> &Register { writedoc!( self.text_section, " \timul {}, {} ", - &self.registers[r1].name, - &self.registers[r2].name, + r1.dword(), + r2.dword(), ) .unwrap(); - self.free(r2); + self.registers.free(r2); r1 } //NOTE: if mafs doesn't works, prolly because of this - fn div(&mut self, r1: usize, r2: usize) -> usize { + fn div(&mut self, r1: &Register, r2: &Register) -> &Register { writedoc!( self.text_section, " @@ -263,13 +234,13 @@ impl<'a> CodeGen<'a> { \tidiv {} \tmov {}, rax ", - &self.registers[r1].name, - &self.registers[r2].name, - &self.registers[r1].name, + r1.dword(), + r2.dword(), + r1.dword(), ) .unwrap(); - self.free(r2); + self.registers.free(r2); r1 } diff --git a/src/codegen/register.rs b/src/codegen/register.rs index 162e5b1..2358ddc 100644 --- a/src/codegen/register.rs +++ b/src/codegen/register.rs @@ -55,7 +55,7 @@ impl<'a> RegisterAllocator<'a> { Err(AllocatorError::RanOutOfRegisters) } - pub fn free(&mut self, r: &Register<'a>) -> Result<(), AllocatorError> { + pub fn free(&mut self, r: &Register) -> Result<(), AllocatorError> { for (i, register) in self.registers.iter().enumerate() { if r == register { if let RegisterStatus::Free = self.status[i] {