gcrecomp_core/recompiler/codegen/register.rs
1//! Register Allocation
2//!
3//! This module provides register allocation for code generation, mapping PowerPC registers
4//! to Rust variables. In a full implementation, this would use graph coloring or linear scan
5//! algorithms for optimal register allocation.
6//!
7//! # Memory Optimizations
8//! - Uses `HashMap` for register mapping (efficient lookup)
9//! - String interning could be added for repeated register names
10//!
11//! # Allocation Strategy
12//! Currently uses a simple mapping strategy. A full implementation would:
13//! - Use graph coloring to minimize register pressure
14//! - Implement register spilling when registers are exhausted
15//! - Track register liveness to optimize allocation
16
17use std::collections::HashMap;
18
19/// Register allocator for mapping PowerPC registers to Rust variables.
20///
21/// Maps PowerPC general-purpose registers (r0-r31) to Rust variable names.
22/// In a full implementation, would use graph coloring or linear scan algorithms.
23pub struct RegisterAllocator {
24 /// Map from PowerPC register number to Rust variable name
25 register_map: HashMap<u8, String>,
26 /// Next temporary variable number (for unique variable names)
27 next_temp: usize,
28 /// List of spilled registers (registers moved to stack)
29 spilled_registers: Vec<u8>,
30}
31
32impl RegisterAllocator {
33 /// Create a new register allocator.
34 ///
35 /// # Returns
36 /// `RegisterAllocator` - New register allocator instance
37 ///
38 /// # Examples
39 /// ```rust
40 /// let mut allocator = RegisterAllocator::new();
41 /// ```
42 #[inline] // Constructor - simple, may be inlined
43 pub fn new() -> Self {
44 Self {
45 register_map: HashMap::new(),
46 next_temp: 0usize,
47 spilled_registers: Vec::new(),
48 }
49 }
50
51 /// Allocate a Rust variable name for a PowerPC register.
52 ///
53 /// # Algorithm
54 /// Maps PowerPC register to Rust variable name. If register hasn't been allocated,
55 /// creates a new variable name. Otherwise, returns existing variable name.
56 ///
57 /// # Arguments
58 /// * `ppc_reg` - PowerPC register number (0-31)
59 ///
60 /// # Returns
61 /// `String` - Rust variable name for the register
62 ///
63 /// # Examples
64 /// ```rust
65 /// let var_name = allocator.allocate_register(3); // Returns "r3"
66 /// ```
67 #[inline] // Hot path - may be inlined
68 pub fn allocate_register(&mut self, ppc_reg: u8) -> String {
69 // Map PowerPC register to Rust variable
70 // In a full implementation, would use graph coloring or linear scan
71 self.register_map
72 .entry(ppc_reg)
73 .or_insert_with(|| {
74 let name: String = format!("r{}", ppc_reg);
75 self.next_temp = self.next_temp.wrapping_add(1);
76 name
77 })
78 .clone()
79 }
80
81 /// Spill a register to the stack.
82 ///
83 /// # Algorithm
84 /// When registers are exhausted, spill a register to stack memory.
85 /// Returns a stack variable name for the spilled register.
86 ///
87 /// # Arguments
88 /// * `reg` - PowerPC register number to spill
89 ///
90 /// # Returns
91 /// `String` - Stack variable name for the spilled register
92 ///
93 /// # Examples
94 /// ```rust
95 /// let stack_var = allocator.spill_register(3); // Returns "spilled_r3"
96 /// ```
97 #[inline] // May be called frequently
98 pub fn spill_register(&mut self, reg: u8) -> String {
99 // Spill register to stack
100 let stack_var: String = format!("spilled_r{}", reg);
101 self.spilled_registers.push(reg);
102 stack_var
103 }
104}
105
106impl Default for RegisterAllocator {
107 #[inline] // Simple default implementation
108 fn default() -> Self {
109 Self::new()
110 }
111}