Merge branch 'feat/func-param'
This commit is contained in:
@@ -15,6 +15,7 @@ pub struct Generator {
|
||||
|
||||
const DEFAULT_VAR_ALIGN: usize = 4;
|
||||
|
||||
const ARG_REGS: [Register; 4] = [REG_R0, REG_R1, REG_R2, REG_R3];
|
||||
fn load_variable(variable: Variable, reg_allocator: &mut RegisterAllocator, var_index_to_stack_offset: &BTreeMap<usize, usize>, instrs: &mut Vec<ARMInstr>) -> RegisterAlloc {
|
||||
match variable.var_type {
|
||||
VariableType::Global => {
|
||||
@@ -27,8 +28,14 @@ fn load_variable(variable: Variable, reg_allocator: &mut RegisterAllocator, var_
|
||||
// }
|
||||
var_alloc
|
||||
},
|
||||
VariableType::ParamTemp => {
|
||||
todo!()
|
||||
VariableType::ParamTemp(param_index) => {
|
||||
if param_index < ARG_REGS.len() {
|
||||
let reg = ARG_REGS[param_index];
|
||||
let var_alloc = reg_allocator.alloc_reg(reg).expect("Ran out of registers");
|
||||
var_alloc
|
||||
} else {
|
||||
todo!("More than 4 parameters not supported yet");
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
let stack_offset = var_index_to_stack_offset.get(&variable.index).expect("Variable not declared");
|
||||
@@ -48,7 +55,7 @@ fn save_variable(variable: Variable, reg: Register, reg_allocator: &mut Register
|
||||
instrs.push(LoadPseudoInstr::new(address_alloc.reg, format!("global_var_{}", variable.index)));
|
||||
instrs.push(StoreInstr::new(reg, address_alloc.reg, None));
|
||||
},
|
||||
VariableType::ParamTemp => {
|
||||
VariableType::ParamTemp(_) => {
|
||||
todo!()
|
||||
},
|
||||
_ => {
|
||||
@@ -199,7 +206,6 @@ impl Generator {
|
||||
if args.len() > 4 {
|
||||
todo!("More than 4 arguments not supported yet");
|
||||
}
|
||||
const ARG_REGS: [Register; 4] = [REG_R0, REG_R1, REG_R2, REG_R3];
|
||||
let mut arg_reg_allocs = Vec::new();
|
||||
for (i, arg) in args.into_iter().enumerate() {
|
||||
arg_reg_allocs.push(self.register_allocator.alloc_reg(ARG_REGS[i]).expect("Ran out of registers"));
|
||||
|
||||
@@ -78,4 +78,8 @@ mod tests {
|
||||
fn test_if_while() {
|
||||
test_case("26-32,34-41,46-51,57");
|
||||
}
|
||||
#[test]
|
||||
fn test_func() {
|
||||
test_case("12-13,58-60");
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,9 @@ pub const REGISTERS: &[Register] = &[
|
||||
pub const REGISTERS_CAN_ALLOC: &[Register] = &[
|
||||
REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7, REG_R8, REG_R9, REG_R10, REG_R12
|
||||
];
|
||||
pub const REGISTERS_RESERVED: &[Register] = &[
|
||||
REG_R0, REG_R1, REG_R2, REG_R3
|
||||
];
|
||||
pub struct RegisterAlloc {
|
||||
allocator: Weak<RefCell<RegisterAllocatorInner>>,
|
||||
pub reg: Register,
|
||||
@@ -102,7 +105,17 @@ impl RegisterAllocator {
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
fn debug_use(&self) {
|
||||
let inner = self.inner.borrow();
|
||||
for (®, use_kind) in inner.register_map.iter() {
|
||||
match use_kind {
|
||||
RegisterUseKind::Designated => println!("{}: Designated", reg),
|
||||
RegisterUseKind::UsedByVariable(var) => println!("{}: UsedByVariable({})", reg, var),
|
||||
RegisterUseKind::AllocatedToVariable(var) => println!("{}: AllocatedToVariable({})", reg, var),
|
||||
RegisterUseKind::Free => println!("{}: Free", reg),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn alloc(&mut self, var: Variable) -> Option<RegisterAlloc> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
if let Some(®) = inner.variable_to_register.get(&var) {
|
||||
@@ -122,6 +135,9 @@ impl RegisterAllocator {
|
||||
// Find a free register
|
||||
for (®, use_kind) in inner.register_map.iter_mut() {
|
||||
// Find free register first
|
||||
if REGISTERS_RESERVED.contains(®) {
|
||||
continue;
|
||||
}
|
||||
if let RegisterUseKind::Free = use_kind {
|
||||
*use_kind = RegisterUseKind::UsedByVariable(var);
|
||||
inner.variable_to_register.insert(var, reg);
|
||||
@@ -135,6 +151,9 @@ impl RegisterAllocator {
|
||||
let RegisterAllocatorInner{register_map, variable_to_register} = &mut *inner;
|
||||
for (®, use_kind) in register_map.iter_mut() {
|
||||
// Find allocated register then
|
||||
if REGISTERS_RESERVED.contains(®) {
|
||||
continue;
|
||||
}
|
||||
if let RegisterUseKind::AllocatedToVariable(ori_var) = use_kind {
|
||||
assert!(variable_to_register.remove(&ori_var).is_some());
|
||||
*use_kind = RegisterUseKind::UsedByVariable(var);
|
||||
@@ -146,6 +165,8 @@ impl RegisterAllocator {
|
||||
});
|
||||
}
|
||||
}
|
||||
std::mem::drop(inner);
|
||||
self.debug_use();
|
||||
// No free register available
|
||||
None
|
||||
}
|
||||
@@ -164,6 +185,10 @@ impl RegisterAllocator {
|
||||
});
|
||||
},
|
||||
RegisterUseKind::UsedByVariable(_var) => {
|
||||
std::mem::drop(inner);
|
||||
|
||||
println!("{}", reg);
|
||||
self.debug_use();
|
||||
return None;
|
||||
},
|
||||
RegisterUseKind::AllocatedToVariable(var) => {
|
||||
@@ -176,6 +201,9 @@ impl RegisterAllocator {
|
||||
});
|
||||
},
|
||||
RegisterUseKind::Designated => {
|
||||
std::mem::drop(inner);
|
||||
println!("{}", reg);
|
||||
self.debug_use();
|
||||
return None;
|
||||
},
|
||||
}
|
||||
@@ -186,6 +214,9 @@ impl RegisterAllocator {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
|
||||
for (®, use_kind) in inner.register_map.iter_mut() {
|
||||
if REGISTERS_RESERVED.contains(®) {
|
||||
continue;
|
||||
}
|
||||
if let RegisterUseKind::Free = use_kind {
|
||||
*use_kind = RegisterUseKind::Designated;
|
||||
return Some(RegisterAlloc {
|
||||
@@ -197,6 +228,9 @@ impl RegisterAllocator {
|
||||
}
|
||||
let RegisterAllocatorInner{register_map, variable_to_register} = &mut *inner;
|
||||
for (®, use_kind) in register_map.iter_mut() {
|
||||
if REGISTERS_RESERVED.contains(®) {
|
||||
continue;
|
||||
}
|
||||
if let RegisterUseKind::AllocatedToVariable(ori_var) = use_kind {
|
||||
variable_to_register.remove(&ori_var);
|
||||
*use_kind = RegisterUseKind::Designated;
|
||||
@@ -207,7 +241,8 @@ impl RegisterAllocator {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::mem::drop(inner);
|
||||
self.debug_use();
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -1096,4 +1096,8 @@ mod tests {
|
||||
fn test_error() {
|
||||
test_case("999");
|
||||
}
|
||||
#[test]
|
||||
fn test_func() {
|
||||
test_case("12-13,58-60");
|
||||
}
|
||||
}
|
||||
|
||||
+14
-6
@@ -106,7 +106,9 @@ impl Generator {
|
||||
Ok(p) => p,
|
||||
Err(()) => return vec![],
|
||||
};
|
||||
let temp_parameters = parameters.iter().map(|param| self.var_manager.declare_param_temp(param.data_type)).collect::<Vec<_>>();
|
||||
let temp_parameters = parameters.iter().enumerate()
|
||||
.map(|(i, param)| self.var_manager.declare_param_temp(param.data_type, i))
|
||||
.collect::<Vec<_>>();
|
||||
let mut body_instrs = vec![];
|
||||
self.func_exit = Some((self.request_label(), {
|
||||
let ret_type = func_decl.return_type.into();
|
||||
@@ -118,14 +120,14 @@ impl Generator {
|
||||
}));
|
||||
let block_instrs = self.generate_block_stmt(func_decl.body);
|
||||
for var in self.var_manager.get_cur_func_variables() {
|
||||
if matches!(var.var_type, VariableType::ParamTemp) {
|
||||
if matches!(var.var_type, VariableType::ParamTemp(_)) {
|
||||
continue;
|
||||
}
|
||||
body_instrs.push(IRInstr::Declare(var));
|
||||
}
|
||||
body_instrs.push(IRInstr::Entry);
|
||||
parameters.iter().zip(temp_parameters.iter()).for_each(|(param, temp_param)| {
|
||||
body_instrs.push(IRInstr::Move(*temp_param, MoveRValue::Var(*param)));
|
||||
body_instrs.push(IRInstr::Move(*param, MoveRValue::Var(*temp_param)));
|
||||
});
|
||||
body_instrs.extend(block_instrs);
|
||||
let func_exit = self.func_exit.take().unwrap();
|
||||
@@ -140,7 +142,7 @@ impl Generator {
|
||||
return_type: func_decl.return_type.into(),
|
||||
};
|
||||
self.function_map.insert(func.name.clone(), func.clone());
|
||||
vec![IRInstr::DefineFunc(func, parameters, body_instrs)]
|
||||
vec![IRInstr::DefineFunc(func, temp_parameters, body_instrs)]
|
||||
}
|
||||
fn generate_block_stmt(&mut self, block_stmt: BlockStmt) -> Vec<IRInstr> {
|
||||
let mut instrs = vec![];
|
||||
@@ -633,7 +635,9 @@ impl Generator {
|
||||
return None;
|
||||
}
|
||||
for (i, arg) in args.into_iter().enumerate() {
|
||||
self.current_exit_label.push(None);
|
||||
let (arg_instrs, arg_var) = self.generate_expr(arg)?;
|
||||
self.current_exit_label.pop();
|
||||
let parameter_type = func_def.parameter_types.get(i).unwrap();
|
||||
if *parameter_type != arg_var.map_or(IRType::Void, |v| v.data_type) {
|
||||
self.diagnostic.add_from_ir_error(IRError::TypeMismatch(*parameter_type, arg_var.map_or(IRType::Void, |v| v.data_type)), expr.span);
|
||||
@@ -737,8 +741,8 @@ impl VariableManager {
|
||||
self.local_var_type.push(var);
|
||||
var
|
||||
}
|
||||
pub fn declare_param_temp(&mut self, var_data_type: IRType) -> Variable {
|
||||
let var = Variable { index: self.local_counter, var_type: VariableType::ParamTemp, data_type: var_data_type };
|
||||
pub fn declare_param_temp(&mut self, var_data_type: IRType, param_index: usize) -> Variable {
|
||||
let var = Variable { index: self.local_counter, var_type: VariableType::ParamTemp(param_index), data_type: var_data_type };
|
||||
self.local_counter += 1;
|
||||
self.local_var_type.push(var);
|
||||
var
|
||||
@@ -830,4 +834,8 @@ mod tests {
|
||||
fn test_if_while() {
|
||||
test_case("26-32,34-41,46-51,57");
|
||||
}
|
||||
#[test]
|
||||
fn test_func() {
|
||||
test_case("12-13,58-60");
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -116,7 +116,7 @@ impl Display for MoveRValue {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub enum VariableType {
|
||||
Global,
|
||||
ParamTemp,
|
||||
ParamTemp(usize),
|
||||
Local,
|
||||
Temp,
|
||||
}
|
||||
@@ -155,7 +155,7 @@ impl Display for Variable {
|
||||
VariableType::Global => "@g",
|
||||
VariableType::Local => "%l",
|
||||
VariableType::Temp => "%t",
|
||||
VariableType::ParamTemp => "%t",
|
||||
VariableType::ParamTemp(_) => "%t",
|
||||
};
|
||||
write!(f, "{}{}", prefix, self.index)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user