From 828f5bfb2d861a5f40e206e6f263ee52c911ac96 Mon Sep 17 00:00:00 2001 From: zxq5 Date: Sun, 8 Feb 2026 11:45:26 +0000 Subject: [PATCH] fixed pointers and stuff. --- compiler/src/backend/dsa/codegen.rs | 36 +++---- compiler/src/backend/dsa/registers.rs | 139 +++++++++++++++----------- 2 files changed, 102 insertions(+), 73 deletions(-) diff --git a/compiler/src/backend/dsa/codegen.rs b/compiler/src/backend/dsa/codegen.rs index 680f9ad..3072ade 100644 --- a/compiler/src/backend/dsa/codegen.rs +++ b/compiler/src/backend/dsa/codegen.rs @@ -245,7 +245,7 @@ impl CodeGenerator { code.extend(store_code); // Free temporary register - self.allocator.free_temp(&result_reg); + self.allocator.free_temp(result_reg); } else { // Just declaring variable without initialization self.allocator.alloc_var(&var.name)?; @@ -267,8 +267,8 @@ impl CodeGenerator { code.push(format!("\tstw {}, {}", result_reg, ptr_reg)); - self.allocator.free_temp(&result_reg); - self.allocator.free_temp(&ptr_reg); + self.allocator.free_temp(result_reg); + self.allocator.free_temp(ptr_reg); } Statement::Assign { varname, value } => { @@ -288,7 +288,7 @@ impl CodeGenerator { } // Free temporary register - self.allocator.free_temp(&result_reg); + self.allocator.free_temp(result_reg); } Statement::Return(expr) => { @@ -298,7 +298,7 @@ impl CodeGenerator { code.extend(expr_code); code.push(format!("\tstw {}, bpr, 8", result_reg)); code.push(format!("\tjmp _ret")); - self.allocator.free_temp(&result_reg); + self.allocator.free_temp(result_reg); } } @@ -314,7 +314,7 @@ impl CodeGenerator { // Compare with zero code.push(format!("\tcmp {}, zero", cond_reg)); - self.allocator.free_temp(&cond_reg); + self.allocator.free_temp(cond_reg); // Generate unique labels let then_label = format!("_then_{}", self.get_unique_label()); @@ -361,7 +361,7 @@ impl CodeGenerator { code.extend(cond_code); code.push(format!("\tcmp {}, zero", cond_reg)); - self.allocator.free_temp(&cond_reg); + self.allocator.free_temp(cond_reg); code.push(format!("\tjeq {}", loop_end)); @@ -390,7 +390,7 @@ impl CodeGenerator { let (result_reg, expr_code) = self.generate_expression(expr, false, func_body)?; code.extend(expr_code); - self.allocator.free_temp(&result_reg); + self.allocator.free_temp(result_reg); } Statement::Block(statements) => { @@ -562,8 +562,8 @@ impl CodeGenerator { } // Free operand registers (allocator will protect variables) - self.allocator.free_temp(&left_reg); - self.allocator.free_temp(&right_reg); + self.allocator.free_temp(left_reg); + self.allocator.free_temp(right_reg); Ok((result_reg, code)) } @@ -592,7 +592,7 @@ impl CodeGenerator { let saved_regs = self.allocator.get_caller_saved_registers(); for reg in &saved_regs { // spill variables to stack - code.extend(self.allocator.free_register(reg).unwrap()); + code.extend(self.allocator.free_register(reg).unwrap().1); } // Evaluate and push arguments in reverse order @@ -651,7 +651,7 @@ impl CodeGenerator { // Free argument registers for reg in arg_regs { - self.allocator.free_temp(®); + self.allocator.free_temp(reg); } Ok((result_reg, code)) @@ -678,16 +678,18 @@ impl CodeGenerator { code.push(format!("\tldw {}, {}", operand_reg, result_reg)); } UnaryOperator::Reference => { - code.extend(self.allocator.spill_register(&operand_reg)?); + let (offset, alloc_code) = + self.allocator.free_register(&operand_reg)?; + code.extend(alloc_code); code.push(format!( - "\tsubi bpr {} {}", - -(4 + self.allocator.get_stack_offset()), + "\taddi spr, {}, {}", + offset - self.allocator.get_stack_offset(), result_reg - )) + )); } } - self.allocator.free_temp(&operand_reg); + self.allocator.free_temp(operand_reg); Ok((result_reg, code)) } diff --git a/compiler/src/backend/dsa/registers.rs b/compiler/src/backend/dsa/registers.rs index 3e3453b..abf5df3 100644 --- a/compiler/src/backend/dsa/registers.rs +++ b/compiler/src/backend/dsa/registers.rs @@ -82,7 +82,7 @@ impl RegisterAllocator { pub fn alloc_temp(&mut self) -> Result<(Register, Vec), CompilerError> { // Try to find an unused register - println!("finding! {:#?}", self.in_use); + // println!("finding! {:#?}", self.in_use); if let Some(reg) = self.find_free_register() { self.in_use.insert(reg, true); @@ -116,25 +116,33 @@ impl RegisterAllocator { )) } + // fn set_in_use(&mut self, reg: Register, in_use: bool) { + // self.in_use[reg as usize].1 = in_use; + // } + /// Free a temporary register after use /// NOTE: This will NOT free registers that contain variables! /// Variables persist throughout their scope and must not be freed - pub fn free_temp(&mut self, reg: &Register) { + pub fn free_temp(&mut self, reg: Register) { // Check if this register contains a variable - if self.register_contents.contains_key(reg) { + if self.register_contents.contains_key(®) { // This register holds a variable - don't free it! // Variables are only freed when they go out of scope via free_var() return; } // This is a true temporary - safe to free - self.in_use.insert(*reg, false); + if reg != Register::Zero { + self.in_use.insert(reg, false); + } } pub fn free_var(&mut self, var: &str) { // Check if this variable is in a register if let Some(location) = self.variable_locations.get(var).cloned() { - if let Some(reg) = location.register { + if let Some(reg) = location.register + && reg != Register::Zero + { self.register_contents.remove(®); self.in_use.insert(reg, false); } @@ -165,12 +173,12 @@ impl RegisterAllocator { location.register = Some(reg); // Load from bpr + offset (offset is negative) - code.push(format!("\tsubi bpr {} {}", -(offset + 4), reg)); + // code.push(format!("\tsubi bpr {} {}", -(offset + 4), reg)); code.push(format!( - "\tldw {}, {} // bpr{}: {}", + "\tldw spr, {}, {} // spr+{}: {}", reg, - reg, - offset - 4, + offset - self.stack_offset, + offset - self.stack_offset, var_name )); @@ -217,8 +225,8 @@ impl RegisterAllocator { if let Some(reg) = location.register { if reg == *source_reg { return vec![format!( - "\tmov {}, {} // var {}", - source_reg, reg, var_name + "\tmov {}, {} // save var:{} reg:{}", + source_reg, reg, var_name, reg )]; } } @@ -226,8 +234,11 @@ impl RegisterAllocator { // if the variable exists on the stack but not a register we write here. if let Some(offset) = location.stack { return vec![format!( - "\tstw {}, bpr, {} // var {}", - source_reg, offset, var_name + "\tstw {}, spr, {} // save var:{} offset:{}", + source_reg, + offset - self.stack_offset, + var_name, + offset )]; } } @@ -268,7 +279,8 @@ impl RegisterAllocator { } /// spill a register to the stack (WITHOUT FREEING) - pub fn spill_register( + /// DO NOT USE this if it's for a pointer!!!! + pub fn _spill_register( &mut self, reg: &Register, ) -> Result, CompilerError> { @@ -281,22 +293,31 @@ impl RegisterAllocator { // check if var is on the stack if let Some(offset) = location.stack { // ensure stack value is up to date with register value. - code.push(format!("\tstw {}, {}", reg, offset)); + code.push(format!( + "\tstw {}, spr, {} // save var:{} offset:{}", + reg, + offset - self.stack_offset, + var_name, + offset + )); return Ok(code); } - // if the variable is not on the stack: - // push register to stack (spr decrements automatically) - code.push(format!( - "\tpush {} // bpr{}: {}", - reg, self.stack_offset, var_name - )); - // Track that we pushed one word self.stack_offset -= 4; + + // if the variable is not on the stack: + // push register to stack (spr decrements automatically) + let offset = self.stack_offset; + code.push(format!( + "\tpush {} // free var:{} offset:{}", + reg, var_name, offset + )); + // Update variable location - it's now at current spr // Note: We track offset from bpr for consistency - location.stack = Some(self.stack_offset); + location.stack = Some(offset); + Ok(code) } else { Err(CompilerError::Generic(format!( @@ -311,7 +332,7 @@ impl RegisterAllocator { pub fn free_register( &mut self, reg: &Register, - ) -> Result, CompilerError> { + ) -> Result<(i32, Vec), CompilerError> { let mut code = Vec::new(); // check if the variable is declared. @@ -321,30 +342,36 @@ impl RegisterAllocator { // check if var name is on the stack if let Some(offset) = location.stack { // store current register value in stack location - code.push(format!("\tstw {}, {}", reg, offset)); + code.push(format!( + "\tstw {}, spr, {} // save var:{} offset:{}", + reg, + offset - self.stack_offset, + var_name, + offset + )); // free the register. location.register = None; self.register_contents.remove(reg); - return Ok(code); + return Ok((offset, code)); } - // if the variable is not on the stack: - // push register to stack (spr decrements automatically) - code.push(format!( - "\tpush {} // bpr{}: {}", - reg, self.stack_offset, var_name - )); - // Track that we pushed one word self.stack_offset -= 4; - // Update variable location - it's now at current spr + + let offset = self.stack_offset; + code.push(format!( + "\tpush {} // free var:{} offset:{}", + reg, var_name, offset + )); + + // Update variable location // Note: We track offset from bpr for consistency - location.stack = Some(self.stack_offset); + location.stack = Some(offset); location.register = None; self.register_contents.remove(reg); - Ok(code) + Ok((offset, code)) } else { Err(CompilerError::Generic(format!( "Register {} does not contain a variable to spill!", @@ -357,7 +384,7 @@ impl RegisterAllocator { fn find_free_register(&self) -> Option { self.in_use .iter() - .filter(|(_, in_use)| !**in_use) + .filter(|(_, in_use)| !*in_use) .map(|(reg, _)| *reg) .next() } @@ -371,7 +398,7 @@ impl RegisterAllocator { for reg in regs_to_spill { if let Ok(spill_code) = self.free_register(®) { - code.extend(spill_code); + code.extend(spill_code.1); } } @@ -469,24 +496,24 @@ impl RegisterAllocator { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Register { - Rg0, - Rg1, - Rg2, - Rg3, - Rg4, - Rg5, - Rg6, - Rg7, - Rg8, - Rg9, - Rga, - Rgb, - Rgc, - Rgd, - Rge, - Rgf, - Zero, - Null, + Rg0 = 0, + Rg1 = 1, + Rg2 = 2, + Rg3 = 3, + Rg4 = 4, + Rg5 = 5, + Rg6 = 6, + Rg7 = 7, + Rg8 = 8, + Rg9 = 9, + Rga = 10, + Rgb = 11, + Rgc = 12, + Rgd = 13, + Rge = 14, + Rgf = 15, + Zero = 16, + Null = 17, } impl fmt::Display for Register {